Webpack 6 中 Babel 配置与使用详解
本文详细解析在 Webpack 6 项目中如何配置和使用 Babel。内容涵盖 Babel 基础概念、CLI 工具使用、配置文件编写,重点讲解 @babel/preset-env 的 useBuiltIns 和 target 选项,以及 @babel/polyfill 与 @babel/runtime 的区别与应用场景,帮助开发者实现高效的代码转换与兼容性处理。
Webpack 中 Babel 概述
在 Webpack 项目中编写 JavaScript 代码时,开发者可以使用最新的 ES 语法。在最终打包阶段,Webpack 会利用 Babel 将 ES6 及更高版本的语法转换为目标浏览器支持的 ES5 语法。因此,掌握 Babel 是前端开发中的重要技能。
Babel 基础概念
什么是 Babel
Babel 是一个 JavaScript 编译器,能够将最新 ES 语法编写的代码转换为任意版本的 JavaScript。随着浏览器对 ES 标准支持程度的提高,开发者无需修改源代码,只需调整 Babel 配置即可适配新浏览器。例如,ES6 箭头函数的代码如下:
[1,2,3].map(n => n**2);
经过 Babel 处理后,上述代码可转换为标准的 ES5 语法:
[1,2,3].map(function(n) {
return Math.pow(n, 2);
});
Babel 初体验与 CLI 使用
Babel 初体验
接下来介绍 Babel 的安装方法、功能及其配置文件的使用。
1. 使用 babel-cli 命令行工具
Babel 自带 CLI(Command-Line Interface,命令行界面)工具,可以单独安装使用。在项目中,我们需要安装 @babel/cli 和 @babel/core。
npm i -D @babel/core @babel/cli
随后创建一个名为 babel.js 的文件:
// babel.js
[1,2,3].map(n => n**2);
执行命令 npx babel babel.js 后,会看到输出内容。此时输出可能与源文件一致,因为尚未添加转换规则。接下来安装 @babel/preset-env,并在执行 CLI 时添加 --presets 标志:
// 安装 preset-env
npm i -D @babel/preset-env
// 执行 CLI 添加 --presets
npx babel babel.js --presets=@babel/preset-env
最终输出的代码即为转换后的 ES5 代码:
‘use strict'
[1,2,3].map(function(n) {
return Math.pow(n, 2);
});
若要将结果输出到指定文件,可以使用 --out-file 或 -o 参数:
npx babel babel.js -o output.js。
提示:Babel 7 使用 @babel 命名空间来区分官方包,因此以前的官方包 babel-xxx 已更改为 @babel/xxx。
Babel 配置文件与 env 选项
2. 配置文件
除了使用命令行配置标志外,Babel 还支持配置文件,配置文件支持两种形式:
使用 package.json 中的 babel 属性;
在项目根目录单独创建 .babelrc 或 .babelrc.js 文件。
示例如下:
// package.json
{
‘name': ‘my-package',
‘version': ‘1.0.0',
‘babel': {
‘presets': [‘@babel/preset-env']
}
}
// .babelrc
{
‘presets': [‘@babel/preset-env']
}
Babel 会在正在被转义的文件当前目录中查找 .babelrc 文件。如果不存在,它会向外层目录遍历目录树,直到找到一个 .babelrc 文件,或一个 package.json 文件中有 "babel": {}。
3. env 选项
如果希望在不同环境中使用不同的 Babel 配置,可以在配置文件中添加 env 选项:
{
‘env': {
‘production': {
‘presets': [‘@babel/preset-env']
}
}
}
env 选项的值将从 process.env.BABEL_ENV 获取,如果没有的话,则获取 process.env.NODE_ENV 的值,它也无法获取时会设置为 "development"。
Babel 插件与 Preset 机制
Babel 的插件和 Preset
Babel 的语法转换是通过强大的插件系统来支持的。Babel 的插件分为两类:转换插件和语法解析插件。
不同的语法对应着不同的转换插件,比如我们要将箭头函数转换为 ES5 函数写法,那么可以单独安装 @babel/plugin-transform-arrow-functions 插件,转换插件主要职责是进行语法转换的,而解析插件则是扩展语法的,比如我们要解析 jsx 这类 React 设计的特殊语法,则需要对应的 jsx 插件。
如果不想一个个的添加插件,那么可以使用插件组合 preset(插件预设,插件组合更加好理解一些),最常见的 preset 是 @babel/preset-env。之前的 preset 是按照 TC39 提案阶段来分的,比如看到 babel-preset-stage-1 代表,这个插件组合里面是支持 TC39< Stage-1 阶段的转换插件集合。
@babel/preset-env 是 Babel 官方推出的插件预设,它可以根据开发者的配置按需加载对应的插件,通过 @babel/preset-env 我们可以根据代码执行平台环境和具体浏览器的版本来产出对应的 JavaScript 代码,例如可以设置代码执行在 Node.js 8.9 或者 iOS 12 版本。
Polyfill 方案:@babel/polyfill 与 @babel/runtime
Babel polyfill
Babel 只负责进行语法转换,即将 ES6 语法转换成 ES5 语法,但是如果在 ES5 中,有些对象、方法实际在浏览器中可能是不支持的,例如:Promise、 Array.prototype.includes,这时候就需要用 @babel/polyfill 来做模拟处理。@babel/polyfill 使用方法是先安装依赖,然后在对应的文件内显性的引入:
// 安装,注意因为我们代码中引入了 polyfill,所以不再是开发依赖(--save-dev,-D)
npm i @babel/polyfill
在文件内直接 import 或者 require 进来:
// polyfill
import ‘@babel/polyfill'
console.log([1,2,3].includes(1));
Bable runtime
@babel/polyfill 虽然可以解决模拟浏览器不存在对象方法的事情,但是有以下两个问题:
直接修改内置的原型,造成全局污染;
无法按需引入,Webpack 打包时,会把所有的 Polyfill 都加载进来,导致产出文件过大。
为了解决这个问题,Babel 社区又提出了 @babel/runtime 的方案,@babel/runtime 不再修改原型,而是采用替换的方式,比如我们用 Promise,使用 @babel/polyfill 会产生一个 window.Promise 对象,而 @babel/runtime 则会生成一个 _Promise (示例而已)来替换掉我们代码中用到的 Promise。另外 @babel/runtime 还支持按需引入。下面以转换 Object.assign 为例,来看下 @babel/runtime 怎么使用。
- 安装依赖 @babel/runtime:npm i @babel/runtime;
- 安装 npm i -D @babel/plugin-transform-runtime 作为 Babel 插件;
- 安装需要转换 Object.assign 的插件:
npm i -D @babel/plugin-transform-object-assign
编写一个 runtime.js 文件,内容如下:
Object.assign({}, {a:1});
执行 npx babel runtime.js --plugins @babel/plugin-transform-runtime,@babel/plugin-transform-object-assign,最终的输出结果是:
import _extends from ‘@babel/runtime/helpers/extends';
_extends(
{},
{
a:1
}
);
代码中自动引入了 @babel/runtime/helpers/extends 这个模块(所以要添加 @babel/runtime 依赖啊)。 @babel/runtime也不是完美的解决方案,由于 @babel/runtime 不修改原型,所以类似[].includes() 这类使用直接使用原型方法的语法是不能被转换的。
Tips:'@babel/polyfill'实际是 core-js和 regenerator-runtime的合集,所以如果要按需引入'@babel/polyfill'的某个模块,可以直接引入对应的 core-js 模块,但是手动引入的方式还是太费劲。
@babel/preset-env 高级配置
@babel/preset-env
铺垫了这么多,我们继续来讲 @babel/preset-env,前面介绍了@babel/preset-env 可以零配置的转化 ES6 代码,我们如果要精细化的使用 @babel/preset-env ,就需要配置对应的选项了,在 @babel/preset-env 的选项中,useBuiltIns 和 target 是最重要的两个, useBuiltIns 用来设置浏览器 polyfill,target 是为了目标浏览器或者对应的环境(browser/node)。
preset-env 的 useBuiltIns
前面介绍了 @babel/polyfill 和 @babel/runtime 两种方式来实现浏览器 polyfill,两种方式都比较繁琐,而且不够智能,我们可以使用 @babel/preset-env 的 useBuildIn 选项做 polyfill,这种方式简单而且智能。 useBuiltIns 默认为 false,可以使用的值有 usage 和 entry:
{
‘presets': [
‘@babel/preset-env', {
‘useBuiltnls': ‘usage|entry|false'
}
]
}
usage 表示明确使用到的 Polyfill 引用。在一些 ES2015+ 语法不支持的环境下,每个需要用到 Polyfill 的引用时,会自动加上,例如:
const p = new Promise();
[1,2].includes(1);
‘foobar'.includes(‘foo');
使用 useBuiltIns='usage' 编译之后,上面代码变成,真正的做到了按需加载,而且类似 [].includes() 这类直接使用原型方法的语法是能被转换的:
‘use strict'
require(‘core-js/modules/es.array.includes');
require(‘core-js/modules/es.object.to-string');
require(‘core-js/modules/es.promise');
require(‘core-js/modules/es.string.includes');
var p = new Promise();
[1,2].includes(1);
‘foobar'.includes(‘foo');
entry 表示替换 import "@babel/polyfill";(新版本的 Babel,会提示直接引入 core-js或者regenerator-runtime/runtime来代替 @babel/polyfill)的全局声明,然后根据 targets 中浏览器版本的支持,将 polyfill 拆分引入,仅引入有浏览器不支持的 polyfill,所以 entry 相对 usage 使用起来相对麻烦一些,首先需要手动显性的引入 @babel/polyfill ,而且根据配置 targets 来确定输出,这样会导致代码实际用不到的 polyfill 也会被打包到输出文件,导致文件比较大。
一般情况下,个人建议直接使用 usage 就满足日常开发了。
需要提一下的是,polyfill 用到的 core-js 是可以指定版本的,比如使用 core-js@3,则首先安装依赖 npm i -S core-js@3,然后在 Babel 配置文件 .babelrc 中写上版本。
// .babelrc
{
‘presets': [
[
‘@babel/preset-env',
{
‘useBuiltlns': ‘useage',
‘corejs': 3
}
]
]
}
preset-env 的 target
假设希望代码中使用 ES6 的模板字面量`语法,但是实际执行代码的宿主浏览器是 IE 10 却不支持,那么我们可以使用</code>target指定目标浏览器了。
{
‘presets': [
[
‘@babel/preset-env',
{
‘targets': {
‘browsers': ‘IE 10'
}
}
]
]
}
如果我们代码是在 Node.js 环境执行的,则可以指定 Node.js 的版本号:
{
‘presets': [
[
‘env',
{
‘@babel/preset-env': {
‘node: ‘8.9.3'
}
}
]
]
}
targets.browsers 需要使用 browserslist 的配置方法,但是其设置会被 targets.[chrome, opera, edge, firefox, safari, ie, ios, android, node, electron] 覆盖; targets.node 设置为 true 或 "current" 可以根据当前 Node.js 版本进行动态转换。也可以设置为具体的数字表示需要支持的最低 Node.js 版本; targets.esmodules 设置使用 ES Modules 语法,最新浏览器支持,这个在后面 Webpack 插件章节会详细介绍如何实现 Modern Mode。
Webpack 集成 Babel 配置
在 Webpack 中使用 Babel
通过上面的内容,我们已经掌握了 Babel 的基本用法,下面在 webpack 中使用 Babel 就变得很简单了,首先安装 npm 依赖,然后修改 webpack.config.js。
安装依赖包:
// 安装开发依赖
npm i webpack babel-loader webpack-cli @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
// 将 runtime 作为依赖
npm i @babel/runtime -S
第二步创建 webpack.config.js 文件,内容如下:
// webpack.config.js
module.exports = {
entry: ‘./babel.js',
mode: ‘development',
devtool: false,
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: ‘babel-loader',
options: {
presets: [
[
‘@babel/preset-env',
{
useBuiltlns: ‘usage'
}
]
]
}
}
]
}
]
}
}
上面的 webpack.config.js 文件直接将 Babel 的配置写到了 options 中,还可以在项目根目录下创建 .babelrc 或者使用 package.json 的 babel 字段。
小结
在本篇中,我们学习了 Webpack 怎么配置 Babel,希望对大家有所帮助,如果喜欢萝卜的文章,请大家持续关注,下一篇我将给大家介绍 webpack-dev-server 这个超好用的工具。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
JavaScript项目常见配置文件详解:package.json、tsconfig与构建配置
2026-11-04 21:34:42
React 项目集成 Mock.js 的最佳实践与配置详解
2026-11-03 22:33:26
使用 core-js-pure 避免全局污染:模块化库开发的最佳实践
2026-11-03 12:11:35
团队协作中怎么统一JS代码格式化规范
2026-11-03 10:18:39
Wiki.js 是什么?基于 Node.js 的开源 Wiki 引擎介绍
2026-11-02 10:30:54
