持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
Webpack 系列专栏地址 进入
本文demo地址查看
babel
js使用 es6+
的一些语法时,遇到某些版本较低的浏览器时可能无法运行,此时就可以用 babel 对js的一些语法进行兼容处理。
Babel 是一个 JavaScript 编译器,可以做以下事情:
- 通过语法转换器来支持新版本的 JavaScript 语法
- 通过 Polyfill 方式在目标环境中添加缺失的特性 (通过引入第三方 polyfill 模块,例如 core-js)
Babel 是一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
安装
安装 loader 和 核心包:
# 当前版本 7.x
npm i babel-loader @babel/core -D
preset-env
安装预设 用来处理es6+
语法:
npm i @babel/preset-env -D
webpack.config.js 配置:
{
test: '/.js$/',
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
src/index.js中写一段测试代码:
const arr = [new Promise(() => {}), new Promise(() => {})]
arr.map((item) => {
console.log(item)
})
执行打包命令成功后,查看bundle文件:
const
被转换成了 var
,箭头函数被转换成了 普通的function
。相关的语法都被转换成了兼容的形式,但是Promise
并没有被转换,这是因为babel只是针对语法进行转换,一些目标环境缺失的特性(如浏览器不支持Promise),需要使用Polyfill 方式。
Polyfill
Polyfill 基于
core-js
,core-js
中包含了es6+的一些新特性。在代码执行之前加载core-js
就可以让原本不支持新特性的浏览器通过调用core-js
而支持Promise等新特性。
安装Polyfill:
npm i @babel/polyfill -S
注意 Polyfill 要安装在生产环境,在需要使用得地方引入 src/index.js:
import '@babel/polyfill'
提示:从babel 7.4版本开始不再安装 Polyfily,直接使用core-js/stable
执行打包命令:
打包出来的文件大了很多,这是因为引入了 Polyfill,上面的引入方式是全量引入,没用到的特性也被打包了进来,可以利用按需引入来优化包体积,减少多余的代码。
通过给 preset-env
添加配置项,来实现Polyfill的按需引入。
useBuiltIns
useBuiltIns
是 @babel/preset-env
的一个配置项,可以为Polyfill提供按需引入特性的功能,可选参数有 entry | usage | fasle
entry
需要在webpack的入口模块中import '@babel/polyfill'
,babel就会根据我们的代码情况导入相应的垫片(特性代码)usage
不需要在入口模块 import ,它是一个全自动检测的过程false
默认值,全量打包
配置:
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
corejs: 2, // 版本
useBuiltIns: 'usage',
},
],
],
},
},
},
使用usage
模式,可以取消掉 index.js中的 import '@babel/polyfill
,因为它是一个全自动检测的机制。
注意:配置项的结构,presets
参数对应的值是数组,给presets
添加配置项也是数组,下标1
是表示要给@babel/preset-env
添加配置,下标2
是一个对象里面包含针对@babel/preset-env
的配置项。
再次打包,bundle文件的大小就减少了很多,由原来的 400多kb
变成了现在的 190多kb
:
此时我们的目标浏览器集合是 package.json 中配置的:
"browserslist": [
"last 2 versions",
">1%"
],
给 @babel/preset-env
添加 targets
设置目标浏览器集合:
presets: [
[
'@babel/preset-env',
{
corejs: 2, // 版本
useBuiltIns: 'usage',
targets: {
edge: '17',
chrome: '67',
firefox: '60',
},
},
],
],
再次打包,目标浏览器集合就变成了 targets
中的现代浏览器,打包出来的bundle文件体积只有 4kb
左右,这是因为针对于现代新版本的浏览器,我们需要的特性垫片更少,所以体积就会更小。
babel.config.json
创建 babel.config.json文件,把上述针对于 babel的配置文件抽离出来。
{
"presets": [
[
"@babel/preset-env",
{
"corejs": 2, // 版本
"useBuiltIns": "usage"
// 设置目标浏览器集合
// targets: {
// edge: '17',
// chrome: '67',
// firefox: '60',
// },
}
]
]
}
此时,webpack.config.js 关于babel的配置看起来就很简洁
{
test: /\.js$/,
use: {
loader: 'babel-loader',
},
},
preset-react
进行对 react JSX 的相关处理
安装 react 相关依赖:
npm i react react-dom -S
写一段 react 的代码:
import React from 'react'
import ReactDOM from 'react-dom/client'
const root = ReactDOM.createRoot(document.getElementById('app'))
root.render(<h1>hello JSX</h1>)
如何让项目支持这种 JSX 的写法?需要用到 @babel/preset-react 处理JSX 代码。当前版本:7.18.6
npm i @babel/preset-react -D
babel.config.json 添加相关的配置:
{
"presets": [
[
"@babel/preset-env",
{
"corejs": 2, // 版本
"useBuiltIns": "usage"
}
],
// +++
"@babel/preset-react"
]
}
配置完成,执行npm run build
打包命令,打包完成运行代码,发现会报错 # Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘
。
webpack.config.js 添加配置让babel-loader
忽略处理node_modules目录下的文件。
{
test: /\.js$/,
use: {
loader: 'babel-loader',
},
// +++
exclude: /node_modules/,
},
再次打包,就没有报错信息了。会发现bundle文件变大了很多,这是因为引入了react react-dom
的原因。