Giter Club home page Giter Club logo

responsive-loader's Introduction

responsive-loader

build node

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. Browser support is pretty good.

Install

With sharp

npm install responsive-loader sharp --save-dev

For super-charged performance and webp and avif formats support, responsive-loader works with sharp. It's recommended to use sharp if you have lots of images to transform.

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 jimp --save-dev

Responsive-loader can be use with 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 jimp, you need to configure responsive-loader to use its adapter:

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.(png|jpe?g)$/,
        use: [
          {
            loader: 'responsive-loader',
            options: {
+               adapter: require('responsive-loader/jimp')
            },
          },
        ],
        type: 'javascript/auto',
      }
    ]
  },
}

Typescript

//declare a module to your type definitions files *.d.ts 
interface ResponsiveImageOutput {
  src: string
  srcSet: string
  placeholder: string | undefined
  images: { path: string; width: number; height: number }[]
  width: number
  height: number
  toString: () => string
}

declare module '*!rl' {
  const src: ResponsiveImageOutput
  export default src
}
import responsiveImage from 'img/myImage.jpg?sizes[]=300,sizes[]=600,sizes[]=1024,sizes[]=2048!rl';
import responsiveImageWebp from 'img/myImage.jpg?sizes[]=300,sizes[]=600,sizes[]=1024,sizes[]=2048&format=webp!rl';
...

Then import images in your JavaScript files:

import responsiveImage from 'img/myImage.jpg?sizes[]=300,sizes[]=600,sizes[]=1024,sizes[]=2048';
import responsiveImageWebp from 'img/myImage.jpg?sizes[]=300,sizes[]=600,sizes[]=1024,sizes[]=2048&format=webp';

// Outputs
// responsiveImage.srcSet => '2fefae46cb857bc750fa5e5eed4a0cde-300.jpg 300w,2fefae46cb857bc750fa5e5eed4a0cde-600.jpg 600w,2fefae46cb857bc750fa5e5eed4a0cde-600.jpg 600w ...'
// responsiveImage.images => [{height: 150, path: '2fefae46cb857bc750fa5e5eed4a0cde-300.jpg', width: 300}, {height: 300, path: '2fefae46cb857bc750fa5e5eed4a0cde-600.jpg', width: 600} ...]
// responsiveImage.src => '2fefae46cb857bc750fa5e5eed4a0cde-2048.jpg'
// responsiveImage.toString() => '2fefae46cb857bc750fa5e5eed4a0cde-2048.jpg'
...
  <picture>
    <source srcSet={responsiveImageWebp.srcSet} type='image/webp' sizes='(min-width: 1024px) 1024px, 100vw'/>
    <img
      src={responsiveImage.src}
      srcSet={responsiveImage.srcSet}
      width={responsiveImage.width}
      height={responsiveImage.height}
      sizes='(min-width: 1024px) 1024px, 100vw'
      loading="lazy"
    />
  </picture>
...

Notes:

  • width and height are intrinsic and are used to avoid layout shift, other techniques involve the use of aspect ratio and padding.
  • sizes, without sizes, the browser assumes the image is always 100vw for any viewport.
  • loading do not add loading lazy if the image is part of the initial rendering of the page or close to it.
  • srcset Modern browsers will choose the closest best image depending on the pixel density of your screen.
    • in the example above is your pixel density is >1x for a screen >1024px it will display the 2048 image.

Or use it in CSS (only the first resized image will be used, if you use multiple sizes):

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

@media (max-width: 480px) {
  .myImage {
    background: url('myImage.jpg?size=480');
  }
}
// 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')

// responsiveImage.placeholder => 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAIBAQE…'
ReactDOM.render(
  <div
    style={{
      height: responsiveImage.height,
      width: responsiveImage.width,
      backgroundSize: 'cover',
      backgroundImage: 'url("' + responsiveImage.placeholder + '")',
    }}>
    <img src={responsiveImage.src} srcSet={responsiveImage.srcSet} />
  </div>,
  el
)

You can also use JSON5 notation:

<source srcSet={require('./image.jpg?{sizes:[50,100,200,300,400,500,600,700,800], format: "webp"}').srcSet} type='image/webp'/>

Options

Option Type Default Description
name string [hash]-[width].[ext] Filename template for output files.
outputPath string | Function undefined Configure a custom output path for your file
publicPath string | Function undefined Configure a custom public path for your file.
context string this.options.context Custom file context, defaults to webpack.config.js context
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.
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)
min integer As an alternative to manually specifying sizes, you can specify min, max and steps, and the sizes will be generated for you.
max integer See min above
steps integer 4 Configure the number of images generated between min and max (inclusive)
quality integer 85 JPEG and WEBP compression quality
format string original format Either png or jpg; use to convert to another format. webp and avif is also supported, but only by the sharp adapter
placeholder boolean false A true or false value to specify wether to output a placeholder image as a data URI
placeholderSize integer 40 A number value specifying the width of the placeholder image, if enabled with the option above
adapter Adapter JIMP Specify which adapter to use. Can only be specified in the loader options.
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.
esModule boolean false Use ES modules syntax.
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.
cacheDirectory string or boolean false Experimental: If true, this will cache the result object but not the image files. The images are only produced once, when they are not found in the results object cache, or when the options change (cache key). For Development you can set query parameter to ?cacheDirectory=false.

Adapter-specific options

jimp
  • background: number — Background fill when converting transparent to opaque images. Make sure this is a valid hex number, e.g. 0xFFFFFFFF)
sharp
  • background: string — Background fill when converting transparent to opaque images. E.g. #FFFFFF or %23FFFFFF for webpack > 5
  • format: webp — Conversion to the image/webp format. Recognizes the quality option.
  • format: avif — Conversion to the image/avif format. Recognizes the quality option.
  • progressive: boolean - Use progressive (interlace) scan for image/jpeg format.
  • rotate: number - Rotates image more here

Examples

Set a default sizes array, so you don't have to declare them with each require.

module.exports = {
  entry: {...},
  output: {...},
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|webp)$/i,
         use: [
          {
            loader: "responsive-loader",
            options: {
              adapter: require('responsive-loader/sharp'),
              sizes: [320, 640, 960, 1200, 1800, 2400],
              placeholder: true,
              placeholderSize: 20
            },
          },
        ],
      }
    ]
  },
}

cacheDirectory

Type: Boolean or string Default: false

Experimental: If true, this will cache the result object but not the image files. The images are only produced once, when they are not found in the results object cache, or when the options change (cache key). For Development you can set query parameter to individual images by using ?cacheDirectory=false.

Default cache directory might be .node_modules/.cache/responsive-loader

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png)$/i,
        use: [
          {
            loader: 'responsive-loader',
            options: {
              esModule: true,
              cacheDirectory: true,
              publicPath: '/_next',
              name: 'static/media/[name]-[hash:7]-[width].[ext]',
            },
          },
        ],
      },
    ],
  },
}

esModule

Type: Boolean Default: false

By default, responsive-loader generates JS modules that use the CommonJS syntax. There are some cases in which using ES modules is beneficial, like in the case of module concatenation and tree shaking.

You can enable a ES module syntax using:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png)$/i,
        use: [
          {
            loader: 'responsive-loader',
            options: {
              esModule: true,
            },
          },
        ],
      },
    ],
  },
}

Writing Your Own Adapter

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:

type Adapter = (imagePath: string) => {
  metadata: () => Promise<{width: number, height: number}>
  resize: (config: {width: number, mime: string, options: Object}) => Promise<{data: Buffer, width: number, height: number}>
}

The resize method takes a single argument which has a width, mime and options property (which receives all loader options)

In your webpack config, require your adapter

{
  test: /\.(jpe?g|png)$/i,
  loader: 'responsive-loader',
  options: {
    adapter: require('./my-adapter')
    foo: 'bar' // will get passed to adapter.resize({width, mime, options: {foo: 'bar}})
  }
}

Notes

  • Doesn't support 1x, 2x sizes, but you probably don't need it.

Usage Examples

Next.js

Pug

Please submit your own example to add here

responsive-loader's People

Contributors

alex-ketch avatar arcanis avatar bensmithett avatar callumacrae avatar dazuaz avatar dependabot[bot] avatar domenicocardillo avatar dscafati avatar dzuloaga avatar greenkeeperio-bot avatar jstcki avatar klathmon avatar lnhrdt avatar matpen avatar mcfunley avatar saraedum avatar tymick avatar youngpirate32 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

responsive-loader's Issues

Feature Request - Add support of Image operation for sharp adapter

Hello,

Sharp allowing the possibility of extract an image (a crop) using http://sharp.pixelplumbing.com/en/stable/api-operation/#extract. Does it make sense to add it to this package?
With this, it would be nice to be able to chain images transformation, with something like:

              use: [
                   {
                       loader: 'file-loader',
                   }
                   {
                       loader: 'responsive-loader',
                       options: {
                           adapter: require('responsive-loader/sharp-extract'),
                           name: "images/responsive/[name]-[width].[ext]"
                       }
                   },
                   {
                       loader: 'responsive-loader',
                       options: {
                           adapter: require('responsive-loader/sharp')
                       }
                   },
               ],

this way, we can resize then extract the image (looks like another feature request).

src equals smallest size

Hi,

why is responsiveImage.src set to the smallest of all values defined in "sizes" instead of the original imagesize?

doesn't seem straight forward to me, any thought behind this?

Dynamic name templating

Hello,

It could very usefull to have different name for an image based on an attribute.
For example:
A name in french set with i18n and another one in english.
2 pictures will be generated.
This is mainly for SEO optimisation.
It could be also usefull to set the name dynamically even for a unique language.

Do you think it could be, is it already possible ?

Thanks

TypeError: Cannot read property 'height' of null

I use sharp adapter and i get:

/Users/grzegorzzajac000/Praca/webpack-www-starter/node_modules/responsive-loader/lib/adapters/sharp.js:30
var height = _ref2.height;
                            ^

TypeError: Cannot read property 'height' of null
    at /Users/grzegorzzajac000/Praca/webpack-www-starter/node_modules/responsive-loader/lib/adapters/sharp.js:37:29

(sharp:97516): GLib-CRITICAL **: g_hash_table_lookup: assertion 'hash_table != NULL' failed

(sharp:97516): GLib-CRITICAL **: g_hash_table_insert_internal: assertion 'hash_table != NULL' failed

(sharp:97516): GLib-CRITICAL **: g_hash_table_lookup: assertion 'hash_table != NULL' failed
Magick: abort due to signal 11 (SIGSEGV) "Segmentation Fault"...
/bin/sh: line 1: 97516 Abort trap: 6           node_modules/.bin/webpack --config webpack/prod.config.babel.js -p --hide-modules
error Command failed with exit code 134.

Options without configuring loader?

In the old version, I did something like this when importing the image:

import topImage from 'responsive-loader!./images/contact-us.jpg';

And then had a section with options in my webpack 2 config:

new webpack.LoaderOptionsPlugin({
	options: {
		responsiveLoader: {
			sizes: [1000, 500, 1500],
			placeholder: true,
			placeholderSize: 20,
			quality: 75,
			name: 'images/[name]-[sha512:hash:base64:5]-[width].',
		},
	},
}),

But with v1.x there are only examples specifying options when responsive-loader is configured as a loader? Is there any other way to specify default settings (without LoaderOptionsPlugin since that will be deprecated eventually)?

Give image mime type in images array

It'd be useful for building <picture> elements to have each image's mime type along with its other data, for use in the type attribute of the <source> element.

Replace name with outPath and publicPath

Can you replace the name option with outPath and publicPath?

For example when using Laravel the outPath is /public/images/image.png. However the publicPath should be /images/image.png This is now impossible to do.

webp export

Any change to add webp as an option?
Ideally it would be nice to build something like

<picture>
    <!--[if IE 9]><video style="display: none;"><![endif]-->
    <source type="image/webp" srcset="2700x1209/rocket-pods-mr-ben-01-2700x1209.webp 2700w, 
                    1800x806/rocket-pods-mr-ben-01-1800x806.webp 1800w, 
                    1536x1536/rocket-pods-mr-ben-01-1536x1536.webp 1536w, 
                    1024x1024/rocket-pods-mr-ben-01-1024x1024.webp 1024w, 
                    900x900/rocket-pods-mr-ben-01-900x900.webp 900w, 
                    600x600/rocket-pods-mr-ben-01-600x600.webp 600w" 
            sizes="100vw" />
    <source srcset="2700x1209/rocket-pods-mr-ben-01-2700x1209.jpg 2700w, 
                    1800x806/rocket-pods-mr-ben-01-1800x806.jpg 1800w, 
                    1536x1536/rocket-pods-mr-ben-01-1536x1536.jpg 1536w, 
                    1024x1024/rocket-pods-mr-ben-01-1024x1024.jpg 1024w, 
                    900x900/rocket-pods-mr-ben-01-900x900.jpg 900w, 
                    600x600/rocket-pods-mr-ben-01-600x600.jpg 600w" 
            sizes="100vw" />
    <!--[if IE 9]></video><![endif]-->
    <img class="rsImg" src="600x600/rocket-pods-mr-ben-01-600x600.jpg" alt="Visit MrBen" />
</picture>

SASS mixin example

Hello,

First, thanks for this loader, very useful :)

I just wanted to share my solution for integrating this loader with SASS.
SASS users that are using, for example, Bootstrap, can have responsives images very easily, without the boilerplate of the pure-CSS version as showed in the readme:

@mixin responsive-background-image($url) {
    @each $breakpoint in map-keys($grid-breakpoints) {
        $next-breakpoint: breakpoint-next($breakpoint);

        @include media-breakpoint-up($breakpoint) {
            @if ($next-breakpoint == null) {
                background-image: url('#{$url}?size=3840'); // max: 4k images
            } @else {
                $next-width: map-get($grid-breakpoints, $next-breakpoint);
                background-image: url('#{$url}?size=#{$next-width}');
            }
        }
    }
}

Usage:

@include responsive-background-image('image.jpg');

I use it in conjunction with a responsive-loader config that uses Bootstrap breakpoints by default:

options: {
    loader: 'responsive-loader',
    adapter: require('responsive-loader/sharp'),
    sizes: [576, 768, 992, 1200], // copied from Bootstrap breakpoints

Cannot find module when using vars in image path

I currently have the need to dynamically get images inducing require statements of strings concatenated with vars.

This loader works totally fine with statics assets but throws an error whit dynamic paths

import test from '../../images/orbital/ALL/0.jpg?size=1920'
console.log(test) // outputs the object
const test2 = require('../../images/orbital/ALL/0.jpg?size=1920')
console.log(test2) // outputs the object
const foo = 'ALL'
const test3 = require('../../images/orbital/' + foo + '/0.jpg?size=1920') // Error: Cannot find module

[Question] Webpack 2 supported?

Is this lib compatible with webpack 2?

I've tried

 @include breakpoint(mobile) {
     background-image: url('responsive?size=480!../../../../assets/hero.jpg');
  }

However this breaks my build. Webpack seems to no longer support the ! loader syntax?

Also would this be correct?

module: {
        rules: [
            {
                test: /\.(png|jpg|svg)$/,
                use: 'url-loader?limit=8192',
                include: PATHS.app,
            },
            {
                test: /\.(jpg|png|svg)$/,
                use: 'file-loader?name=[path][name].[hash].[ext]',
                include: PATHS.images,
            },
{
                test: /\.(jpg)$/,
                use: 'responsive',
                include: PATHS.images,
            }
        ]
    }

Optimize quality and performance

JIMP is pretty neat because it doesn't depend on some binary (makes it easy to run anywhere) but performance degrades quickly with many images.

Also, the resized image quality could be better (noticeable when scaling down 1px lines in transparent PNGs).

These problems could potentially be remedied with using another library/binary. Maybe add a configuration option for the 'engine'.

Cache resized images for faster build times

After installing this my webpack built times have gone up to 5+ seconds making my feedback look much longer. Would it be possible for this plugin to cache the created images and only re-compress them if the parameters were different?

Example for HTML/Blade (PHP)?

@herrstucki:
It would be great if there is an example for using this loader in HTML/Blade (PHP template language).
It should be used in a Sage (WordPress base) theme.

Resize and/or crop images?

Is it possible to use this loader to also resize/crop images? For instance, it could be great to use it to create thumbnails with different ratio, ...
Thank you

Change output directory

I can't seem to find a way to change where the resulting files are output. At the moment they are all put in webpack's output.path, but in my case this isn't ideal. Is there any way to change this?

Many thanks

PostCSS

I've found this loader particularly useful. However, it's looking like I'm going to be using parcel more and more, and one of the only things I can't find an alternative for is this loader. While I realise it's much easier said than done, it would be nice if this was rewritten as a postcss plugin, then it could be used by webpack, parcel, and others.

Individual background color option

It would be great if a background color can be applied per image
(when converting an alphatransparent PNG/transparent GIF to flat JPEG).

Related issue: #50

Can this work with create-react-app?

As in the title, I have installed this and used crako to plug the module but it seems to be ignored by the one create-react-app use under the hood.

Did anyone succeed to use this in webpack and non ejected create react app?

Ignores all parameters (CSS/SASS/PostCSS)

I am using SASS with PostCSS together with responsive-loader in a webpack setup.
The size parameter is ignored, always the original (max) size file used.

Example:

.test {
  background-image: url(../images/background.jpg?size=1600&quality=10);
}

parsedResourceQuery is empty for the files referenced from within the SCSS files.

"React does not recognize the `toString` prop [...]" warning

I'm using the <img {...responsiveImage} /> shorthand syntax. I just recently noticed the warning although I'm not sure when it started occurring. Not sure anything can be done about it. I should note that I'm using next-optimized-images but as far as I can tell the issue stems from this loader.

Thank you for developing this fantastic project!

How to reference different sizes in a template

Responsive-loader is generating all my images beautifully with the correct names and sizes, but I can't figure out how to reference other sizes than the default (smallest one) in my template!

// webpack.config file
...
{
  test: /\.(jpe?g|png)$/i,
  loader: 'responsive-loader',
  options: {
    adapter: require('responsive-loader/sharp'),
    sizes: [600, 1200],
    placeholder: true,
    placeholderSize: 50,
    name: '/assets/img/[hash]-[width].[ext]'
  }
},
...

And this is how I'm referencing the images in my template html

  <img src="${require('./assets/img/image_0.jpg')}" alt="">

This gives me the 600px wide image and I would like to get different images based on screen size. Any pointers?

Background: '#FFFFFF' forces ALL transparent PNGs to white

Expected behavior:
When I set Background: '#FFFFFF' I expect white background ONLY on JPGs converted from transparent PNGs.

Current behavior:
Applies white background to ALL transparent PNGs, not just the ones being converted to JPGs.

I am using the Sharp adapter.

Add option to output no files at all

A valuable option would be to only make the URL-encoded placeholder version, plus srcSet and src for requested sizes clamped to real file size. The custom name formatting + publicPath will then allow requesting the resized images from imgIX or Cloudinary, which handle things static hosting can't easily do such as accept headers for webp.

Proposal: Change how emitted file name extensions are handled

Would you be open to a PR to change how the file extension is attached to the base file name?

I'm wary as it could potentially be breaking change, but it seems odd—and not in line with other loaders—that you need to include a trailing period when including a name query.

For instance with a file named test.jpg:
responsive?name=[name]-[width].[ext] outputs test-500.jpgjpg
responsive?name=[name]-[width] outputs test-500jpg
responsive?name=[name]-[width]. outputs test-500.jpg (note the trailing period in the query)

The PR would make it so that:

  • A query without a name parameter would use the default file extension
  • A query with a name parameter would require a full naming structure (`[name]-[width].[ext])
  • A query with an explicitly named extension would convert the file to that type and use that extension (as currently handled)

Fix `pass` option to skip image resizing

It is not always necessary to output resized images, local development for instance, and this becomes cumbersome if you need to stop and start the local build process.

I'd like to clean up the pass option to simply spit out the original image, without resizing it.

Currently this partially works but I'm getting corrupted images, and no placeholder data URI output.
Height & Width would be that of the original image.

For placeholder I see three approaches:

  1. Encode the image at original size
  • Will potentially lead to very long URIs
  • Will need to do speed tests
  1. Scale down and output at the placeholder size setting
  • Slow, as we'll have to resize the image. Could be mitigated by #29
  1. Hard code a small image when using this option

A side question, is a more explicit option name better? skip for example?

What do you think @herrstucki?

File not found when generated from CSS

"responsive-loader": "^1.1.0"
"webpack": "^3.10.0"

Great loader, much thanks. One issue I'm finding is when an image is created from a CSS url, the path that's generated to pull in the resource results in a "can't be found" type error. To clarify, an image with the correct name gets created however it gets assigned a path that can't be found. However, an image created from importing in a JS file is located and pulls in fine.

Example of a path generated from within a JS file:
file:///C:/Users/kcantrell/Desktop/offline-dev-projects/practice-router/dist/imgs/cloud-200.jpg

Example of a path generated from a CSS url:
file:///C:/Userskcantrell%C3%9Esktopoffline-dev-projectspractice-router/dist/imgs/calculator-background-700.jpg

Is this a bug or perhaps am I missing something and there's some configuration I need to do to get CSS urls to work with the loader. Webpack config below:

const path = require('path'),
	  ExtractTextPlugin = require('extract-text-webpack-plugin'),
	  CompressionPlugin = require('compression-webpack-plugin'),
	  webpack = require('webpack');

module.exports = {
	entry: {
		app: './src/js/index.js'
	},
	output: {
		path: __dirname + '/dist',
		publicPath: __dirname + '/dist/',
		filename: "[name].bundle.js",
		chunkFilename: "[name].bundle.js"
	},
	module: {
	    rules: [
			{
			      test: /\.js$/,
			      include: path.resolve(__dirname, 'src/js'),
			      use: [{
			        loader: 'babel-loader',
			        options: {
			          presets: [
			            ['env', { modules: false }]
			          ]
			        }
			      }]
			    },
		      {
		        test: /\.(png|jpg|gif)$/,
		        use: {
		        	loader: 'responsive-loader',
		        	options: {
		        		name: 'imgs/[name]-[width].[ext]'
		        	}
		        }
		      },
		      {
		        test: /\.css$/,
		        exclude: path.resolve(__dirname, 'src/css'),
		        loader: 'css-loader',
		        options: {
		        	minimize: true
		        }
		      },
		      {
		        test: /\.css$/,
		        include: path.resolve(__dirname, 'src/css'),
		        loader: ExtractTextPlugin.extract(
		        	{use: [
		        		{ loader: 'css-loader',
		        			options: { minimize: true } 
		        		}
                                 ]}
                         )
		      }
	    ]
	},
  plugins: [
    new ExtractTextPlugin("app.css"),
    new webpack.optimize.CommonsChunkPlugin({
				name: 'commons',
				filename: 'commons.js'
		}),
		new webpack.optimize.LimitChunkCountPlugin({
		  maxChunks: 6
		  // minChunkSize: 1000
		})
  ]
}

Wrong extension

{
    test: /\.(jpe?g|png)$/i,
    use: {
      loader: 'responsive-loader',
      options: {
        name: '[name].[hash].[ext]',
        size: 768,
        placeholder: false
      }
    }
}

It returns filename.784f17d8a8c77977b1c087cc21edb553.jpgjpg and if I remove .[ext] there will be no dot before jpg

Cache/reuse output files if newer than the source files

It seems that the rescaling of assets is currently one of the longest (~1m) parts of our build right now, and I wonder if this step is even needed at all, since the static files do not change.

Some details:

  • There are input images:
    ** 8 jpegs with total size 2 289 723 bytes
    ** 4 pngs with total size 2 009 442 bytes
  • There are 40 output images with total size 5 163 055 bytes

Possible to add png optimization?

I'm aware of the discussion in #3 but it seems that responsive-loader is able to optimize jpegs via the quality setting. Why is it possible to optimize jpegs but not png? Or can optipng and/or pngquant be added? I'd love to be able to handle both jpegs and pngs with this loader.

How to handle `responsive-loader` with jest/CRA?

I am using CRA with responsive-loader, and I am getting the following errors:

 FAIL  src/pages/User/test.tsx
  ● Test suite failed to run

    Cannot find module './assets/user_background.jpg?min=320&max=800&steps=3' from 'index.tsx'

    However, Jest was able to find:
        './index.tsx'

    You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['web.js', 'js', 'web.ts', 'ts', 'web.tsx', 'tsx', 'json', 'web.jsx', 'jsx', 'node'].

    See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string

      20 | 
    > 21 | const userBackground = require('./assets/user_background.jpg?min=320&max=800&steps=3')
         |                        ^
      22 | 

Are there any solutions to fix the test?

The only way around it I can find it edit my import into const userBackground = require('./assets/user_background.jpg') and so not having any benefits of the loader.

CSS Loader and Responsive-Loader issue

In web pack 2.x, I'm having issues using responsive-loader inside of my sass files. CSS loader throws an error..

 ERROR in ./~/css-loader?{"sourceMap":true,"importLoaders":1,"modules":true,"localIdentName":"[name]__[local]--[hash:base64:5]","di
scardComments":{"removeAll":true}}!./~/sass-loader/lib/loader.js?{"sourceMap":true}!./src/views/Main/Home/style.scss
    Module not found: Error: Can't resolve './responsive-loader' in '/Users/projects/am/am-web/src/views/Main/Home'
     @ ./~/css-loader?{"sourceMap":true,"importLoaders":1,"modules":true,"localIdentName":"[name]__[local]--[hash:base64:5]","discardC
omments":{"removeAll":true}}!./~/sass-loader/lib/loader.js?{"sourceMap":true}!./src/views/Main/Home/style.scss 6:6240-6315

Any ideas? I've looked through the source but I don't understand how it handles css files...

Thanks

Webpack modules

module: {
        rules: [
            {
                test: /\.(jpg)$/,
                use: 'responsive-loader',
                include: PATHS.images,
            },
            {
                test: /\.tsx?$/,
                use: 'ts-loader',
                include: PATHS.app,
            },
            {
                test: /\.(png|jpg|svg)$/,
                use: 'url-loader?limit=8192',
                include: PATHS.app,
            },
            {
                test: /\.(jpg|png|svg)$/,
                use: 'file-loader?name=[path][name].[hash].[ext]',
                include: PATHS.images,
            }
        ]
    }

Webpack css loader rules

{
                    test: /(\.scss|\.sass)$/,
                    use: ExtractTextPlugin.extract({
                        fallback: "style-loader",
                        use: [
                            {
                                loader: 'css-loader',
                                options: {
                                    sourceMap: true,
                                    importLoaders: 1,
                                    modules: true,
                                    localIdentName: '[name]__[local]--[hash:base64:5]',
                                    discardComments: {
                                        removeAll: true
                                    }
                                }
                            },
                            {
                                loader: "sass-loader",
                                options: {
                                    sourceMap: true
                                }
                            }
                        ]
                      
                    }),
                 
                }

My sass

hero {
  background-image: url('../../../../assets/hero.jpg');
  background-size: cover;
  color: #fff;
  text-align: center !important;

  @include breakpoint(desktop) {
    background-image: url('responsive-loader?size=1000!../../../../assets/hero.jpg');
  }

  @include breakpoint(laptop) {
    background-image: url('responsive-loader?size=800!../../../../assets/hero.jpg');
  }

  @include breakpoint(tablet) {
    background-image: url('responsive-loader?size=600!../../../../assets/hero.jpg');
  }

  @include breakpoint(mobile) {
    background-image: url('responsive-loader?size=480!../../../../assets/hero.jpg');
  }
}  

min and max arguments to calculate sizes automatically

Hey! I'm currently attempting to integrate a responsive images loader into html-loader, as currently it just outputs full sized images.

Would you accept a PR enabling this syntax?

require('responsive?min=100&max=300!./myImage.jpg');

From there, it'll calculate the best sizes (maybe another argument to say the number of images?), and generate the images. This could be done from html-loader, but I figure it's best to do it from the place that actually accesses the image file so that max can be taken down if necessary.

Injecting srcset in html

Hello.
I'm trying to use responsive-loader with a html file.
My loader setup:

       {
          test: /\.(png|jpg)$/,
          use: {
            loader: 'responsive-loader',
            options: {
              placeholder: true,
              sizes: [400, 600, 800, 1000, 1200],
              name: 'assets/images/[name]-[width].[hash:4].[ext]'
            }
          }
        }

Inside .html file:

<img src="${require('../../assets/images/image.png').src}" srcset="${require('../../assets/images/image.png').srcSet}"/>

In the output:

<img src="undefined" srcset="undefined"/>

When I omit .src or .srcSet in html and write it like this:

<img src="${require('../../assets/images/image.png')}"  />

it will return a smallest image of the set:

<img src="assets/images/image-400.png'  />

In the same time, when I require an image inside my .js file, it returns an object with all properties as it's supposed.

I read a similar issue #68 but the solution proposed there did not work for me as I am not using Vue.

Image srcSets not escaped, breaks on paths with spaces in them

Because srcSet's paths are not escaped, it will produce this invalid output;

<img 
  src="/_next/static/images/Review List-711-834bd42895bd86b4f618f1dedcf9df31.png" 
  srcSet="/_next/static/images/Review List-711-834bd42895bd86b4f618f1dedcf9df31.png 711w"
/>

resulting in this error in the conosle (in Chrome):

Dropped srcset candidate "/_next/static/images/Review"
Failed parsing 'srcset' attribute value since it has an unknown descriptor.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.