A Webpack plugin that works with Babel to allow differential loading - production deployment of ES2015 builds targeted to modern browsers, with an ES5 fallback for legacy browsers.
npm install webpack-babel-multi-target-plugin



This project, inspired by Phil Walton's article
Deploying es2015 Code in Production Today,
adds tooling to simplify the additional configuration with a
Webpack plugin, BabelMultiTargetPlugin.

Using the plugin requires making a few small changes to your existing webpack configuration:
* Replace any instances of 'babel-loader' with BabelMultiTargetPlugin.loader()
* Do not use a Loader configuration object here - see Options Reference
below for information on customizing options for 'babel-loader'
* Add a loader rule for .js files if there isn't one already:
``javascript`
{
test: /\.js$/,
use: [
BabelMultiTargetPlugin.loader(),
],
},
_Note:_ The above example intentionally does not exclude _node\_modules_.
* Set resolve.mainFields to favor modern ES modules, which allows webpack to load the most modern source possible.`
There are several intersecting de-facto standards flying around, so this should cover as much as possible:javascript
mainFields: [
// rxjs and Angular Package Format
// these are generally shipped as a higher ES language level than module
'es2015',
'esm2015',
'fesm2015',
// current leading de-facto standard - see https://github.com/rollup/rollup/wiki/pkg.module
'module',
// previous de-facto standard, superceded by module, but still in use by some packages
'jsnext:main',
// Angular Package Format - lower ES level
'esm5',
'fesm5',
// standard package.json fields
'browser',
'main',
],
`
* Add an instance of BabelMultiTargetPlugin to the webpackplugins
configuration's property
* BabelMultiTargetPlugin does not require any configuration - but can
be customized (see Options Reference below)
* Remove any .babelrc - see Options Reference below for setting preset options
* Remove any references to babel-loader from your package.json - it is a direct dependency ofwebpack-babel-multi-target-plugin
, and may cause unexpected issues if there are duplicate instances due toexclude
a version mismatch
* Remove any path or pattern matching _node\_modules_ from the BabelMultiTargetPlugin.loader()
property of any rules using
* TypeScript
* Loader rules must use BabelMultiTargetPlugin.loader() after your compiler loader (remember, loaders are run bottom to top)tsconfig
* Set to target es6 or higher
* Vue
* Replace 'vue-loader' with BabelMultiTargetPlugin.loader('vue-loader')expose-loader
* expose-loader
* Rules using must be defined _before_ rules using BabelMultiTargetPlugin.loader()import
* Do not /require libraries exposed with expose-loader - either reference them from the global scope,expose-loader
or do not use . You may also need to use Webpack's ProvidePlugin.
* Change usages of BabelMultiTargetPlugin.loader to BabelMultiTargetPlugin.loader()
When using ES6's import(...) syntax, you may use Webpack's built-in chunk naming syntax to control the naming
of the resulting chunk:
`typescript`
import(/ webpackChunkName: "my-dynamic-import" /'./some-other-module')
When working with imports that use an expression within the import syntax, BabelMultiTargetPlugin adds the [resource][resource]
tag to allow better control over the naming of the resulting chunk. The tag will be replaced by the
relative path of the imported module, minus the file extension.
`typescript
/*
* ./src/
* - plugins
* - a
* plugin.js
* - b
* plugin.js
*
*/
// ./src/loader.js
import(/ webpackChunkName: "[resource]" /./plugins/${plugin}/plugin.js)`
In the above example, the resulting chunks for the plugin files would be (depending on the target configuration):
* a-plugin.js (legacy bundle for ./src/plugins/a/plugin.js)a-plugin.modern.js
* (modern bundle for ./src/plugins/a/plugin.js)b-plugin.js
* (legacy bundle for ./src/plugins/b/plugin.js)b-plugin.modern.js
* (modern bundle for ./src/plugins/b/plugin.js)
Adding the included NamedLazyChunksPlugin will allow similar human-friendly chunk naming for Angular lazy routes:
`javascript
// webpack.config.js
const BabelMultiTargetPlugin = require('webpack-babel-multi-target-plugin').BabelMultiTargetPlugin
const NamedLazyChunksPlugin = require('webpack-babel-multi-target-plugin').NamedLazyChunksPlugin
module.exports = {
...
plugins: [
new BabelMultiTargetPlugin(),
new NamedLazyChunksPlugin(),
],
}
`
NamedLazyChunkPlugin can also be used with plain ES6 Dynamic Imports as an alternative to Webpack's chunk naming
syntax.
BabelMultiTargetPlugin does not require any options to be set. The
default behavior is:
* Generate "modern" and "legacy" bundles.
* The "modern" bundle assets will have their filenames appended with
.modern, while the "legacy" bundle assets will remain the same. This
enables these assets to be deployed without breaking anything since it
will still have the required polyfills.
* "modern" browsers are the last 2 versions of each browser, excluding
versions that don't support