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 体积成本。
不建议使用
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';
npm i babel-loader @babel/core @babel/preset-env -D
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 文件体积已缩小!