imgix / imgix.js

Responsive images in the browser, simplified
https://imgix.com
BSD 2-Clause "Simplified" License
965 stars 61 forks source link

imgix.js 3.0 #98

Closed kellysutton closed 8 years ago

kellysutton commented 8 years ago

Hi folks,

We'll be bumping imgix.js to 3.0 and introducing many performance improvements along with some breaking changes.

Below is the RFC from an internal process we ran to determine how to bring imgix.js into a more modern era where things like srcset now have wide support. @paulstraw, @jayeb, @gitmiggi, and I all collaborated on coming up with what's next for imgix.js.

We're planning on having this land the week of May 16, 2016, and implementation is already underway.

imgix.js 3.0 will still be a one-line drop-in to bring responsive imagery to your site and will be better than ever. 🏋


Summary

imgix.js is the JavaScript library used by many to deliver responsive imagery. This RFC is discussing the next major version of the project.

Motivation

In the past few months, the company has learned a lot more about delivering responsive imagery in a performant way. Some evidence of this:

Generally, imgix.js 1.x and 2.x pushed the envelope of what was possible with responsive imagery. Since its inception, browsers have caught up with their ability to offer a responsive image experience using static HTML, namely through increased support of srcset, the picture element, and Client Hints.

As it stands, much of the imgix.js functionality will actually contribute to a less performant experience, mostly due to the requirement of JavaScript.

For the purposes of imgix.js 3.0, it will be helpful to define a mission for imgix.js. The following is proposed: imgix.js should push the envelope of what's possible with responsive imagery online, but should not reimplement standards-based approaches or implicitly advocate less performant alternatives.

Thus, the goals of imgix.js 3.0 should be the following:

Given the mission of imgix.js proposed in Motivation, imgix.js 3.0 should be a thinning of functionality to better encapsulate only what is not currently possible with standards-based approaches or approaches with robust polyfills.

Thus, many of the things imgix.js currently does should go away, including:

This leaves only one piece of existing functionality:

As it exists currently, .fluid has several downsides:

.fluid itself should not be moved forward, but reimplemented in a way that solves these issues by using industry-standard best practices.

Many developers are aware of responsive imagery, but don't implement it for two reasons: The assets are difficult to generate, and the HTML is difficult/confusing/tedious to write. imgix provides an incredible solution for the asset generation side of the problem (srcset). In the case of pure resolution switching, a list of all potential derivatives can be easily generated programmatically. If art direction is needed, a single "template" for each style is all that needs to be defined, along with the sizes that style applies to. In all cases, we should default to sizes="100vw" (the browser default), but allow overrides and intelligently generate srcsets based on provided sizes when possible. This will provide a good balance between flexibililty, doing "the right thing" by default, and remaining very approachable. An example of what this implementation might look like can be seen in this imgix-rails pull request by @kellysutton.

A heavy focus of imgix.js 3.0 should be educating users about responsive imagery, how imgix helps solve it, and what the best way to handle images is for your app (which will often not be imgix.js). To this end, the introduction of the imgix.js readme (and other associated materials) should function as a primer, including lots of links to our own documentation and other great reads on the subject (particularly Eric Portis' seminal article on srcset and sizes).

Implementation

These approaches are a work in progress, and do not necessarily reflect exactly how imgix.js 3.0 will function.

img tag using ix-src

Written HTML Input

<img ix-src="https://assets.imgix.net/dogs.png?w=300&h=400&fit=crop">

Generated HTML Output

<img
  srcset="https://assets.imgix.net/dogs.png?w=100&h=75&fit=crop 100w,
          https://assets.imgix.net/dogs.png?w=200&h=150&fit=crop 200w,
          …
          https://assets.imgix.net/dogs.png?w=1200&h=900&fit=crop 1200w"
  src="https://assets.imgix.net/dogs.png?w=400&h=300&fit=crop"
  sizes="100vw"
>

img tag using ix-path and ix-params

Written HTML Input

<img ix-path="dogs.png" ix-params="{
  w: 400,
  h: 300,
  fit: 'crop'
}">

Generated HTML Output

<img
  srcset="https://assets.imgix.net/dogs.png?w=100&h=75&fit=crop 100w,
          https://assets.imgix.net/dogs.png?w=200&h=150&fit=crop 200w,
          …
          https://assets.imgix.net/dogs.png?w=1200&h=900&fit=crop 1200w"
  src="https://assets.imgix.net/dogs.png?w=400&h=300&fit=crop"
  sizes="100vw"
>

picture tag using ix-path and ix-params

Written HTML Input

<picture>
  <source media="(min-width: 800px)" ix-path="dogs.png" ix-params="{
    flip: 'h'
  }">
  <source ix-path="dogs.png" ix-params="{
    flip: 'v'
  }">
  <img src="https://assets.imgix.net/dogs.png?w=400&h=300">
</picture>

Generated HTML Output

<picture>
  <source media="(min-width: 800px)" sizes="100vw" srcset="
    https://assets.imgix.net/dogs.png?w=800&flip=h 800w,
    https://assets.imgix.net/dogs.png?w=900&flip=h 900w,
    …
    https://assets.imgix.net/dogs.png?w=5120&flip=h 5120w
  ">
  <source sizes="100vw" srcset="
    https://assets.imgix.net/dogs.png?w=100&flip=v 100w,
    https://assets.imgix.net/dogs.png?w=200&flip=v 200w,
    …
    https://assets.imgix.net/dogs.png?w=2400&flip=v 2400w
  ">
  <img src="https://assets.imgix.net/dogs.png?w=400&h=300">
</picture>

Drawbacks

imgix.js is in some ways a flagship product. It is the most-starred GitHub project that imgix has created to date.

imgix.js is also one of the most turn-key applications of imgix. By thinning the functionality of imgix.js, imgix may become more difficult to implement. To counter this, greater focus on framework-level libraries should be adopted (e.g. react-imgix, imgix-rails) so that integration responsive imagery into your application is still easy.

Alternatives

The alternative is to continue on that full-featured imgix.js 2.x path and compete with standards and polyfills.

Unresolved questions

gitmiggi commented 8 years ago

Does ix-params work as an override? So to enable fit=max Is there a way to handle variable cases? Like with quality? Changing quality based off of size?

gitmiggi commented 8 years ago

Will there still be methods to use the library like a front end application for editing images? i.e. for setting Params and not just as a responsive solution?

paulstraw commented 8 years ago

I'm not sure I follow your last question @gitmiggi. What do you mean "use the library like a front end application for editing images"?

oaleynik commented 8 years ago

@paulstraw I think @gitmiggi was asking about an ability to use setParam(<name>, <value>). If I remember correctly the first version had separated method for each param. In version 2.0 we've got generic setParam method. Will it be present in >=3.0?

Example from README:

var ix = new imgix.URL('http://assets.imgix.net/examples/butterfly.jpg');
ix.setParam('sepia', 50);
ix.setParam('rot', 20);
ix.getURL(); // equals http://assets.imgix.net/examples/butterfly.jpg?sepia=50&rot=20
paulstraw commented 8 years ago

Ah, no. This will not be part of 3.x. If someone needs to do URL generation in JS for something other than insertion into HTML tags, we'll likely be directing them toward imgix-core-js going forward. This is more in line with the direction all of our "language/framework" libraries are moving (e.g. imgix-rb/imgix-rails).

As an aside, we're also moving away from setParam-style URL generation in other libraries, preferring to just accept a hash (or hash-like construct in the given language). imgix-python 1.x is a good example of this.

oaleynik commented 8 years ago

@paulstraw makes sense for me. Always was wondering about existence of these two modules (imgix.js and imgix-core-js), which can do almost the same :)

Thanks!