前言
现在项目打包,打多数是用的 webpack
来打包的。可能处于某种原因,例如带宽呀,节约服务器资源呀等,以及访问性能呀,会要求我们按需打包,打包后的文件尽可能的小,且兼容一些低版本的浏览器。
那如何按需引入,又该如何按需打包呢?今天我们就一起来探讨一下!
言归正传
接下来,我们会做些测试,来一步一步说明,如何按需引用和打包的。
我们先写一段 ES6
语法的测试代码,如下:
src/index.js 文件
const fn = ()=>{
console.log('this is fn()')
}
fn();
new Promise(()=>{})
Array.from(new Set([1,2,3,4]))
class A { }
运行 npm run serve
命令,启动后点击 F12
选择 Sources
选项查看我们的打包文件,如下:
可以看到,我们写的 ES6
语法,并没有转换成 ES5
语法?
有同学可能会说,还没引入 babel
!
是没引入,那为何引入 babel
就可以了,babel
又偷摸做了什么事呢?
说到 babel
不得不提 预设包 @babel/preset-env
,这包说明了 babel
本身不能把 ES6
转换成 ES5
的,它只是提供了一个平台,这个平台是依赖 babel core
来实现的。那 babel core
就是干活的吗?答案是否定的,它只是相当于一个组织者,组织了各种语法
对应的的插件。
简单讲就是:预设包就是许多 babel 插件的集合包,用来解析多个ES6
的语法。
但 预设包
也不是万能的,它只能转换浏览器不兼容的语法,比如 const、let、class 以及 箭箭头函数
等,不能转换新的的 API
, 例如 Peomise、Set、Map 以及 Object.assign()
等。
怎么办呢?这时又来了一个包 @babel/polyfill
又称 补丁包
。它包含了两个插件
core-js
: 实现了除 async await
外所有 ES6、ES7、以及 ES8
语法
regenerator-runtime
:实现了 async await
我们接下来最为关键的异步,配置 babel
- 安装
babel
相关包
npm install -D babel-loader @babel/core @babel/preset-env
- 在
webpack.config.js
文件里配置rules
module:{
rules:[
// 处理 ES6 => ES5
{
test: /\.js/, // 需要处理的文件类型
include: [resolve('src')], // 需要梳理的文件
// 组合一 use 后面跟字符串
use: 'babel-loader',
// 组合二 use 后面是数组,每项元素是对象,可单独配置 或者 数组每项是字符串,相当于组合一
// use: [
// {
// laoder: 'babel-loader',
// options: {
// presets: [],
// plugins: []
// },
// }
// ],
// use: ['babel-loader'],
// 组合三 loader + options
// loader: 'babel-loader',
// options: {
// presets: [],
// plugins: []
// }
}
]
}
- 创建
babel.config.js
文件并配置
module.exports = function(api) {
api.cache(true); // 缓存加快打包
// 每个预设 都是一个数组,包含 第一项是名称,第二项是配置
// const presets = [
// [
// '@babel/preset-env',
// {
// // 如需要配置项
// }
// ],
// [
// // 其他配置项
// ]
// ]
// 如果不需要配置,可简写
const presets = ['@babel/preset-env'];
const plugins = [];
return {
presets, plugins
}
}
- 再次运行
npm run serve
命令,启动后点击F12
选择Sources
选项查看我们的打包文件,如下:
由上可以看出,ES6
语法已经被转换为 ES5
的语法了。
但有一个问题没有解决:生成的文件里有
Promise
,这就意味着低版本浏览器不支持,可能导致我们的项目没法正常运行。
这是可以用到我们提到过的一个包 @babel/polyfill
安装
npm install @babel/polyfill -D
在程序头部引入
import '@babel/polyfill’
配置好后, npm run serve
命令,启动后点击 F12
选择 Sources
选项查看我们的打包文件已经多出了 Promise 及相关的定义。
这时问题又来了,引入
@babel/polyfill
后打包的文件体积变大了,也就是说,不管你当前的浏览器支不支持Promise
它都会重新定义, 从而造成了资源浪费。
而我们想要的结果是:
浏览器不支持我们就引入@babel/polyfill
,否则不引入。
解决这个问题只需在 babel.config.js
中配置 useBuiltlns
,且有三种方案,不需要在程序文件中单独引入,具体如下:
- 配置 为
useBuiltlns: false
const presets = [
[ '@babel/preset-env' ]
]
等同于
const presets = [
[
'@babel/preset-env',
{
"useBuiltlns": "false"
}
]
]
特点:
- 不管项目中用没用到
ES6/7/8
它都会全部引入所有浏览器的兼容
- 配置 为
useBuiltlns: entry
const presets = [
[
'@babel/preset-env',
{
"useBuiltlns": "entry", // 默认是 false 即全部打包
"corejs": 2,
"targets": { //指定浏览器兼容的最低版本
"edge": 70,
// "ie": 10,
"chrome": 67
}
}
]
]
特点:
- 会全部引入从设置的最低版本起的所有
ES6/7/8
的语法 - 兼容浏览器版本越低,打包的文件体积越大。
- 配置 为
useBuiltlns: usage
const presets = [
[
'@babel/preset-env',
{
"useBuiltlns": "usage", // 默认是 false 即全部打包
"corejs": 2,
"targets": { //指定浏览器兼容的最低版本
"edge": 70,
// "ie": 10,
"chrome": 67
}
}
]
]
特点:
- 只会引入项目所需的
ES6/7/8
的语法
文档到此咱们的研究就告一段落了,实现了项目文件按需引入并打包。
赶紧试试吧,记得点赞转发哦 ~~~