UNPKG

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