面试题答案
一键面试可能导致问题的原因
- 全量引入:直接全量引入
polyfill
,包含了很多项目实际不会用到的特性填充,导致大量冗余代码被打包。 - 重复引入:在多个地方重复引入了相同的
polyfill
内容。 - 没有按需加载:没有根据目标浏览器的支持情况按需加载所需的
polyfill
。
优化 polyfill
引入策略的方法及配置操作
1. 使用 @babel/plugin-transform-runtime
- 原理:该插件会将
Babel
转译过程中使用到的辅助函数(helper)和polyfill
进行复用,避免重复引入,从而减小打包体积。 - Webpack 配置:无额外配置,
@babel/plugin-transform-runtime
主要在Babel
配置中起作用。 - Babel 配置:
在
.babelrc
或babel.config.js
文件中添加如下配置:
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": false, // 如果不使用 core-js 作为 polyfill 来源,设置为 false
"helpers": true,
"regenerator": true,
"useESModules": false
}
]
]
}
若项目使用 core-js
作为 polyfill
来源,可以将 corejs
设置为 2
或 3
,如 { "corejs": 3 }
,此时会自动引入 core-js
相关的 polyfill 且避免重复引入。
2. 按需引入 polyfill
- 原理:根据目标浏览器的特性支持情况,只引入需要的
polyfill
,减少不必要的代码。 - Webpack 配置:
可以使用
webpack
的ProvidePlugin
按需注入polyfill
。例如,如果只需要Promise
的polyfill
,在webpack.config.js
中配置:
const webpack = require('webpack');
module.exports = {
//...其他配置
plugins: [
new webpack.ProvidePlugin({
Promise: 'es6-promise'
})
]
};
- Babel 配置:
在
.babelrc
或babel.config.js
文件中,结合@babel/preset-env
进行配置。@babel/preset-env
可以根据目标浏览器的支持情况自动确定需要的polyfill
。
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage", // 根据代码中使用到的特性按需引入 polyfill
"corejs": 3 // 使用 core-js 3 作为 polyfill 来源
}
]
]
}
同时在项目入口文件中引入 core-js/stable
和 regenerator-runtime/runtime
,例如:
import 'core-js/stable';
import'regenerator-runtime/runtime';
3. 基于浏览器列表进行差异化引入
- 原理:根据不同浏览器及其版本,针对性地引入
polyfill
。对于支持新特性较好的现代浏览器,减少或不引入polyfill
,而对于旧浏览器,引入必要的polyfill
。 - Webpack 配置:
结合
webpack
的Target
配置以及DefinePlugin
来实现。例如,假设现代浏览器支持fetch
API,对于旧浏览器才需要引入whatwg-fetch
polyfill。
const webpack = require('webpack');
module.exports = {
//...其他配置
target: 'web',
plugins: [
new webpack.DefinePlugin({
'process.env.BROWSER_SUPPORTS_FETCH': JSON.stringify(process.env.BROWSER_SUPPORTS_FETCH)
})
]
};
然后在构建脚本中,根据不同的浏览器环境设置 process.env.BROWSER_SUPPORTS_FETCH
的值。
- Babel 配置:
同样结合
@babel/preset-env
,根据浏览器列表设置不同的polyfill
引入策略。
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"browsers": ["ie >= 11"] // 仅对 ie11 及以下浏览器进行 polyfill
},
"useBuiltIns": "usage",
"corejs": 3
}
]
]
}
在代码中,可以根据 process.env.BROWSER_SUPPORTS_FETCH
的值来决定是否引入 fetch
的 polyfill
,例如:
if (!process.env.BROWSER_SUPPORTS_FETCH) {
import('whatwg-fetch');
}