All Projects → SebastianS90 → Webpack Polyfill Injector

SebastianS90 / Webpack Polyfill Injector

Licence: mit
Webpack plugin to automatically inject polyfills into your bundle without affecting modern browsers.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Webpack Polyfill Injector

React Router Animation Examples
An example using React Router and React's Animations
Stars: ✭ 80 (-4.76%)
Mutual labels:  webpack
Web React
💠 Another React Dev Kit with Webpack and NodeJS
Stars: ✭ 82 (-2.38%)
Mutual labels:  webpack
Tkframework
react + relay + redux + saga + graphql + webpack
Stars: ✭ 83 (-1.19%)
Mutual labels:  webpack
Multi Page App With React
🔧 A lightweight, flexible webpack setup with React for multi page application development
Stars: ✭ 82 (-2.38%)
Mutual labels:  webpack
React Webpack Babel
Simple React Webpack Babel Starter Kit
Stars: ✭ 1,241 (+1377.38%)
Mutual labels:  webpack
Laravel Blog
Laravel 8.0 blog application with Vue.js, Homestead, Horizon, Telescope and Pusher
Stars: ✭ 1,248 (+1385.71%)
Mutual labels:  webpack
Alias Hq
The end-to-end solution for configuring, refactoring, maintaining and using path aliases
Stars: ✭ 77 (-8.33%)
Mutual labels:  webpack
Graphql Import Loader
Webpack loader for `graphql-import`
Stars: ✭ 84 (+0%)
Mutual labels:  webpack
Hactar
The solution to JavaScript Fatigue. Zero config dev
Stars: ✭ 82 (-2.38%)
Mutual labels:  webpack
Inline Chunk Manifest Html Webpack Plugin
Extension plugin for html-webpack-plugin to inline webpack's chunk manifest. Default inlines in head tag.
Stars: ✭ 83 (-1.19%)
Mutual labels:  webpack
Semaphore Ng2 Webpack
Stars: ✭ 81 (-3.57%)
Mutual labels:  webpack
Easy Pack
Webpack, Ahhhhhhh .... Take Easy
Stars: ✭ 82 (-2.38%)
Mutual labels:  webpack
Google Fonts Plugin
Webpack plugin that downloads fonts from Google Fonts and encodes them to base64
Stars: ✭ 83 (-1.19%)
Mutual labels:  webpack
Page Builder
自定义页面构建平台
Stars: ✭ 81 (-3.57%)
Mutual labels:  webpack
React D3 Transitions
Enter, update and exit pattern using React 15.0, D3 4.0 and Redux
Stars: ✭ 83 (-1.19%)
Mutual labels:  webpack
Jhipster5 Demo
Get Started with JHipster 5 Tutorial and Example
Stars: ✭ 80 (-4.76%)
Mutual labels:  webpack
Micro Frontends Practice
基于qiankun的微前端实践,提供更为简单、完整的项目。react/vue demo已完成
Stars: ✭ 83 (-1.19%)
Mutual labels:  webpack
Add Asset Webpack Plugin
Dynamically add an asset to the Webpack graph
Stars: ✭ 84 (+0%)
Mutual labels:  webpack
Lit Loader
LitElement Single File Component loader for Webpack.
Stars: ✭ 84 (+0%)
Mutual labels:  webpack
Bottle Vue Kickstart
🍕 Very basic Bottle kickstart kit with Vue.js and Webpack. Included Axios, Autoprefixer, Babel, Webpack config, demo app with Bulma and Web font loader.
Stars: ✭ 83 (-1.19%)
Mutual labels:  webpack

npm deps test coverage

Webpack Polyfill Injector Plugin

This plugin uses polyfills from polyfill-library and inserts them into your bundle.

The benefits of this plugin are:

  • Users with modern browsers will not be punished:
    • The script size increases only by some very small checks to see if the browser supports all required features natively (i.e. no polyfills are necessary)
    • If all required features are supported natively, then there is no additional HTTP request.
  • It does not rely on an external service (e.g. a CDN). All scripts will be included in your bundle.
    • Failures of external services providing polyfills won't affect your users.
    • Serving all scripts from the same domain avoids problems with browser-plugins like NoScript or uMatrix.
  • If a browser does not support some features, then only the polyfills required for that specific browser are loaded, all together in a single additional HTTP request.
    • All possible combinations of polyfills will be bundled as separate files. No magic at runtime! The files can be served by any dumb webserver.
    • If you don't feel well with 2^n - 1 bundled files for n polyfills, then there is an option to only bundle a single file containing all n polyfills. All browsers that are missing any feature will have to load this file, potentially wasting bandwith on unnecessary polyfills.
  • The plugin even works for the Promise polyfill. Webpack's chunk loading internally uses Promise, therefore this plugin implements its own loading technique.

Install

Note: The current version of this plugin requires webpack 4, for older webpack please use ^1.0.2.

yarn add webpack-polyfill-injector --dev

or

npm install webpack-polyfill-injector --save-dev

Usage

const PolyfillInjectorPlugin = require('webpack-polyfill-injector');

module.exports = {
    entry: {
        app: `webpack-polyfill-injector?${JSON.stringify({
            modules: ['./resources/js/app.js'] // list your entry modules for the `app` entry chunk
        })}!` // don't forget the trailing exclamation mark!
    },
    output: {...},
    module: {...},
    plugins: [
        new PolyfillInjectorPlugin({
            polyfills: [
                'Promise',
                'Array.prototype.find',
            ]
        })
    ]
};

You always need to use webpack-polyfill-injector as loader in your entry chunks and as plugin in the plugin array. They both take an options object as argument, where the plugin options specify default settings that the loader can override.

Loader and plugin work hand-in-hand as follows:

  • The loader creates a small module that checks whether any of the specified polyfills are required.
    • If the browser supports all required features natively, then the entry modules are executed directly (by doing require(...) for every module listed in the modules option.)
    • If the browser misses some features, then the appropriate polyfill file will be loaded (by inserting a new script tag to the head of the html page). Afterwards, your entry modules will be executed.
    • It is possible to use the loader multiple times with different configurations, for example to inject polyfills into several entry chunks, possibly with different lists of polyfills.
  • The plugin emits the files containing the polyfills.

Options

The following options can be specified (for both loader and plugin, where loader options override plugin options):

Option Type Default Description
polyfills Array of Strings none List of features that are required. Browsers will load polyfills for all features that are not supported natively.
You can use any polyfill from polyfill-library. See also this list, but keep in mind that webpack-polyfill-injector creates staticly bundled files and therefore does not use the User-Agent string to determine which polyfills will be required, neither is there a default set. You need to explicitly list everything that is required by your application code.
modules Array of Strings none List of modules that are part of the current entry chunk. If you used to have {name: ["./file1.js", "./file2.js"]} as entry point then you will configure {name: 'webpack-polyfill-injector?{modules:["./file1.js","./file2.js"]}!'}.
You can specify anything that can also be written inside a require() call, e.g. 'my-awesome-loader!./some-file.js'.
excludes Array of Strings [] List of polyfills that should not be added even though another polyfill depends on it.
singleFile Boolean false Whether to create only a single file for all polyfills instead of 2^n - 1 files (one per subset). This will decrease your bundle size, but increase the bandwidth usage for browsers that support some (but not all) features natively.
filename String output.filename The path and filename for generated polyfill files. The default is to use whatever is specified in output.filename. Make sure to include the [name] placeholder or use different filename settings if the list of polyfills differs between some entry chunks.
banner String '/*! For detailed credits and licence information see https://github.com/financial-times/polyfill-library */\n' The banner that is inserted on the top of all generated polyfill files.

Technical Details

Consider the configuration:

{
    entry: {
        app: `webpack-polyfill-injector?${JSON.stringify({
            modules: [
                './your/first/module/for/this/entry.js',
                './your/second/module/for/this/entry.js'
            ]
        })}!`
    },
    output: {
        filename: `js/[name].js`,
        publicPath: '/'
    },
    plugins: [
        new PolyfillInjectorPlugin({
            polyfills: [
                'Promise',
                'Array.prototype.find',
            ]
        })
    ]
}

The loader creates this entry module in js/app.js:

function main() {
    require('./your/first/module/for/this/entry.js');
    require('./your/second/module/for/this/entry.js');
}
var polyfills = function() {
    return [
        /* Promise */ ('Promise' in this) ? 0 : 1,
        /* Array.prototype.find */ ('find' in Array.prototype) ? 0 : 1
    ];
}.call(window);
if (polyfills.indexOf(1) === -1) {
    main();
} else {
    var js = document.createElement('script');
    js.src = "/js/polyfills." + polyfills.join('') + '.js';
    js.onload = main;
    js.onerror = function onError(message) {
        console.error('Could not load the polyfills: ' + message);
    };
    document.head.appendChild(js);
}

The plugin creates the files js/polyfills.01.js (containing the Array.prototype.find polyfill), js/polyfills.10.js (containing the Promise polyfill), and js/polyfills.11.js (containing both polyfills).

If a single polyfill file is created (singleFile option or only one polyfill specified), then the code generated by the loader simplifies:

function main() {
    require('./your/first/module/for/this/entry.js');
    require('./your/second/module/for/this/entry.js');
}
if (function() {
    return /* Promise */ !('Promise' in this) ||
        /* Array.prototype.find */ !('find' in Array.prototype);
}.call(window)) {
    var js = document.createElement('script');
    js.src = "/js/polyfills.js";
    js.onload = main;
    js.onerror = function onError(message) {
        console.error('Could not load the polyfills: ' + message);
    };
    document.head.appendChild(js);
} else {
    main();
}

Note that in both cases, the detectors are wrapped in a function which is bound to window. This is due to some detectors using this instead of window, e.g. Promise tests 'Promise' in this.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].