webpack高级应用篇(十一):Polyfills

Polyfills

npm install --save @babel/polyfill

然后,使用 import 将其引入到我们的主 bundle 文件:

import '@babel/polyfill'
console.log(Array.from([1, 2, 3], x => x + x))

注意,这种方式优先考虑正确性,而不考虑 bundle 体积大小。

为了安全和可靠,polyfill/shim 必须运行于所有其他代码之前,而且需要同步加载,或者说,需要在所有 polyfill/shim 加载之后,再去加载所有应用程序代码。

社区中存在许多误解,即现代浏览器“不需要”polyfill,或者 polyfill/shim 仅用于添加缺失功能 - 实际上,它们通常用于修复损坏实现(repair broken implementation),即使是在最现代的浏览器中,也会出现这种情况。

因此,最佳实践仍然是,不加选择地和同步地加载所有polyfill/shim,尽管这会导致额外的 bundle 体积成本。

进一步优化Polyfills

不建议使用 import @babel/polyfilll 方式。因为这样做的缺点是会全局引入整个polyfill包,比如 Array.from 会全局引入,不但包的体积大,而且还会污染全局环境。

babel-preset-env package 通过 browserslist 来转译那些你浏览器中不支持的特性。这个 preset 使用 useBuiltIns 选项,默认值是 false ,这种方式可以将全局 babel-polyfill 导入,改进为更细粒度的 import 格式:

import 'core-js/modules/es7.string.pad-start';
import 'core-js/modules/es7.string.pad-end';
import 'core-js/modules/web.timers';
import 'core-js/modules/web.immediate';
import 'core-js/modules/web.dom.iterable';
  • 安装 @babel/preset-env 及 相关的包
npm i babel-loader @babel/core @babel/preset-env -D
  • webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  plugins: [new HtmlWebpackPlugin()],
  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
                targets: [ // 告诉@babel/preset-env遇到了这样的浏览器需要通过Polyfills使用添加垫片
                  '> 1%',
                  'last 1 version',
                ],
                useBuiltIns: 'usage',
              },
            ],
          ],
        },
      },
    }],
  },
};

useBuiltIns: 参数有 “entry”“usage”false 三个值

默认值是 false ,此参数决定了babel打包时如何处理 @babel/polyfilll 语句。

"entry": 会将文件中 import '@babel/polyfilll' 语句 结合 targets ,转换为一系列引入语句,去掉目标浏览器已支持的 polyfilll 模块,不管代码里有没有用到,只要目标浏览器不支持都会引入对应的 polyfilll 模块。

"usage": 不需要手动在代码里写 import '@babel/polyfilll' ,打包时会自动根据实际代码的使用情况,结合 targets 引入代码里实际用到部分 polyfilll 模块

false:import '@babel/polyfilll' 不作任何处理,也不会自动引入 polyfilll 模块。需要注意的是在 webpack 打包文件配置的 entry 中引入的 @babel/polyfill 不会根据 useBuiltIns 配置任何转换处理。

由于 @babel/polyfill 在7.4.0中被弃用,我们建议直接添加corejs并通过corejs选项设置版本。

执行编译 npx webpack

HuaJi:step_11-Polyfills HuaJi$ npx webpack

WARNING (@babel/preset-env): We noticed you're using the `useBuiltIns` option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in future versions of Babel, we recommend explicitly setting the core-js version you are using via the `corejs` option.

You should also be sure that the version you pass to the `corejs` option matches the version specified in your `package.json`'s `dependencies` section. If it doesn't, you need to run one of the following commands:

  npm install --save core-js@2    npm install --save core-js@3
  yarn add core-js@2              yarn add core-js@3

More info about useBuiltIns: https://babeljs.io/docs/en/babel-preset-env#usebuiltins
More info about core-js: https://babeljs.io/docs/en/babel-preset-env#corejs

  When setting `useBuiltIns: 'usage'`, polyfills are automatically imported when needed.
  Please remove the direct import of `@babel/polyfill` or use `useBuiltIns: 'entry'` instead.
asset main.js 16.8 KiB [emitted] [minimized] (name: main)
asset index.html 214 bytes [emitted]
runtime modules 663 bytes 3 modules
modules by path ../../node_modules/core-js/modules/*.js 38.9 KiB 68 modules
./src/index.js 346 bytes [built] [code generated]
webpack 5.65.0 compiled successfully in 2242 ms

出现警告:useBuiltIns 需要使用 core-js 翻译器。安装 core-js

npm i core-js@3 -S

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  plugins: [new HtmlWebpackPlugin()],
  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
                targets: [ // 告诉@babel/preset-env遇到了这样的浏览器需要通过Polyfills使用添加垫片
                  '> 1%',
                  'last 1 version',
                ],
                useBuiltIns: 'usage',
                corejs: 3, // 添加corejs配置
              },
            ],
          ],
        },
      },
    }],
  },
};

执行 npx webpack

在这里插入图片描述

看到警告,当设置 'useBuiltIns: 'usage' 时,polyfills 会在需要时自动导入。
请删除 '@babel/polyfill' 的直接导入或使用 'useBuiltIns: 'entry' 代替。

删除 import '@babel/polyfill'

// import '@babel/polyfill';

console.log(Array.from([1, 2, 3], (x) => x + x));

再次执行 npx webpack

优化成功!打包出的 bundle 文件体积已缩小!

你可能感兴趣的:(Webpack,前端工程化,webpack,Polyfills,babel,useBuiltIns,corejs)