-
Notifications
You must be signed in to change notification settings - Fork 91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How would one dynamically inline an image based on a prop? #235
Comments
Same problem. Any solution? |
You need to use babel compiler for replace param of image at the place of the component call
var babelParser = require('@babel/parser')
const nestedVisitor = {
StringLiteral(path, opts) {
try{
var pathFile = path.node.value;
if(pathFile && /\_\_load\_images\_\_/g.test(pathFile)){
console.log('optimize image', pathFile)
var newPath = pathFile.replace('__load_images__', ''),
originPath = newPath;
var pathRequest = newPath.match(/\?.*/g);
if(pathRequest){
pathRequest = pathRequest[0];
newPath = newPath.replace(pathRequest, '')
}
if( !newPath ) return match;
var resizeMode = pathRequest && /\\?resize/.test(pathRequest),
webpMode = pathRequest && /\\?webp/.test(pathRequest),
images = [], imagesString = '[';
if(resizeMode){
images.push(`require('public/static/${newPath}?resize&format=webp')`)
if(/\.png/g.test(newPath)){
images.push(`require('public/static/${newPath}?resize&format=png')`);
}
if(/\.jpg/g.test(newPath)){
images.push(`require('public/static/${newPath}?resize&format=jpg')`);
}
}
if(webpMode){
images.push(`{path: require('public/static/${newPath}?webp')}`)
images.push(`{path: require('public/static/${newPath}')}`)
}
if(!webpMode && !resizeMode){
images.push(`{path: require('public/static/${originPath}')}`)
}
for(var item of images){
imagesString += item + ','
}
imagesString += ']';
var node = babelParser.parse(imagesString)
path.replaceWith(
node.program.body[0]
);
}
}catch(err){
console.log('err', err)
}
}
}
const nestedVisitor2 = {
JSXExpressionContainer(path, opts){
path.traverse(nestedVisitor, opts);
}
}
module.exports = function({ types: t }) {
return {
visitor: {
JSXAttribute(path) {
path.traverse(nestedVisitor2, t);
}
}
};
} then apply plugin in require('dotenv').config();
var DEV_VAR = process.env.DEV_VAR == 'true' ? false : true;
module.exports = function (api) {
api.cache(DEV_VAR);
return {
presets: [
["next/babel"]
],
"plugins": [
["./babel-plugin-replace-path-images.js"]
]
}
}
My realization of image wrapper component - import { Component } from 'react';
class Img extends Component {
componentDidMount() {
if (this.img.complete) {
this.img.style.background = 'initial';
}
}
render() {
return(
<img
ref={el => this.img = el}
onLoad={ e => {
e.target.style.background = 'initial'
}}
{...this.props}
/>
)
}
}
const Image = (props) => {
if(!props.src) return null;
var newProps = JSON.parse(JSON.stringify(props))
var images = [], image, placeholder, addExtra = false;
for(var item of props.src){
if(item.images){
if(!addExtra){
addExtra = true;
image = item.image;
placeholder = item.placeholder;
}
for(var item2 of item.images){
images.push(item2)
}
}else{
images.push(item)
}
}
var reversed = images.reverse();
delete newProps.src;
delete newProps.require;
delete newProps.priority;
if(placeholder){
newProps.style = {background: `url(${placeholder})`}
}
if(!props.priority){
newProps.loading = "lazy"
}
return(
<picture>
{reversed.map(item => {
var sourceProps = {
srcSet: item.path,
type: 'image/'
}
if(/(\.png|data\:image\/png\;base64)/g.test(item.path)){
sourceProps.type += 'png'
}else if(/(\.webp|data\:image\/webp\;base64)/g.test(item.path)){
sourceProps.type += 'webp'
}else if(/(\.jpg|data\:image\/jpg\;base64)/g.test(item.path)){
sourceProps.type += 'jpeg'
}else{
delete sourceProps.type;
}
if(item.width){
sourceProps.media = `(min-width: ${item.width - 10}px)`
}
return(
<source {...sourceProps} />
)
})}
<Img
src={image}
{...newProps}
/>
</picture>
)
};
export default Image; finally example how you can use it <Image draggable="false" src={"__load_images__happyDeveloper.png?resize"} alt="Счастливый разработчик" /> |
is there a easy solution to this ? the answer is not so clear to me |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is my Image wrapper. I would like to inline above-the-fold images so they don't pop in. I can't pass the prop in - it doesn't work.
Here's the structure I have:
Here's what I would like to have:
The text was updated successfully, but these errors were encountered: