Skip to content

Commit

Permalink
changes default adapter to sharp
Browse files Browse the repository at this point in the history
  • Loading branch information
dazuaz committed Jun 4, 2022
1 parent 53ae723 commit 9e30f4b
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 126 deletions.
77 changes: 47 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,68 @@
# responsive-loader

[![build][travis]][travis-url]
[![npm][npm]][npm-url]
[![node][node]][node-url]

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).

## Install

### With jimp
### With sharp

```
npm install responsive-loader jimp --save-dev
npm install responsive-loader sharp --save-dev
```

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.
For [super-charged performance](http://sharp.dimens.io/en/stable/performance/) and webp and avif formats support, responsive-loader works with [sharp](/~https://github.com/lovell/sharp). It's recommended to use sharp if you have lots of images to transform.

### With sharp
```js
module.exports = {
// ...
module: {
rules: [
{
test: /\.(png|jpe?g)$/,
use: [
{
loader: 'responsive-loader',
options: {
// Set options for all transforms
},
},
],
type: 'javascript/auto',
},
],
},
}
```

### With jimp

```
npm install responsive-loader sharp --save-dev
npm install responsive-loader jimp --save-dev
```

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/or need to generate webp/avif images.
Responsive-loader can be use with [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.

If you want to use sharp, you need to configure responsive-loader to use its adapter:
If you want to use jimp, you need to configure responsive-loader to use its adapter:

```diff
module.exports = {
// ...
module: {
rules: [
{
test: /\.(jpe?g|png|webp)$/i,
use: {
loader: 'responsive-loader',
options: {
+ adapter: require('responsive-loader/sharp')
}
}
test: /\.(png|jpe?g)$/,
use: [
{
loader: 'responsive-loader',
options: {
+ adapter: require('responsive-loader/jimp')
},
},
],
type: 'javascript/auto',
}
]
},
Expand All @@ -57,10 +81,10 @@ module.exports = {
{
test: /\.(jpe?g|png|webp)$/i,
use: {
loader: "responsive-loader",
loader: 'responsive-loader',
options: {
// If you want to enable sharp support:
adapter: require("responsive-loader/sharp"),
adapter: require('responsive-loader/sharp'),
},
},
},
Expand Down Expand Up @@ -108,30 +132,29 @@ Or use it in CSS (only the first resized image will be used, if you use multiple

```css
.myImage {
background: url("myImage.jpg?size=1140");
background: url('myImage.jpg?size=1140');
}

@media (max-width: 480px) {
.myImage {
background: url("myImage.jpg?size=480");
background: url('myImage.jpg?size=480');
}
}
```

```js
// Outputs placeholder image as a data URI, and three images with 100, 200, and 300px widths
const responsiveImage = require("myImage.jpg?placeholder=true&sizes[]=100,sizes[]=200,sizes[]=300")
const responsiveImage = require('myImage.jpg?placeholder=true&sizes[]=100,sizes[]=200,sizes[]=300')

// responsiveImage.placeholder => 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAIBAQE…'
ReactDOM.render(
<div
style={{
height: responsiveImage.height,
width: responsiveImage.width,
backgroundSize: "cover",
backgroundSize: 'cover',
backgroundImage: 'url("' + responsiveImage.placeholder + '")',
}}
>
}}>
<img src={responsiveImage.src} srcSet={responsiveImage.srcSet} />
</div>,
el
Expand Down Expand Up @@ -233,7 +256,7 @@ module.exports = {
test: /\.(jpe?g|png)$/i,
use: [
{
loader: "responsive-loader",
loader: 'responsive-loader',
options: {
esModule: true,
},
Expand Down Expand Up @@ -279,13 +302,7 @@ In your webpack config, require your adapter

- Inspired by [resize-image-loader](/~https://github.com/Levelmoney/resize-image-loader), but simpler and without dependency on ImageMagick

[npm]: https://img.shields.io/npm/v/responsive-loader.svg
[npm-url]: https://npmjs.com/package/responsive-loader
[node]: https://img.shields.io/node/v/responsive-loader.svg
[node-url]: https://nodejs.org
[deps]: https://david-dm.org/dazuaz/responsive-loader.svg
[deps-url]: https://david-dm.org/dazuaz/responsive-loader
[travis]: https://travis-ci.com/dazuaz/responsive-loader.svg?branch=master
[travis-url]: https://travis-ci.com/dazuaz/responsive-loader
[size]: https://packagephobia.now.sh/badge?p=responsive-loader
[size-url]: https://packagephobia.now.sh/result?p=responsive-loader
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export async function transform({
adapterOptions,
esModule,
}: TransformParams): Promise<string> {
const adapter: Adapter = adapterModule || require('./adapters/jimp')
const adapter: Adapter = adapterModule || require('./adapters/sharp')
const img = adapter(resourcePath)
const results = await transformations({ img, sizes, mime, outputPlaceholder, placeholderSize, adapterOptions })

Expand Down
186 changes: 93 additions & 93 deletions test/jimp/index.js
Original file line number Diff line number Diff line change
@@ -1,95 +1,95 @@
test("multiple sizes", () => {
const multi = require("../cat-1000.jpg?sizes[]=500&sizes[]=2000");
expect(multi).toMatchSnapshot();
expect(multi.default.toString()).toBe(multi.default.src);
});

test("parses json notation", () => {
const multi = require("../cat-1000.jpg?{sizes:[50,100,200]}");
expect(multi).toMatchSnapshot();
});

test("single size", () => {
const single = require("../cat-1000.jpg?size=500");
expect(single).toMatchSnapshot();
});

test("with size defined in webpack.config.js", () => {
const multi = require("../cat-1000.jpg");
expect(multi).toMatchSnapshot();
});

test("disable", () => {
const multi = require("../cat-1000.jpg?disable");
expect(multi).toMatchSnapshot();
});

test("output should be relative to context", () => {
const multi = require("../cat-1000.jpg?name=[path][hash]-[width]x[height].[ext]&context=./");
expect(multi).toMatchSnapshot();
});

test("output should be in outputPath dir", () => {
const multi = require("../cat-1000.jpg?outputPath=img/");
expect(multi).toMatchSnapshot();
});

test("public path should replace global publicPath", () => {
const multi = require("../cat-1000.jpg?outputPath=img/&publicPath=public/");
expect(multi).toMatchSnapshot();
});

test("with placeholder image", () => {
const output = require("../cat-1000.jpg?placeholder=true");
expect(output).toMatchSnapshot();
});

test("output first resized image height & width", () => {
const output = require("../cat-1000.jpg?size=500");
expect(output).toMatchSnapshot();
});

test("png", () => {
const output = require("../cat-transparent.png");
expect(output).toMatchSnapshot();
});

test("png to jpeg with background color", () => {
const output = require("../cat-transparent.png?background=0xFF0000FF&format=jpg");
expect(output).toMatchSnapshot();
});

test("png to jpeg with background color", () => {
const output = require("../cat-transparent.png?background=0xFF0000FF&format=jpg");
expect(output).toMatchSnapshot();
});

test("with min and max sizes", () => {
const output = require("../cat-1000.jpg?min=600&max=800&steps=3");
expect(output).toMatchSnapshot();
});

test("with min and max sizes, and default steps", () => {
const output = require("../cat-1000.jpg?min=500&max=1000");
expect(output).toMatchSnapshot();
});

test("with min and max sizes options", () => {
const output = require("../cat-1000.jpg?minmax");
expect(output).toMatchSnapshot();
});

test("override min and max with sizes", () => {
const output = require("../cat-1000.jpg?minmax&sizes[]=100&sizes[]=200");
expect(output).toMatchSnapshot();
});

test("override min and max with size", () => {
const output = require("../cat-1000.jpg?minmax&size=100");
expect(output).toMatchSnapshot();
});
test('multiple sizes', () => {
const multi = require('../cat-1000.jpg?sizes[]=500&sizes[]=2000')
expect(multi).toMatchSnapshot()
expect(multi.default.toString()).toBe(multi.default.src)
})

test('parses json notation', () => {
const multi = require('../cat-1000.jpg?{sizes:[50,100,200]}')
expect(multi).toMatchSnapshot()
})

test('single size', () => {
const single = require('../cat-1000.jpg?size=500')
expect(single).toMatchSnapshot()
})

test('with size defined in webpack.config.js', () => {
const multi = require('../cat-1000.jpg')
expect(multi).toMatchSnapshot()
})

test('disable', () => {
const multi = require('../cat-1000.jpg?disable')
expect(multi).toMatchSnapshot()
})

test('output should be relative to context', () => {
const multi = require('../cat-1000.jpg?name=[path][hash]-[width]x[height].[ext]&context=./')
expect(multi).toMatchSnapshot()
})

test('output should be in outputPath dir', () => {
const multi = require('../cat-1000.jpg?outputPath=img/')
expect(multi).toMatchSnapshot()
})

test('public path should replace global publicPath', () => {
const multi = require('../cat-1000.jpg?outputPath=img/&publicPath=public/')
expect(multi).toMatchSnapshot()
})

test('with placeholder image', () => {
const output = require('../cat-1000.jpg?placeholder=true')
expect(output).toMatchSnapshot()
})

test('output first resized image height & width', () => {
const output = require('../cat-1000.jpg?size=500')
expect(output).toMatchSnapshot()
})

test('png', () => {
const output = require('../cat-transparent.png')
expect(output).toMatchSnapshot()
})

test('png to jpeg with background color', () => {
const output = require('../cat-transparent.png?background=0xFF0000FF&format=jpg')
expect(output).toMatchSnapshot()
})

test('png to jpeg with background color', () => {
const output = require('../cat-transparent.png?background=0xFF0000FF&format=jpg')
expect(output).toMatchSnapshot()
})

test('with min and max sizes', () => {
const output = require('../cat-1000.jpg?min=600&max=800&steps=3')
expect(output).toMatchSnapshot()
})

test('with min and max sizes, and default steps', () => {
const output = require('../cat-1000.jpg?min=500&max=1000')
expect(output).toMatchSnapshot()
})

test('with min and max sizes options', () => {
const output = require('../cat-1000.jpg?minmax')
expect(output).toMatchSnapshot()
})

test('override min and max with sizes', () => {
const output = require('../cat-1000.jpg?minmax&sizes[]=100&sizes[]=200')
expect(output).toMatchSnapshot()
})

test('override min and max with size', () => {
const output = require('../cat-1000.jpg?minmax&size=100')
expect(output).toMatchSnapshot()
})

test("doesn't emit file", () => {
const multi = require("../cat-1000.jpg?emitFile=false&sizes[]=250");
expect(multi).toMatchSnapshot();
});
const multi = require('../cat-1000.jpg?emitFile=false&sizes[]=250')
expect(multi).toMatchSnapshot()
})
2 changes: 2 additions & 0 deletions test/jimp/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = {
min: 100,
max: 300,
esModule: true,
adapter: require('../../jimp'),
},
type: 'javascript/auto',
},
Expand All @@ -23,6 +24,7 @@ module.exports = {
options: {
sizes: [500, 750, 1000],
esModule: true,
adapter: require('../../jimp'),
},
type: 'javascript/auto',
},
Expand Down
2 changes: 0 additions & 2 deletions test/sharp/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ module.exports = {
options: {
min: 100,
max: 300,
adapter: require('../../sharp'),
},
},
],
Expand All @@ -28,7 +27,6 @@ module.exports = {
loader: require.resolve('../../lib/index'),
options: {
sizes: [500, 750, 1000],
adapter: require('../../sharp'),
},
},
],
Expand Down

0 comments on commit 9e30f4b

Please sign in to comment.