Giter VIP home page Giter VIP logo

srcset-loader's Introduction

srcset-loader for webpack 2

Build Status

A super flexible and easily chainable (with other loaders like file-loader or image-webpack-loader) srcset loader for webpack 2.

Its purpose is to automatically resize your images to the requested dimensions and return those as an srcSet.

Installation

npm i -D srcset-loader

Usage

There are basically two parts to configure, one part is the loader itself, the other part is the images you want to have a srcset for. Instead of specifying the loader inline, you specify which images should be loaded with the srcset-loader in your webpack config, then specify the sizes for the srcset on the resource itself.

e.g. your config could have a loader specified like this, notice the ?sizes at the end of the resource match

const webpackConfig = {
  // Only showing relevant parts.
  module: {
    rules: [{
      // match image files
      test: /\.(jpe?g|png|svg|gif)$/,

      // match one of the loader's main parameters (sizes and placeholder)
      resourceQuery: /[?&](sizes|placeholder)(=|&|\[|$)/,

      use: [
        'srcset-loader',

        // any other loader
        'file-loader?hash=sha512&digest=hex&name=[hash].[ext]',
        'image-webpack-loader?optimizationLevel=7&interlaced=false',
      ],
    }],
  },

  // ...
};

and a resource request could look like this:

import image from './image.jpeg?sizes=200w+800w';

This allows us to separate the configuration of the loader, and the specification of the image sizes of the srcset. This also allows us to use the same loaders we use for normal image requests (e.g. optimizers like webpack-image-loader or the file-loader). Basically all this loader does is creating multiple requests for each srcset image and let known and well tested loaders do the heavy lifting.

Why is the srcset loader before the other loaders

Its actually very important that you add the srcset-loader before all the other loaders, as the srcset-loader uses webpack's pitch mechanism to split your import request into multiple import request which will all use the loaders specified after srcset-loader.

Simplified it works something like this:

// webpack gets this request
const someSrcSet = require('./someImage.jpg?sizes=800w+500w+200w');

//----------------------------------------

// the srcset loader gets this *single* request that actually looks something like this:
const someSrcSet = require('srcset-loader!url-loader!image-webpack-loader!./someImage.jpg?sizes=800w+500w+200w');

// and splits it up into *three* requests looking more like this:
const someSrcSet = [
  require('url-loader!image-webpack-loader!srcset-loader/resize!./someImage.jpg?size=800'),
  require('url-loader!image-webpack-loader!srcset-loader/resize!./someImage.jpg?size=500'),
  require('url-loader!image-webpack-loader!srcset-loader/resize!./someImage.jpg?size=200'),
];

Thats all :), simple and robust.

Can I use srcset-loader inline?

Yes you can, but why? Seriously why? Please write an issue.

srcset-loader options

sizes

sizes is the main feature of the srcset-loader, you use this option to specify the different image sizes you wish to import.

You can either specify the different sizes as a standard array (?sizes[]=100w&sizes[]=200w) or using the less verbose, srcset-specific, syntax (?sizes=100w+200w)

The sizes values must follow the format <number>w (where w stands for width), or the string default (not resized). <density>x is not a supported format.

lightweight

This will remove any property that can be computed at runtime in order to reduce the size of the bundle.

placeholder

placeholder will generate and inline a tiny placeholder which you can display while the full-sized image loads.

You can specify the size of the placeholder as the value of the option (e.g. placeholder=12). By default, the size is 20px (width).

Results of an image loaded with srcset-loader

An image imported with the srcset-loader returns an Object which contains the following properties:

srcSet: string

This property contains the string to use as the value of HTMLImageElement's srcset (i.e. <img srcset="..."/>).

e.g.

import image from './image.jpeg?sizes=200w+800w';
// image.srcSet => 'xxxx.jpeg 200w,xxxx.jpeg 800w'

Note: This key is not available if lightweight is specified in either the Loader options or the resource query.

sources: object

The sources object is a map where the keys are the requested sizes of the image and the values are the URLs to those images.

e.g.

import image from './image.jpeg?sizes=200w+800w';

/*
image.sources => {
  '200w': 'xxx.jpg',
  '800w': 'xxx.jpg',
}
*/

placeholder

Only available if the option placeholder is present in either the loader configuration or the resource query.

This will generate an object with these keys:

  • url:
    • if the lightweight option is present, a tiny version of the image, encoded in base64.
    • otherwise, that tiny image but wrapped inside a SVG which applies a blur filter on the image.
  • color: an array containing the rgba color representing the most ubiquitous color of the image. [r, g, b, a]
  • ratio: the width to height ratio of the image.

e.g.

import image from './image.jpeg?sizes=200w+800w&placeholder';
/*
image.placeholder => {
  url: 'data:image/svg+xml;base64,...',
  color: [198, 123, 87, 1],
  ratio: 1.587302
}
*/

check the placeholder example for a possible use case.

Note: You can use placeholder on its own, without specifying sizes.

srcset-loader's People

Contributors

dcalhoun avatar ephys avatar gabrielbull avatar timse avatar tremby avatar xeophin 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

Watchers

 avatar  avatar  avatar  avatar

srcset-loader's Issues

Bug in SVG placeholder size

I came across this piece of code:

const svg = `
<svg
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 ${10 * ratio} ${10 * (1 - ratio)}"
>

Whichever way around the aspect ratio is (see #14), this code seems broken.

viewBox is x offset, y offset, width, height.

For height you have 10 * (1 - ratio).

But ratio can be any number greater than zero and less than infinity. If ratio is 2, for example (either a 100x200 or 200x100 image, depending how the ratio is calculated), this will evaluate to a height of -10.

How to use?

I'm not sure whether I use this right.

So I suppose this plugin creates images depending on the query string you give each image in your html (picture tags)? Or not?

I have the following code:

<picture>
    <source srcset="{{ asset('images/header01.jpg?sizes=575w&placeholder=true') }}" media="max-width: 575px">
    <source srcset="{{ asset('images/header01.jpg?sizes=768w&placeholder=true') }}" media="max-width: 768px">
    <source srcset="{{ asset('images/header01.jpg?sizes=991w&placeholder=true') }}" media="max-width: 991px">
    <source srcset="{{ asset('images/header01.jpg?sizes=1199w&placeholder=true') }}" media="max-width: 1199px">
    <img srcset="{{ asset('images/header01.jpg') }}" alt="My default image">
</picture>

then in my webpack config (using the Laravel framework) I have following config set:

 mix.webpackConfig({
   module: {
     rules: [{
       test: /\.(jpe?g|png|svg|gif)$/,
       resourceQuery: /[?&](sizes|placeholder)(=|&|\[|$)/,
       use: [
         'srcset-loader',
         'image-webpack-loader?optimizationLevel=7&interlaced=false',
       ],
     }],
   }
 });

This code doesn't create any images, it doesn't seem to do anything. Am I using it correctly?

Dynamic paths with rule options raises Error

I can't manage to make srcset-loader work when I have both dynamic paths and loader options.

Here is the webpack.config.js section corresponding to the image rules:

{
    test: /\.(gif|png|jpe?g)$/i,
    include: path.join(__dirname, 'src'),
    oneOf: [
      {
        resourceQuery: /[?&](sizes|placeholder)(=|&|\[|$)/,
        use: ['srcset-loader', 'file-loader?name=[md5:hash:hex].[ext]'],
      },
      {
        use: ['file-loader?name=[md5:hash:hex].[ext]'],
      },
    ],
}

It tries to match images with the srcset-loader if it can find any sizes/placeholder options; or use directly the file-loader if no parameter has been found.

Although this setup works well with static requirement paths, I can't make it work with dynamic paths, while the standalonefile-loader works fine in the same conditions:

require('./assets/image.jpeg'); // works (returns image url)
require('./assets/image.jpeg?sizes=default+10w'); // works (return Object with srcset properties...)

const filename = 'image.jpeg';
require(`./assets/${filename}`); // works (as before, returns image url)
require(`./assets/${filename}?sizes=default+10w`); // does not work ?! (Error: Cannot find module at webpackMissingModule...)

'ratio' should be promoted

In my opinion ratio shouldn't be at img.placeholder.ratio but instead promoted to img.ratio. It's a property of the original image, not just of the placeholder, and is useful even when not using the placeholder.

For example, browsers like when width and height attributes are given, since it means the page can be laid out sooner. This can be done with the ratio and a reference size:

<!-- current ratio implementation (ratio=height/width) -->
<img ... width="250" height="{{Math.round(250 * img.placeholder.ratio)}}">

<!-- ratio implementation from #16 (ratio=width/height) -->
<img ... width="250" height="{{Math.round(img.placeholder.ratio / 250)}}">

I think this should be possible even if the placeholder is not being calculated.

Can ?placeholder give us the raw image instead of an svg one ?

Instead of exporting a .svg containing a base64-encoded image, can you just export the base64-encoded image itself ?

The reasoning behind my request is that we might want to do something else than blur the tiny image, or do an animation on the svg itself.
Also, adding the blur after importing the image might reduce the bundle size as the svg part wouldn't be repeated in every image module.

Thank you :)

Support for CSS `image-set` ?

This is more a discussion on how feasible it would be than a feature request

Some browser support defining responsive images in CSS, it would be nice if there was a way to write them as easily as it currently is in JS.

Unfortunately, CSS is a little less flexible when it comes to processing data at runtime. So anything the loader returns should be a string in this case.

Currently, the only way I would see it work is by declaring every size manually

background: image-set(
  url('foo.png?sizes=200w') 1x,
  url('foo.png?sizes=400w') 2x,
  // ...
);

It isn't as short and simple as the JS version, but it would work and would at least automate the resizing part.

The main problem I have with it is that currently, this query would return an object containing exactly one size instead of a string. Changing the behavior to return a string when there is only one size and no placeholder would mean another breaking change and an inconsistent API, which I'm not sure I like.

Any ideas ? Should image-sets be supported by this loader ?

Broken images

Hello,
srcset-loader is returning appropriate output but the images created are broken. I have asked for help on Stackoverflow
Any help is appreciated.

srcset-loader embeds webpack config in final bundle

Versions:

image-webpack-loader 3.4.2
srcset-loader 2.2.2
webpack 3.6.0

This is my loader setup for image files, pairing srcset-loader with image-webpack-loader

rules: [
  {
    test: /\.(gif|png|jpe?g)$/i,
    use: [
      {
        loader: 'srcset-loader',
        options: { placeholder: 20 },
      },
      'file-loader',
      {
        loader: 'image-webpack-loader',
        options: {
          gifsicle: {
            interlaced: false,
          },
          optipng: {
            optimizationLevel: 7, // 0 = light; 7 = heavy
          },
          pngquant: {
            quality: '50-70', // min-max
            speed: 1, // 1 = heavy, slow; 10 = light, fast
          },
          mozjpeg: {
            progressive: true,
            quality: 60, // 0–100
          },
        },
      },
    ],
  },
],

This is what gets output in my minified, production bundle (truncated):

!function(){"use strict";var a=!("undefined"==typeof window||!window.document||!window.document.createElement),i={canUseDOM:a,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:a&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:a&&!!window.screen};void 0!==(o=function(){return i}.call(t,s,t,e))&&(e.exports=o)}()},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/about/office-1.jpg?size=1200w':function(e,t,s){e.exports=s.p+"b217f778359d9336d52e5d336cb37758.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/about/why-communication.jpg?size=1200w':function(e,t,s){e.exports=s.p+"80762ad981e793729ccf31f9e7d6b3b9.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/home/about.jpg?size=1200w':function(e,t,s){e.exports=s.p+"c326908c3e343268ed4b989d3d542eb8.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/home/colophon.jpg?size=1200w':function(e,t,s){e.exports=s.p+"bda3dd6e38f004c766240672be17f118.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/home/services.jpg?size=1200w':function(e,t,s){e.exports=s.p+"b23b6ef61ff996dba199a18253aa9c99.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/services/deliver.jpg?size=1200w':function(e,t,s){e.exports=s.p+"acbbf4dc37da8ba74b268a093b2ea5b4.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/services/discover.jpg?size=1200w':function(e,t,s){e.exports=s.p+"d7bcade20f4789a3c51a83c9d7ec5f94.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/social/envy-labs-animated.gif?size=1200w':function(e,t,s){e.exports=s.p+"ee6a1f3f78d336d9e1577df409ad07fc.gif"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/social/og-about.gif?size=1200w':function(e,t,s){e.exports=s.p+"fa576abe3fc37d446e77ae2f2db66df5.gif"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/social/og-contact.gif?size=1200w':function(e,t,s){e.exports=s.p+"cc450f661eba5dc871db0631fc7dcb94.gif"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/social/og-home.gif?size=1200w':function(e,t,s){e.exports=s.p+"45c1557eabfb1b2853d6fb6fa75af460.gif"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/social/og-services.gif?size=1200w':function(e,t,s){e.exports=s.p+"608d682c6232ebc8cae6b9152a5b91d6.gif"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/social/og-work.gif?size=1200w':function(e,t,s){e.exports=s.p+"e369b49825063e71fe69933b827ac260.gif"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/work/cisco/cisco-cover.jpg?size=1200w':function(e,t,s){e.exports=s.p+"f7cdd3d897c27c51e75623d7eec482fa.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/work/code-school/code-school-cover.png?size=1200w':function(e,t,s){e.exports=s.p+"3e6d47de33e62bad312ef2810729631f.png"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/work/ivy/ivy-cover.jpg?size=1200w':function(e,t,s){e.exports=s.p+"3775e7883fc9f85129f96615042b757f.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/work/orlando-creators/orlando-creators-cover.jpg?size=1200w':function(e,t,s){e.exports=s.p+"db24c283fada3d1a296ba5ddef7f2aa7.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/work/real-thread/real-thread-cover.jpg?size=1200w':function(e,t,s){e.exports=s.p+"c936c585daa0e361e38dde6eb82c4a60.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1200!./assets/work/tech-rocket/tech-rocket-cover.jpg?size=1200w':function(e,t,s){e.exports=s.p+"b5328f2e859779bf82258406ae6d52c0.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1280!./assets/about/office-2.jpg?size=1280w':function(e,t,s){e.exports=s.p+"50b6b22590d8ab4645d9c2d301805997.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1280!./assets/about/office-3.jpg?size=1280w':function(e,t,s){e.exports=s.p+"432c5e95c6d770cd3d99955f15fef0a9.jpg"},'../node_modules/file-loader/dist/cjs.js!../node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}!../node_modules/srcset-loader/lib/resize-loader.js?size=1280!./assets/services/design-mobile.png?size=1280w':function(e,t,s){e.exports=s.p+"fdb910dc84e8dfb720d3833581d0d1c4.png"}

...

As you can see, hundreds of instances of node_modules/image-webpack-loader/index.js?{"gifsicle":{"interlaced":false},"optipng":{"optimizationLevel":7},"pngquant":{"quality":"50-70","speed":1},"mozjpeg":{"progressive":true,"quality":60}}! over and over and over again make it into the final production build. It’s actually taking up a significant portion of my codebase. While this gzips pretty efficiently with all the repetition, I’d rather it not be in the output as it doesn’t seem to be helping users.

The images themselves are optimized, minified, and spit out by srcset-loader just fine, but I’m wondering why all this makes it into my final bundle.

Is there any way to avoid this behavior?

webpack2 issue

Hi I'm on webpack2 and this regexp doesn't seem to work: /.*\.(jpe?g|png)\?sizes/
The query string apparently is never included in the test.

Sharp command failed;

Not sure what's going on, but when I do:
yarn add srcset-loader --dev

It fails, even though yarn add sharp --dev works. Maybe the version? Installing it straight uses version ^0.24.1

[12/12] ⠄ sharp
error /XXX/node_modules/sharp: Command failed.
Exit code: 1
Command: node-gyp rebuild
Arguments:
Directory: /XXX/node_modules/sharp
Output:
gyp info it worked if it ends with ok
gyp info using [email protected]
gyp info using [email protected] | darwin | x64
gyp info find Python using Python version 2.7.16 found at "/System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python"
gyp info spawn /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
gyp info spawn args [
gyp info spawn args   '/usr/local/Cellar/node/13.8.0/libexec/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args   'binding.gyp',
gyp info spawn args   '-f',
gyp info spawn args   'make',
gyp info spawn args   '-I',
gyp info spawn args   '/XXX/node_modules/sharp/build/config.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/usr/local/Cellar/node/13.8.0/libexec/lib/node_modules/npm/node_modules/node-gyp/addon.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/XXX/Caches/node-gyp/13.8.0/include/node/common.gypi',
gyp info spawn args   '-Dlibrary=shared_library',
gyp info spawn args   '-Dvisibility=default',
gyp info spawn args   '-Dnode_root_dir=/XXX/Library/Caches/node-gyp/13.8.0',
gyp info spawn args   '-Dnode_gyp_dir=/usr/local/Cellar/node/13.8.0/libexec/lib/node_modules/npm/node_modules/node-gyp',
gyp info spawn args   '-Dnode_lib_file=/XXX/Library/Caches/node-gyp/13.8.0/<(target_arch)/node.lib',
gyp info spawn args   '-Dmodule_root_dir=/XXXb/node_modules/sharp',
gyp info spawn args   '-Dnode_engine=v8',
gyp info spawn args   '--depth=.',
gyp info spawn args   '--no-parallel',
gyp info spawn args   '--generator-output',
gyp info spawn args   'build',
gyp info spawn args   '-Goutput_dir=.'
gyp info spawn args ]
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
  TOUCH Release/obj.target/libvips-cpp.stamp
  CXX(target) Release/obj.target/sharp/src/common.o
In file included from ../src/common.cc:27:
../src/common.h:80:20: error: no member named 'Handle' in namespace 'v8'
  bool HasAttr(v8::Handle<v8::Object> obj, std::string attr);
               ~~~~^
../src/common.h:80:37: error: expected '(' for function-style cast or type construction
  bool HasAttr(v8::Handle<v8::Object> obj, std::string attr);
                          ~~~~~~~~~~^
../src/common.h:80:39: error: use of undeclared identifier 'obj'
  bool HasAttr(v8::Handle<v8::Object> obj, std::string attr);
                                      ^
../src/common.h:80:56: error: expected '(' for function-style cast or type construction
  bool HasAttr(v8::Handle<v8::Object> obj, std::string attr);
                                           ~~~~~~~~~~~ ^
../src/common.h:81:29: error: no member named 'Handle' in namespace 'v8'
  std::string AttrAsStr(v8::Handle<v8::Object> obj, std::string attr);
                        ~~~~^
../src/common.h:81:46: error: expected '(' for function-style cast or type construction
  std::string AttrAsStr(v8::Handle<v8::Object> obj, std::string attr);
                                   ~~~~~~~~~~^
../src/common.h:81:48: error: use of undeclared identifier 'obj'
  std::string AttrAsStr(v8::Handle<v8::Object> obj, std::string attr);
                                               ^
../src/common.h:81:65: error: expected '(' for function-style cast or type construction
  std::string AttrAsStr(v8::Handle<v8::Object> obj, std::string attr);
                                                    ~~~~~~~~~~~ ^
../src/common.h:82:37: warning: variable templates are a C++14 extension [-Wc++14-extensions]
  template<typename T> v8::Local<T> AttrAs(v8::Handle<v8::Object> obj, std::string attr) {
                                    ^
../src/common.h:82:48: error: no member named 'Handle' in namespace 'v8'
  template<typename T> v8::Local<T> AttrAs(v8::Handle<v8::Object> obj, std::string attr) {
                                           ~~~~^
../src/common.h:82:65: error: expected '(' for function-style cast or type construction
  template<typename T> v8::Local<T> AttrAs(v8::Handle<v8::Object> obj, std::string attr) {
                                                      ~~~~~~~~~~^
../src/common.h:82:67: error: use of undeclared identifier 'obj'
  template<typename T> v8::Local<T> AttrAs(v8::Handle<v8::Object> obj, std::string attr) {
                                                                  ^
../src/common.h:82:84: error: expected '(' for function-style cast or type construction
  template<typename T> v8::Local<T> AttrAs(v8::Handle<v8::Object> obj, std::string attr) {
                                                                       ~~~~~~~~~~~ ^
../src/common.h:82:89: error: expected ';' at end of declaration
  template<typename T> v8::Local<T> AttrAs(v8::Handle<v8::Object> obj, std::string attr) {
                                                                                        ^
                                                                                        ;
../src/common.h:82:90: error: expected unqualified-id
  template<typename T> v8::Local<T> AttrAs(v8::Handle<v8::Object> obj, std::string attr) {
                                                                                         ^
../src/common.h:85:26: warning: variable templates are a C++14 extension [-Wc++14-extensions]
  template<typename T> T AttrTo(v8::Handle<v8::Object> obj, std::string attr) {
                         ^
../src/common.h:85:37: error: no member named 'Handle' in namespace 'v8'
  template<typename T> T AttrTo(v8::Handle<v8::Object> obj, std::string attr) {
                                ~~~~^
../src/common.h:85:54: error: expected '(' for function-style cast or type construction
  template<typename T> T AttrTo(v8::Handle<v8::Object> obj, std::string attr) {
                                           ~~~~~~~~~~^
../src/common.h:85:56: error: use of undeclared identifier 'obj'
  template<typename T> T AttrTo(v8::Handle<v8::Object> obj, std::string attr) {
                                                       ^
../src/common.h:85:73: error: expected '(' for function-style cast or type construction
  template<typename T> T AttrTo(v8::Handle<v8::Object> obj, std::string attr) {
                                                            ~~~~~~~~~~~ ^
../src/common.h:85:78: error: expected ';' at end of declaration
  template<typename T> T AttrTo(v8::Handle<v8::Object> obj, std::string attr) {
                                                                             ^
                                                                             ;
fatal error: too many errors emitted, stopping now [-ferror-limit=]
2 warnings and 20 errors generated.
make: *** [Release/obj.target/sharp/src/common.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/local/Cellar/node/13.8.0/libexec/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:194:23)
gyp ERR! stack     at ChildProcess.emit (events.js:321:20)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)
gyp ERR! System Darwin 19.4.0
gyp ERR! command "/usr/local/Cellar/node/13.8.0/bin/node" "/usr/local/Cellar/node/13.8.0/libexec/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /XXX/node_modules/sharp

"ratio" output is inverted

For a portrait image (500 wide, 634 tall) I'm getting back a ratio from myimg.placeholder.ratio of 1.268. This is backwards. Aspect ratios are usually presented as width divided by height, so this should be 500/634, not the other way around.

Update sharp to v0.20.0

sharp v0.20.0 was recently released, which can provide pre-built binaries. That fixes installation issues in complicated build environments, and makes for hella faster Docker builds, with fewer requirements. Yay!

Only one file included in webpack manifest

Is there any way to include all of the resized images in the manifest? Currently because it's keyed by source filename only one of the files is listed as they all share the same source filename.

Perhaps something like appending #size=300 so they look like different source files.

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.