JSPM

  • Created
  • Published
  • Downloads 1172
  • Score
    100M100P100Q109073F
  • License MIT

Yet another babel plugin that lets you freely customize polyfills.

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (babel-plugin-polyfill-custom) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    Babel Plugin Polyfill Custom

    github sponsors npm MIT License standard-readme compliant

    Yet another babel plugin that lets you freely customize polyfills.

    Table of Contents

    Background

    There are several ways to insert polyfill via babel, including @babel/preset-env and @babel/transform-runtime. Recently, babel-plugin-polyfill-es-shims and others have been created to provide more options other than core-js.

    On the other hand, core-js and es-shims are specialized for ECMAScript polyfills, and there is a lack of DOM API polyfills.

    babel-plugin-polyfill-custom allows you to set any polyfills you want.

    For example, if you want to insert a polyfill for fetch, you can choose whatwg-fetch or unfetch. When considering a polyfill for Promise, you can also choose an alternative other than core-js, such as Zousan, Yaku, or Aigle.

    In addition, babel-plugin-polyfill-custom can determine which polyfill is needed based on the browsers listed in the browserslist. This is highly beneficial when using the differencial bundle serving.

    Install

    npm install --dev @babel/core babel-plugin-polyfill-custom

    ⚠️ This plugin cannot transpile ECMAScript syntax. If you want to use new ECMAScript syntax, please use @babel/preset-env together.

    Using with a bundler

    babel-plugin-polyfill-custom inserts polyfill using base64 data URIs. When used with a bundler, the bundler should be able to recognize base64 data URIs.

    webpack

    webpack 5.38.0 or later supports data scheme.

    const config = {
      module: {
        rules: [
          {
            mimetype: 'text/javascript',
            scheme: 'data',
            type: 'javascript/auto',
          },
          {
            test: /\.js$/,
            use: [
              {
                loader: 'babel-loader',
                options: {
                  ...,
                },
              },
            ],
          },
        ],
      },
    };

    Rollup

    @rollup/plugin-data-uri needs to be loaded.

    const { babel } = require('@rollup/plugin-babel');
    const dataUri = require('@rollup/plugin-data-uri');
    const { nodeResolve } = require('@rollup/plugin-node-resolve');
    const commonjs = require('@rollup/plugin-commonjs');
    
    const config = {
      plugins: [
        babel({
          ...,
        }),
        dataUri(),
        nodeResolve(),
        commonjs(),
      ],
    };

    Parcel

    Parcel does not have a feature to recognize base64 data URIs. You can create your own Parcel Resolver to recognize base64 data URIs.

    See ./examples/parcel for more details.

    {
      "extends": "@parcel/config-default",
      "resolvers": [
        // You should create resolver as parcel-resolver-data-uri.
        "parcel-resolver-data-uri",
        "@parcel/resolver-default"
      ]
    }

    Options

    You can find more examples in ./examples.

    const polyfills = {
      'polyfill:abort-controller': {
        features: ['api.AbortController'],
        packages: [
          {
            packageName: 'abort-controller/polyfill',
          },
        ],
      },
      'polyfill:fetch': {
        features: ['api.fetch', 'api.fetch.init_signal_parameter'],
        packages: [
          {
            definitions: {
              ['fetch']: 'fetch',
            },
            packageName: 'whatwg-fetch',
          },
        ],
      },
    };
    
    const config = {
      plugins: [
        [
          'polyfill-custom',
          {
            method: 'entry-global',
            polyfills,
          },
        ],
      ],
    };

    method

    entry-global is only supported.

    See https://github.com/babel/babel-polyfills#injection-methods.

    polyfills

    An Object for the definition of polyfill. A key of object is the identifier of the polyfill and is used as the package name when importing.

    // Source
    import 'polyfill:fetch';
    import 'polyfill:abort-controller';
    
    const abortController = new AbortController();
    
    fetch('https://example.com', {
      signal: abortController.signal,
    }).then(function (res) {
      if (!res.ok) {
        throw new Error('Failed to fetch: ' + String(res.status));
      }
      console.log(res);
    });
    // Transpiled
    import 'data:text/javascript;base64,aW1wb3J0e2ZldGNoIGFzIF9fZmV0Y2h9ZnJvbSJ3aGF0d2ctZmV0Y2giO3ZhciBleHBvcnRzPWZ1bmN0aW9uKCl7cmV0dXJuIHR5cGVvZiBnbG9iYWxUaGlzIT09InVuZGVmaW5lZCI/Z2xvYmFsVGhpczp0eXBlb2Ygc2VsZiE9PSJ1bmRlZmluZWQiP3NlbGY6dHlwZW9mIHdpbmRvdyE9PSJ1bmRlZmluZWQiP3dpbmRvdzp0eXBlb2YgZ2xvYmFsIT09InVuZGVmaW5lZCI/Z2xvYmFsOkZ1bmN0aW9uKCJyZXR1cm4gdGhpcyIpKCl9KCk7ZXhwb3J0cy5mZXRjaD1fX2ZldGNoOw==';
    import 'abort-controller/polyfill';
    
    const abortController = new AbortController();
    
    fetch('https://example.com', {
      signal: abortController.signal,
    }).then(function (res) {
      if (!res.ok) {
        throw new Error('Failed to fetch: ' + String(res.status));
      }
      console.log(res);
    });

    polyfills[ID].features

    A list of features that polyfill has. Fill in the @mdn/browser-compat-data identifier.

    For example, in the case of polyfill supporting the fetch API, the identifier is api.fetch.

    polyfills[ID].packages

    The definition of the package to be inserted as polyfill.

    packageName is the name of the package. definitions specifies which export variables are to be inserted as what global object.

    // To assign `import { Aigle } from 'aigle'` to `window.Promise`,
    // specify `Promise` on the left side and `Aigle` on the right side.
    {
      definitions: {
        ['Promise']: 'Aigle',
      },
      packageName: 'aigle',
    }
    // To assign `import matches from '@ungap/element-matches'` to `Element.prototype.matches`,
    // specify `Element.prototype.matches` on the left side and `default` on the right side.
    {
      definitions: {
        ['Element.prototype.matches']: 'default',
      },
      packageName: '@ungap/element-matches',
    }

    Contributing

    PRs accepted.

    License

    MIT (c) 3846masa