1 | # responsive-loader
|
2 |
|
3 | [![build][travis]][travis-url]
|
4 | [![npm][npm]][npm-url]
|
5 | [![node][node]][node-url]
|
6 | [![deps][deps]][deps-url]
|
7 | [![size][size]][size-url]
|
8 |
|
9 | A webpack loader for responsive images. Creates multiple images from one source image, and returns a `srcset`. For more information on how to use `srcset`, read [Responsive Images](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images). Browser support is [pretty good](http://caniuse.com/#search=srcset).
|
10 |
|
11 | ## Install
|
12 |
|
13 | > Note: starting with v1.0.0, responsive-loader is only compatible with webpack 2+. For webpack 1 support, use responsive-loader@0.7.0
|
14 |
|
15 | ### With jimp
|
16 |
|
17 | ```
|
18 | npm install responsive-loader jimp --save-dev
|
19 | ```
|
20 |
|
21 | Per default, responsive-loader uses [jimp](https://github.com/oliver-moran/jimp) to transform images. which needs to be installed alongside responsive-loader. Because jimp is written entirely in JavaScript and doesn't have any native dependencies it will work anywhere. The main drawback is that it's pretty slow.
|
22 |
|
23 | ### With sharp
|
24 |
|
25 | ```
|
26 | npm install responsive-loader sharp --save-dev
|
27 | ```
|
28 |
|
29 | For [super-charged performance](http://sharp.dimens.io/en/stable/performance/), responsive-loader also works with [sharp](https://github.com/lovell/sharp). It's recommended to use sharp if you have lots of images to transform, and need to generate webp images.
|
30 |
|
31 | If you want to use sharp, you need to configure responsive-loader to use its adapter:
|
32 |
|
33 | ```diff
|
34 | module.exports = {
|
35 | // ...
|
36 | module: {
|
37 | rules: [
|
38 | {
|
39 | test: /\.(jpe?g|png|webp)$/i,
|
40 | use: [
|
41 | loader: 'responsive-loader',
|
42 | options: {
|
43 | + adapter: require('responsive-loader/sharp')
|
44 | }
|
45 | ]
|
46 | }
|
47 | ]
|
48 | },
|
49 | }
|
50 | ```
|
51 |
|
52 |
|
53 | ## Usage
|
54 |
|
55 | Add a rule for loading responsive images to your webpack config:
|
56 |
|
57 | ```js
|
58 | module.exports = {
|
59 | // ...
|
60 | module: {
|
61 | rules: [
|
62 | {
|
63 | test: /\.(jpe?g|png|webp)$/i,
|
64 | use: [
|
65 | loader: 'responsive-loader',
|
66 | options: {
|
67 | // If you want to enable sharp support:
|
68 | adapter: require('responsive-loader/sharp'),
|
69 | }
|
70 | ]
|
71 | }
|
72 | ]
|
73 | },
|
74 | }
|
75 | ```
|
76 |
|
77 | Then import images in your JavaScript files:
|
78 |
|
79 | ```js
|
80 | import responsiveImage from 'img/myImage.jpg?sizes[]=300,sizes[]=600,sizes[]=1024,sizes[]=2048';
|
81 | import responsiveImageWebp from 'img/myImage.jpg?sizes[]=300,sizes[]=600,sizes[]=1024,sizes[]=2048&format=webp';
|
82 | // or ... require('img/myImage.jpg?sizes[]=300,sizes[]=600,sizes[]=1024,sizes[]=2048')
|
83 |
|
84 | // Outputs
|
85 | // responsiveImage.srcSet => '2fefae46cb857bc750fa5e5eed4a0cde-300.jpg 300w,2fefae46cb857bc750fa5e5eed4a0cde-600.jpg 600w,2fefae46cb857bc750fa5e5eed4a0cde-600.jpg 600w ...'
|
86 | // responsiveImage.images => [{height: 150, path: '2fefae46cb857bc750fa5e5eed4a0cde-300.jpg', width: 300}, {height: 300, path: '2fefae46cb857bc750fa5e5eed4a0cde-600.jpg', width: 600} ...]
|
87 | // responsiveImage.src => '2fefae46cb857bc750fa5e5eed4a0cde-300.jpg'
|
88 | // responsiveImage.toString() => '2fefae46cb857bc750fa5e5eed4a0cde-300.jpg'
|
89 | ...
|
90 | <picture>
|
91 | <source srcSet={responsiveImageWebp.srcSet} type='image/webp' />
|
92 | <img
|
93 | src={responsiveImage.src}
|
94 | srcSet={responsiveImage.srcSet}
|
95 | width={responsiveImage.width}
|
96 | height={responsiveImage.height}
|
97 | sizes='(min-width: 1024px) 1024px, 100vw'
|
98 | loading="lazy"
|
99 | />
|
100 | </picture>
|
101 | ```
|
102 |
|
103 | Notes:
|
104 | - `width` and `height` are intrinsic and are used to avoid layout shift, other techniques involve the use of aspect ratio and padding.
|
105 | - `sizes`, without sizes, the browser assumes the image is always 100vw for any viewport.
|
106 | - A helpful tool to determine proper sizes https://ausi.github.io/respimagelint/
|
107 | - `loading` do not add loading lazy if the image is part of the initial rendering of the page or close to it.
|
108 | - `srcset` Modern browsers will choose the closest best image depending on the pixel density of your screen.
|
109 | - in the example above is your pixel density is `>1x` for a screen `>1024px` it will display the 2048 image.
|
110 |
|
111 |
|
112 |
|
113 | Or use it in CSS (only the first resized image will be used, if you use multiple `sizes`):
|
114 |
|
115 | ```css
|
116 | .myImage { background: url('myImage.jpg?size=1140'); }
|
117 |
|
118 | @media (max-width: 480px) {
|
119 | .myImage { background: url('myImage.jpg?size=480'); }
|
120 | }
|
121 | ```
|
122 |
|
123 | ```js
|
124 | // Outputs placeholder image as a data URI, and three images with 100, 200, and 300px widths
|
125 | const responsiveImage = require('myImage.jpg?placeholder=true&sizes[]=100,sizes[]=200,sizes[]=300');
|
126 |
|
127 | // responsiveImage.placeholder => 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAIBAQE…'
|
128 | ReactDOM.render(
|
129 | <div style={{
|
130 | height: responsiveImage.height,
|
131 | width: responsiveImage.width,
|
132 | backgroundSize: 'cover',
|
133 | backgroundImage: 'url("' + responsiveImage.placeholder + '")'
|
134 | }}>
|
135 | <img src={responsiveImage.src} srcSet={responsiveImage.srcSet} />
|
136 | </div>, el);
|
137 | ```
|
138 |
|
139 |
|
140 | ### Options
|
141 |
|
142 | | Option | Type | Default | Description |
|
143 | | --------------------------- | ------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
144 | | `name` | `string` | `[hash]-[width].[ext]` | Filename template for output files. |
|
145 | | `outputPath` | `string | Function` | `undefined` | Configure a custom output path for your file |
|
146 | | `publicPath` | `string | Function` | `undefined` | Configure a custom public path for your file. |
|
147 | | `context` | `string` | `this.options.context` | Custom file context, defaults to webpack.config.js [context](https://webpack.js.org/configuration/entry-context/#context) |
|
148 | | `sizes` | `array` | *original size* | Specify all widths you want to use; if a specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up). You may also declare a default `sizes` array in the loader options in your `webpack.config.js`. |
|
149 | | `size` | `integer` | *original size* | Specify one width you want to use; if the specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up) |
|
150 | | `min` | `integer` | | As an alternative to manually specifying `sizes`, you can specify `min`, `max` and `steps`, and the sizes will be generated for you. |
|
151 | | `max` | `integer` | | See `min` above |
|
152 | | `steps` | `integer` | `4` | Configure the number of images generated between `min` and `max` (inclusive) |
|
153 | | `quality` | `integer` | `85` | JPEG and WEBP compression quality |
|
154 | | `format` | `string` | *original format* | Either `png` or `jpg`; use to convert to another format. `webp` is also supported, but only by the sharp adapter |
|
155 | | `placeholder` | `boolean` | `false` | A true or false value to specify wether to output a placeholder image as a data URI |
|
156 | | `placeholderSize` | `integer` | `40` | A number value specifying the width of the placeholder image, if enabled with the option above |
|
157 | | `adapter` | `Adapter` | JIMP | Specify which adapter to use. Can only be specified in the loader options. |
|
158 | | `disable` | `boolean` | `false` | Disable processing of images by this loader (useful in development). `srcSet` and other attributes will still be generated but only for the original size. Note that the `width` and `height` attributes will both be set to `100` but the image will retain its original dimensions. |
|
159 | | **[`esModule`](#esmodule)** | `{Boolean}` | `false` | Use ES modules syntax. |
|
160 |
|
161 | #### Adapter-specific options
|
162 |
|
163 | ##### jimp
|
164 |
|
165 | - `background: number` — Background fill when converting transparent to opaque images. Make sure this is a valid hex number, e.g. `0xFFFFFFFF`)
|
166 |
|
167 | ##### sharp
|
168 |
|
169 | - `background: string` — Background fill when converting transparent to opaque images. E.g. `#FFFFFF`
|
170 |
|
171 | - `format: webp` — Conversion to the `image/webp` format. Recognizes the `quality` option.
|
172 |
|
173 |
|
174 | ### Examples
|
175 |
|
176 | Set a default `sizes` array, so you don't have to declare them with each `require`.
|
177 |
|
178 | ```js
|
179 | module.exports = {
|
180 | entry: {...},
|
181 | output: {...},
|
182 | module: {
|
183 | rules: [
|
184 | {
|
185 | test: /\.(jpe?g|png)$/i,
|
186 | use: [
|
187 | {
|
188 | loader: "responsive-loader",
|
189 | options: {
|
190 | adapter: require('responsive-loader/sharp'),
|
191 | sizes: [320, 640, 960, 1200, 1800, 2400],
|
192 | placeholder: true,
|
193 | placeholderSize: 20
|
194 | },
|
195 | },
|
196 | ],
|
197 | }
|
198 | ]
|
199 | },
|
200 | }
|
201 | ```
|
202 |
|
203 |
|
204 |
|
205 | ### `esModule`
|
206 |
|
207 | Type: `Boolean`
|
208 | Default: `false`
|
209 |
|
210 | By default, `responsive-loader` generates JS modules that use the CommonJS syntax.
|
211 | There are some cases in which using ES modules is beneficial, like in the case of [module concatenation](https://webpack.js.org/plugins/module-concatenation-plugin/) and [tree shaking](https://webpack.js.org/guides/tree-shaking/).
|
212 |
|
213 | You can enable a ES module syntax using:
|
214 |
|
215 | **webpack.config.js**
|
216 |
|
217 | ```js
|
218 | module.exports = {
|
219 | module: {
|
220 | rules: [
|
221 | {
|
222 | test: /\.(jpe?g|png)$/i,
|
223 | use: [
|
224 | {
|
225 | loader: "responsive-loader",
|
226 | options: {
|
227 | esModule: true,
|
228 | },
|
229 | },
|
230 | ],
|
231 | },
|
232 | ],
|
233 | },
|
234 | };
|
235 | ```
|
236 |
|
237 |
|
238 | ### Writing Your Own Adapter
|
239 |
|
240 | Maybe you want to use another image processing library or you want to change an existing one's behavior. You can write your own adapter with the following signature:
|
241 |
|
242 | ```js
|
243 | type Adapter = (imagePath: string) => {
|
244 | metadata: () => Promise<{width: number, height: number}>
|
245 | resize: (config: {width: number, mime: string, options: Object}) => Promise<{data: Buffer, width: number, height: number}>
|
246 | }
|
247 | ```
|
248 |
|
249 | The `resize` method takes a single argument which has a `width`, `mime` and `options` property (which receives all loader options)
|
250 |
|
251 | In your webpack config, require your adapter
|
252 |
|
253 | ```js
|
254 | {
|
255 | test: /\.(jpe?g|png)$/i,
|
256 | loader: 'responsive-loader',
|
257 | options: {
|
258 | adapter: require('./my-adapter')
|
259 | foo: 'bar' // will get passed to adapter.resize({width, mime, options: {foo: 'bar}})
|
260 | }
|
261 | }
|
262 | ```
|
263 |
|
264 | ## Notes
|
265 |
|
266 | - Doesn't support `1x`, `2x` sizes, but you probably don't need it.
|
267 |
|
268 | ## See also
|
269 |
|
270 | - Inspired by [resize-image-loader](https://github.com/Levelmoney/resize-image-loader), but simpler and without dependency on ImageMagick
|
271 |
|
272 | [npm]: https://img.shields.io/npm/v/responsive-loader.svg
|
273 | [npm-url]: https://npmjs.com/package/responsive-loader
|
274 | [node]: https://img.shields.io/node/v/responsive-loader.svg
|
275 | [node-url]: https://nodejs.org
|
276 | [deps]: https://david-dm.org/dazuaz/responsive-loader.svg
|
277 | [deps-url]: https://david-dm.org/dazuaz/responsive-loader
|
278 | [travis]: https://travis-ci.com/dazuaz/responsive-loader.svg?branch=master
|
279 | [travis-url]: https://travis-ci.com/dazuaz/responsive-loader
|
280 | [size]: https://packagephobia.now.sh/badge?p=responsive-loader
|
281 | [size-url]: https://packagephobia.now.sh/result?p=responsive-loader |
\ | No newline at end of file |