Pre-release

@eduardoboucas eduardoboucas released this Mar 8, 2018 · 412 commits to develop since this release

Assets 2

New features

Plugin support

CDN 2.0 introduces a new plugin system. A plugin is defined as a JavaScript file placed inside the plugins workspace directory, configurable via the paths.plugins configuration parameter.

CDN plugins can be executed at different points in the lifecycle of a request, determining if and how the response will be affected.

Plugin types

Pre-processing plugins

Executed before an image starts being processed. The plugin can change any manipulation parameters contained in the options object before the image is processed.

Example:

// sets a size of 200x200 and a resize style of "entropy"
// if the image contains "mountain.jpg"
module.exports.pre = ({options, url}) => {
  if (url.contains('mountain.jpg')) {
    options.width = 200
    options.height = 200
    options.resizeStyle = 'entropy'
  }
}

Post-processing plugins

Executed after an image has been processed and before the result is delivered to the client. Plugins can use the instance of the Sharp engine (processor) to run additional operations on the existing stream. Alternatively, they can return a Promise with a new stream, should they want to perform operations not supported by Sharp.

Example:

// Using Sharp to apply a blur of "15" to the image
module.exports.post = ({assetStore, cache, jsonData, options, processor, sharp, stream, url}) => {
  processor.blur(15)
}

For a more complex example of a post-processing plugin, check duotone-plugin.js.

Controller plugins

Receive a raw request and are responsible for fetching and processing any assets, as well as forming and delivering the response.

A good example of how a controller plugin can be used is to replace the concept of processors, available in the previous major version of CDN. This link shows an implementation of the layout processor using a controller plugin, making it completely backwards-compatible.

Using plugins

Pre-processing and post-processing plugins must be attached to a recipe. This is done by adding a plugins property with an array of plugin names to the recipe JSON file. For example, the following recipe would execute plugin-1.js and plugin-2.js, in that order.

{
  "recipe": "test-recipe",
  "plugins": ["plugin-1", "plugin-2"],
  "settings": {
    "format": "jpg",
    "quality": "80",
    "flip":"xy"
  }
}

Controller plugins have a route of their own, so a plugin named plugin-3.js generates a route like http://cdn.your-domain.org/plugin-3.

Closes #168

On-demand JavaScript transpiling

CDN 2.0 introduces experimental support for on-demand JavaScript transpiling based on user-agent. Traditionally, web developers that wish to use modern JavaScript features resort to transpiling – i.e. translating an ES6 or ES7 bundle to ES5 code so that older browsers can interpret it. This is typically done at build time, creating an ES5 bundle that is served to browsers.

The downside of this is that this translated bundle will be served to everyone, even to modern browsers that support all the original features, and therefore not benefiting from the advantages of the modern code. To address this, CDN analyses the user agent of the client and transpiles only the features that the browser does not natively support.

This is fairly uncharted territory and we're still testing the waters regarding what can and can't be done in the space; we've decided to make this feature available to the community as an experimental (and potentially unstable) feature, sitting behind a feature flag.

To enable it, add the following configuration parameter:

"experimental": {
  "jsTranspiling": true
}

Alternatively you can run CDN with the JSTRANSPILING="true" environment variable.

To enable transpiling for an asset, use the transform URL parameter as such:

http://cdn.your-domain.org/es6-file.js?transform=1

Serve any type of asset

CDN 2.0 introduces a generic asset handler that is capable of serving any type of file, with support for caching and with the delivery of the correct mime type

The source of these files is configurable using the existing assets block in the main configuration file, and assets can be requested simply by specifying their path.

For example, a file stored at assets/file.pdf can be requested using a URL such as http://cdn.your-domain.org/file.pdf.

WebP support

CDN 2.0 adds support for the WebP format:

WebP is a modern image format that provides superior lossless and lossy compression for images on the web. Using WebP, webmasters and web developers can create smaller, richer images that make the web faster.

WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller than comparable JPEG images at equivalent SSIM quality index.

Closes #259

Simplified paths for non-image assets

Using CDN 1.x, the URL format for accessing assets such as JS and CSS files is:

http://cdn.somedomain.tech/{TYPE}/{COMPRESS}/file-path.js

CDN 2.0 introduces a new, simplified URL format in line with that used for images. Whilst the above is still valid (but deprecated), the following is now accepted.

http://cdn.somedomain.tech/file-path.js
http://cdn.somedomain.tech/file-path.js?compress=1
http://cdn.somedomain.tech/another-file-path.css

Breaking changes

Preserving aspect ratio from original image (#255)

In CDN 1.x, any image dimensions missing from the URL were taken directly from the original image. For example, given a 1000x400 image, a request for /image.jpg?width=500 would yield a 500x400 output – width of 500 obtained from the URL parameters, height is missing from the URL so the 400 from the original image is used. This effectively meant a cropped image.

With CDN 2.x, any missing dimensions from the URL are calculated in such a way that the aspect ratio of the original image is always preserved. As such, a request for /image.jpg?width=500 would result in a 500x200 output, maintaining the aspect ratio and not cropping the image.

Note that the new behaviour only applies to requests where the aspect ratio is not specified in the URL. A cropped image will still be obtained if both dimensions are specified (e.g. /image.jpg?width=500&height=400), if a ratio parameter is supplied (e.g. /image.jpg?width=500&ratio=5-4) or if the resize style is set to aspectfill (e.g. /image.jpg?width=500&resizeStyle=aspectfill).

Changed

  • #282: deliver the fallback image even when crop is present
  • #283: use correct dimensions when original or calculated size is above the configured security limit
  • #291: cache JSON response of images, in the same way as the actual images are
  • refactor parts of the code base to use ES6 features
  • fix an issue where the gravity URL parameter was not applied correctly
  • fix an issue whereby it was not possible to minify JavaScript files that contain ES6 code
  • begin removal of Underscore.js dependency

Legacy URL support

Support for the legacy URL format will be removed in the next major version of CDN. If a legacy URL format is received by the version of CDN it will log a warning as follows:

'/jpg/50/0/0/801/478/0/0/0/2/aspectfit/North/0/0/0/0/0/mountain.jpg': this request uses a deprecated URL format which will be removed from future versions of DADI CDN. For more information, please visit https://docs.dadi.tech/cdn#querystring-url-scheme.`