-
Notifications
You must be signed in to change notification settings - Fork 74
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
Output placeholder image as data URI #16
Conversation
Nice, thanks!
|
I just tried the suggested solution in the updated README, adding a base64 encoded small image to I don't know if it's out of scope for this plugin to recommend how to actually use the placeholders, but it would be nice :) |
Sorry, I realize I've been lagging very behind. I'll finish this before the week is up. @oscar-b As for the placeholder image, you're right and the README needs changing.
|
@alex-ketch That's a nice way of doing it, never seen that before! I'm trying to figure out if it's feasible to use with responsive images though, since the |
That's why I think we should add width and height information to the loader output, so you can calculate the proper aspect ratio and set the dimensions on the image. |
Yes that would be very useful. |
@herrstucki So this is what I'm thinking:
Also regarding:
I don't think full featured settings are necessary for the placeholder images, but open to be convinced otherwise. As those images are ~1KB at 40px wide, but if settings shave off significant bytes, then sure. |
@alex-ketch Yeah, let's go for it! 👍 Very exciting. I was thinking of compiling some links to articles about different techniques of using placeholders too. Actually, @lnhrdt has already added I probably wouldn't add more "convenience" output to the loader, since people may have different use cases (e.g. use the placeholder in canvas or svg). And how would that work in CSS? |
@alex-ketch Do you have any eta for this PR? Eagerly awaiting it :) |
@oscar-b Sorry for the delays, but I believe this should be it! Would appreciate extra 👀 |
@alex-ketch I'm currently on vacation and won't be able to review/publish for at least a week. I've made you a collaborator in case you want to move more quickly 👍 |
@@ -62,7 +73,9 @@ module.exports = { | |||
]} | |||
}, | |||
responsiveLoader: { | |||
sizes: [300, 600, 1200, 2000] | |||
sizes: [300, 600, 1200, 2000], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
webpack 2 doesn't allow this, options should be passed to the plugin afaik.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't really worked with v2 much and will leave updating documentation to someone more knowledgable. We would need to show examples for both versions, as webpack 2 isn't officially out yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically this, but yeah it's probably for another PR: https://webpack.js.org/how-to/upgrade-from-webpack-1/#loaderoptionplugin-context
@@ -38,13 +38,24 @@ Or use it in CSS (only the first resized image will be used, if you use multiple | |||
} | |||
``` | |||
|
|||
```js | |||
// Outputs placeholder image as a data URI, and three images with 100, 200, and 300px widths | |||
const responsiveImage = require('responsive?placeholder=true&sizes[]=100,sizes[]=200,sizes[]=300!myImage.jpg'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe an example using import
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the syntax for using query configuration with import
? Is it the same?
Otherwise I'd rather keep this consistent with the rest of the examples, and create them with the Webpack v2 documentation update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes sounds reasonable :)
const srcset = files.map(f => f.src).join('+","+'); | ||
|
||
const images = files.map(f => '{path:' + f.path + ',width:' + f.width + ',height:' + f.height + '}').join(','); | ||
|
||
const firstImagePath = files[0].path; | ||
|
||
loaderCallback(null, 'module.exports = {srcSet:' + srcset + ',images:[' + images + '],src:' + firstImagePath + ',toString:function(){return ' + firstImagePath + '}};'); | ||
loaderCallback(null, 'module.exports = {' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't width
and height
missing here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, still too jet lagged. I've added the original image dimensions to the output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be the dimensions of the first resized image to align it with src
and toString()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that would make sense, wouldn't it 😅
Will update
const responsiveImage = require('responsive?placeholder=true&sizes[]=100,sizes[]=200,sizes[]=300!myImage.jpg'); | ||
|
||
// responsiveImage.placeholder => 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAIBAQE…' | ||
React.render(<img src={responsiveImage.src} srcSet={responsiveImage.srcSet} style={{height: responsiveImage.height, width: responsiveImage.width, backgroundImage: 'url("' + responsiveImage.placeholder + '")'}} />, el); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need a background-size: cover
in here as well, no?
I will try to test it in my environment asap, but looks good to me. |
@alex-ketch This seems quite solid, I haven't had any problems using it at all. Nice work! |
And fwiw the following works for ES6 style imports: import topImage from 'responsive?placeholder=true,sizes[]=500w,sizes[]=1000w!./images/about-us.jpg'; |
const srcset = files.map(f => f.src).join('+","+'); | ||
|
||
const images = files.map(f => '{path:' + f.path + ',width:' + f.width + ',height:' + f.height + '}').join(','); | ||
|
||
const firstImagePath = files[0].path; | ||
|
||
loaderCallback(null, 'module.exports = {srcSet:' + srcset + ',images:[' + images + '],src:' + firstImagePath + ',toString:function(){return ' + firstImagePath + '}};'); | ||
loaderCallback(null, 'module.exports = {' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be the dimensions of the first resized image to align it with src
and toString()
?
return q.awaitAll((queueErr, files) => { | ||
'use strict'; // eslint-disable-line |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is 'use strict' necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe I was getting the following error in older versions of node, complaining about use of const
and let
, which is why I added it.
SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But not with node >= 4, no? If we want to support older versions (I don't really 😁 ), we should add tests for those too in travis.yml
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought so too, but it was failing with v4 and v5, only passed with v6.
Let me look into this a bit more...
@alex-ketch thank you so much for the outstanding work and @oscar-b for reviewing and battle-testing! I added two more tiny comments but otherwise I think it's good to go. I'll leave the honor of merging to you 😄 If you'd like I can also give you npm publish rights too (I'll need your username though). |
Just a quick heads up; I'm having difficulties displaying the base64 encoded placeholder image as a background-image in Safari. Don't know why yet. Found some info that Safari doesn't display progressive JPEGs correctly when used as backgrounds, not sure how Jimp handles that (if the original is progressive, will the base64 also be progressive?). |
It wasn't the progressive part, it was using background-image on a |
Thanks for bring this to a close @herrstucki, I'll update the Readme today to update mention not setting placeholder image as a background on an |
@herrstucki All clear to merge this? |
@alex-ketch done and released in |
Hello again!
I know I said I'd make a PR for how file extensions are handled, but needed this first :)
This PR outputs a placeholder image as a data uri to save network requests, addressing issue #4.
The size of the placeholder image can be configured with a
placeholderWidth
option, but defaults to 40px wide.@herrstucki If you have a moment, I would appreciate some extra eyes to ensure things make sense please. In particular this line, where I check if the output width equals placeholder with, then don't write the file but output as data uri instead.
The potential problem with this is if someone wants to actually write out a file at the placeholder width size.
A solution could be to add a flag to
resizeImage()
specifying whether the file should be written or not.To Do: