前言
置信很多人对 Babel
都理解,然而差不多是只知其一; 不知其二,很多中央预计是懵懵懂懂的感觉。配置的时候,在网上搜寻,而后复制粘贴,能跑通就好,但偶然会呈现一些稀奇古怪的问题。前面想深刻理解学习 Babel
,又发现官网读起来艰涩难懂,或者照着官网敲Demo
,又发现理论后果不是官网说的那样( 其实是因为咱们装置的依赖版本有问题,装置成最新的了,所以输入的成果跟官网的不一样 )。这样就造成咱们对Babel
更加的困惑。
因为 Babel
内容切实太多了,所以这篇文章不讲原理,也不讲怎么配置(配置后续会出专门的文章说),但会带着大家一起了解让人感觉“艰涩难懂”的官网,而后梳理、理解,咱们平时接触 Babel
用到的次要几个包,搞清楚 Babel
是什么、作用又是什么。
为了让大家更好的感触 Babel
对咱们日常我的项目的作用,有些例子会联合 Webpack
,毕竟咱们平时的我的项目,根本都会通过Webpack
等打包工具跟 Babel
相结合输入最初的包,而后在浏览器中运行。
章节中的案例,代码都放到 Github
上了,倡议大家边浏览,边跟着案例看。如果大家感觉有帮忙到,欢送 Star 跟 Fork 学习。
备注:
- 以后
@babel/core
最新版本是:7.20.12
- 以后
@babel/preset-env
最新版本是:7.20.2
Babel
官网解释:
Babel
是一个工具链,次要用于将采纳ECMAScript 2015+
语法编写的代码转换为向后兼容的JavaScript
语法,以便可能运行在以后和旧版本的浏览器或其余环境中。
咱们能够这么了解,Babel
就是一个工具。它是一个能够将 ES6+
等新个性,转换成低版本浏览器或其余环境能反对并失常运行的一个工具。
构造
很多人认为 Babel
只有 plugins
、presets
等几个配置。其实不止,咱们看看 Babel
配置文件大抵架构:
// babel.config.js
module.exports = {
...,
envName: "development",
plugins: [],
presets: [],
passPerPreset: false,
targets: {},
browserslistConfigFile: true,
browserslistEnv: undefined,
inputSourceMap: true
...
}
咱们个别次要用到的就是 plugins
、presets
这两个
性能
从大体上看,Babel
提供以下两个性能组成:
- 编译
ES6+
最新语法(let
、class
、() => {}
等) - 实现旧版本浏览器不反对的
ES6+
的API
(Promise
、Symbol
、Array.prototype.includes
等)
参考文章:
- What is Babel?
- Options
@babel/core
从 core
能够看出,它是 Babel
实现编译的外围。所以咱们如果要应用 Babel
,@babel/core
这个包肯定是必不可少的。另外咱们平时说的 Babel 6
、Babel 7
指的就是 @babele/core
的版本
参考文章:@babel/core
@bable/cli
官网解释:
Babel
自带了一个内置的CLI
命令行工具,可通过命令行编译文件
简略地说就是,让咱们能够在 终端 里应用命令来编译(这样能够更好的调试打印信息):
npx babel index.js
装置的话,咱们最好装置到咱们我的项目的本地目录下,尽量不要装置到全局(影响全局的货色,都很可怕)
参考文章:@babel/cli
@bable/preset-env
官网解释:
@babel/preset-env
是一个智能预设,它容许您应用最新的JavaScript
,而无需宏观治理指标环境须要哪些语法转换(以及可选的浏览器polyfill
)。这既让你的生存更轻松,也让JavaScript
包更小!
了解
@bable/preset-env
这个名字,咱们能够拆开两局部来看,这样不便了解:
preset
预设env
环境
preset
Babel
编译 ES6+
语法 ,是通过一个个插件plugin
去实现的。每年都会有不同新的提案、新的语法,但咱们不可能一个个插件去配置,所以就有了 preset
这个货色。因而咱们能够了解成 preset
就是一个 语法插件汇合包,这样咱们只用装置这一个包,不须要一个个配插件,就能够很不便的编译最新的语法了。
咱们通过一个不必预设的案例 no-preset,感受一下如果不必 preset
有多麻烦。
// 入口文件 index.js
const senses = ['eye', 'nose', 'ear', 'mouth'];
const lMC = {
senses,
like: ['eat', 'drink', 'play', 'fun'],
information: {
sex: 'male',
age: '18+'
},
play: (sport = 'badminton') => {console.log(`play ${sport}`);
}
};
const {like, information} = lMC;
这段代码,咱们用了几个 ES6
新语法:
const
申明- 属性的简洁表示法
- 箭头函数
- 函数默认值
- 模板字符串
- 解构
如果不必 preset
咱们 Babel
配置如下:
// Babel 配置文件 babel.config.js
const plugins = [
'@babel/plugin-transform-arrow-functions',
'@babel/plugin-transform-block-scoping',
'@babel/plugin-transform-destructuring',
'@babel/plugin-transform-parameters',
'@babel/plugin-transform-shorthand-properties',
'@babel/plugin-transform-template-literals'
];
module.exports = {plugins};
编译后的文件:
// 编译后的文件 compile.js
var senses = ['eye', 'nose', 'ear', 'mouth'];
var lMC = {
senses: senses,
like: ['eat', 'drink', 'play', 'fun'],
information: {
sex: 'male',
age: '18+'
},
play: function () {var sport = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'badminton';
console.log("play".concat(sport));
}
};
var like = lMC.like,
information = lMC.information;
在不必 preset
的状况下,实现上述编译的过程,我根本是用一个 ES6
新语法,我就要去查一个插件,首先我不记得那么多插件,其次一个个插件找真的很累。
ok,那咱们再用一个应用了预设的案例 use-preset,感受一下预设到底有多不便。
咱们 npm i @babel/preset-env -D
,批改babel.config.js
应用 preset
预设:
// 批改 babel.json
const presets = ['@babel/preset-env'];
module.exports = {presets};
编译后的文件:
// 编译后的文件 compile.js
"use strict";
var senses = ['eye', 'nose', 'ear', 'mouth'];
var lMC = {
senses: senses,
like: ['eat', 'drink', 'play', 'fun'],
information: {
sex: 'male',
age: '18+'
},
play: function play() {var sport = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'badminton';
console.log("play".concat(sport));
}
};
var like = lMC.like,
information = lMC.information;
咱们会发现,用 preset
(预设)形式输入的代码,跟plugins
(不必预设)形式输入的代码是简直是截然不同的。然而preset
的babel.config.js
更简洁,我也不须要一个个插件去找,也不须要装置那么多插件,只用装置 @babel/preset-env
这一个包,就能够很欢快的写ES6+
。
env
env
指的是环境。因为 @babel/preset-env
还有一个配置性能,咱们能够通过配置咱们代码运行的 指标环境 ,来管制polyfill
(一个提供低版本浏览器缺失的ES6+
新个性的办法与实现的汇合,前面会有更具体的解说)的导入跟语法编译,从而使 ES6+
新的个性能够在咱们想要的 指标环境 中顺利运行。
备注:
@babel/preset-env
还有一个配置性能,本文不讲配置,对于配置后续会有文章阐明
性能
通过上面对 preset
、env
的了解跟案例感触,咱们能总结出 @babel/preset-env
次要提供以下性能:
- 它 只编译
ES6+
语法 (上述案例只应用了ES6+
的语法,并没有用ES6+
的API
) - 它并不提供
polyfill
,然而能够通过配置咱们代码运行的 指标环境 ,从而管制polyfill
的导入跟语法编译,使ES6+
的新个性能够在咱们想要的 指标环境 中顺利运行
留神
咱们先看看 TC39
提案分为几个阶段:
- 阶段 0(
stage-0
)——草根(Strawman):只是一个想法,可能是Babel
插件。 - 第一阶段(
stage-1
)——提案(Proposal):这是值得钻研的。 - 第二阶段(
stage-2
)——草案(Draft):初步标准。 - 第三阶段(
stage-3
)——候选(Candidate):残缺的标准和最后的浏览器实现。 - 第四阶段(
stage-4
)——实现(Finished):将被增加到下一年度的版本中。
再看看官网中这段话:
Note:
@babel/preset-env
won’t include any JavaScript syntax proposals less than Stage 3 because at that stage in the TC39 process, it wouldn’t be implemented by any browsers anyway. Those would need to be included manually.
大抵意思是:
- 在
Babel 7
当前,@bable/preset-env
舍弃了Stage presets
(@babel/preset-stage-x
)这种预设 @bable/preset-env
只提供TC39
大于stage-3
的提案(即只蕴含stage-4
阶段),因而如果要用小于stage 4
的提案语法,则必须先装置再手动引入对应插件
第一点置信大家都很好了解,咱们来了解一下第二点是什么意思。
意思是,如果咱们想用一些小于 stage-4
阶段的语法的话,光装置 @babel/preset-env
这一个包是没有用的,因为这个包里只蕴含编译 stage-4
的预设,所以咱们就得装置并配置相应的 plugin
去编译。
在写这篇文章的时候,有一个新的语法 do expressions,它以后是处于 stage-1
阶段的语法,用插件 @babel/plugin-proposal-do-expressions
能够编译这个语法。
官网解释:do {..} 表达式执行一个块(其中有一个或多个语句),块内的最终语句实现值成为 do 表达式的实现值。
咱们借助官网,整顿成这个案例 compile-stage-1 来看看怎么应用小于 stage-4
的语法。
咱们先只用 @babel/preset-env
,看看能不能编译do {...}
这个语法。
// do expressions stage- 1 语法
let x = 100;
let y = 20;
let a = do {if (x > 10) {if (y > 20) {("big x, big y");
} else {("big x, small y");
}
} else {if (y > 10) {("small x, big y");
} else {("small x, small y");
}
}
};
Babel.config.js
配置:
const presets = ['@babel/preset-env'];
// const plugins = [
// '@babel/plugin-proposal-do-expressions'
// ];
// module.exports = {plugins, presets};
module.exports = {presets};
咱们会发现,终端会报错:
大抵意思是:@babel/preset-env
以后未启用对试验语法 doExpressions
的反对(因为 doExpressions
以后是 stage-1
的语法,@babel/preset-env
只蕴含必编译 stage-4
的语法插件),须要咱们退出 @babel/plugin-proposal-do-expressions
插件去编译。
那咱们npm i @babel/plugin-proposal-do-expressions -D
,批改一下babel.config.js
:
const presets = ['@babel/preset-env'];
const plugins = ['@babel/plugin-proposal-do-expressions'];
module.exports = {plugins, presets};
// module.exports = {presets};
咱们能够看到,能够失常输入编译后的文件:
"use strict";
var x = 100;
var y = 20;
var a = x > 10 ? y > 20 ? "big x, big y" : "big x, small y" : y > 10 ? "small x, big y" : "small x, small y";
所以,当咱们想应用小于 stage-4
阶段的语法时,咱们要先找到 其对应的编译插件 装置,而后在 plugins
外面配置就好了。
参考文章:
- TC39 proposals
- proposal-do-expressions
- @babel/plugin-proposal-do-expressions
补充
有时咱们也可能须要晓得咱们以后的 preset
(预设)蕴含了哪些插件,那咱们怎么查看以后@babel/preset-env
蕴含了哪些预设呢?
咱们能够通过查看 @babel/preset-env
–> package.json
–> dependencies
外面能够找到。我目前装置的 @babel/preset-env
版本为7.20.2
,它蕴含了以下预设:
// @babel/preset-env@7.20.2 预设
"dependencies": {
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6",
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9",
...,
"@babel/plugin-transform-sticky-regex": "^7.18.6",
"@babel/plugin-transform-template-literals": "^7.18.9",
"@babel/plugin-transform-typeof-symbol": "^7.18.9",
"@babel/plugin-transform-unicode-escapes": "^7.18.10",
"@babel/plugin-transform-unicode-regex": "^7.18.6",
},
polyfill
性能
ES6+
除了提供很多简洁的语法(let
、class
、() => {}
等)外,还为咱们提供了很多便捷的 API
(Promise
、Symbol
、Array.prototype.includes
等)。但 旧版本浏览器是不反对这些 API
的,而 polyfill
寄存了这些 API
的办法与实现,所以它能够使得这些不反对的浏览器,反对这些API
。
了解
咱们能够把所有这种寄存了 ES6+
API
的办法与实现的汇合 叫做 polyfill
,也就是咱们常常说的 垫片。
polyfill
也分很多种,像 core-js
是会提供旧版本浏览器缺失的 所有 的API
;还有一些只提供缺失 API
的某块,例如 promise-polyfill、proxy-polyfill 等。
Babel
配置 polyfill
的过程,就是实现旧版本浏览器对这些 API
反对的过程。
@babel/polyfill
下面咱们解释了 polyfill
是什么,从包名 @babel/polyfill
就晓得,它就是一个 polyfill
(其外围是依附core-js@2.x.x
实现)。尽管这个包曾经被废除了,但咱们还是略微理解一下它。
官网解释:
🚨 从 Babel 7.4.0 开始,这个包曾经被弃用,转而间接蕴含core-js/stable
(用于polyfill ECMAScript
性能)应用:
import "core-js/stable";
初识
咱们通过这个例子 know-babel-polyfill,来理解一下 @babel/polyfill
的组成。
know-babel-polyfill 什么都没装置,只装置了 @bable/polyfill
这个依赖,咱们能够很分明看到,@bable/polyfill
由以下两个包组成:
<img src=”https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8ff1acb6c6e2463aad5798f805f3efd8~tplv-k3u1fbpfcp-watermark.image?” alt=”babel-polyfill.jpeg” width=”100%” />
core-js
(版本为2
)regenerator-runtime
咱们来大抵了解一下这两包是什么:
core-js
这个包就是咱们上述 polyfill
模块所说的,外面寄存了很多 ES6+
API
的办法与实现。如果要在旧浏览用到 Promise
、Symbol
、Array.prototype.includes
等办法时,这个包会为咱们提供。它能够使那些不反对 API
的浏览器,反对这些API
,它就是一种垫片。
特地留神 :由上图可知,
@babel/polyfill
是与2
版本的core-js
绑定的,2
版本的core-js
并不蕴含stable
这个文件夹的。因而官网说的import "core-js/stable"
,实际上是要咱们装置core-js@3.x.x
版本来代替@babel/polyfill
,因为从3
版本开始,才有stable
这个文件夹
regenerator-runtime
咱们的源码外面应用了 async function() {}
等异步函数,或者 fuction* myGenerator() {}
这种 Generator
函数的话,就会须要用到这个包来编译。
总结
所以对于@babel/polyfill
,咱们有以下总结:
- 这个包由
core-js
( 版本为2.x.x
)与regenerator-runtime
两个包组成 - 这个包在
Babel 7.4.0
当前就被废除了,所以在Babel 7.4.0
当前,咱们想让一些不反对ES6+
API
的浏览器反对这些API
,就不应该装置这个包,应该装置core-js@3.x.x
的包(不要装置2.x.x
的版本,曾经不保护了,目前最新版本为3.x.x
)
参考文章:@babel/polyfill
core-js
概述
通过下面 polyfill
、@babel/polyfill
两个模块,咱们能够晓得 @babel/polyfill
曾经不再应用,而且 @babel/polyfill
实现的外围就是 core-js
,所以如果咱们想要在旧浏览器用到Promise
、Symbol
、Array.prototype.includes
等办法时,咱们间接装置 core-js@3.x.x
这个包。
通过 官网的介绍,咱们能够晓得:
import '@babel/polyfill';
等同于
// core-js 必须是 3.x.x 版本,因为 2.x.x 版本,不蕴含 stable 文件夹
import "core-js/stable";
import "regenerator-runtime/runtime";
Babel >= 7.18.0
等同于
// core-js 必须是 3.x.x 版本,因为 2.x.x 版本,不蕴含 stable 文件夹
// Babel >= 7.18.0 后 不须要再 import "regenerator-runtime/runtime";
import "core-js/stable";
留神
咱们针对不须要再 import "regenerator-runtime/runtime"
这块,略微解释一下,加深一下咱们对 Babel
跟官网文档的了解。
咱们看官网这段话:
If you are compiling generators or async function to
ES5
, and you are using a version of@babel/core
or@babel/plugin-transform-regenerator
older than7.18.0
, you must also load the regenerator-runtime package
大家看这句话的时候可能有点纳闷,其实它的意思就是:
如果咱们要把 async function() {}
等异步函数,或者 fuction* myGenerator() {}
这种 Generator
函数编译成 ES5
,并且@babel/core
或@babel/plugin-transform-regenerator
小于 7.18.0
,咱们就须要手动import "regenerator-runtime/runtime"
这个包。
但在 Babel 7.18.0
或者 @babel/plugin-transform-regenerator 7.18.0
及其当前的版本,regenerator-runtime
包外面的内容会被 内联编译 到咱们的代码中,所以咱们只用引入 import "core-js/stable"
这一个包就能够了。
咱们来用两个例子联合 Webpack
打包进去,在浏览器运行,这样更直观的了解感受一下。
Babel < 7.18.0
咱们用这个例子 import-regenerator-runtime 看看在 Babel 7.18.0
之前为什么要手动引入 regenerator-runtime
这个包。
特地阐明: 咱们例子装置
Babel
的版本为7.16.7
,@babel/plugin-transform-regenerator
这个插件必须 手动装置为小于7.18.0
的版本 (因为咱们装置依赖的时候,即便指定了依赖的版本,但依赖的依赖装置时,可能会是最新的,这样可能会看不出成果。所以为什么有时咱们对着官网敲Demo
理论进去的后果不一样,因为版本没对上)。能够通过package-lock.json
查看各个依赖版本
ok,来看看咱们的入口文件(index.js
):
// 先不引入 regenerator-runtime/runtime
// import 'regenerator-runtime/runtime';
const sleep = async function() {setTimeout(() => console.log('get up'), 1000);
}
sleep();
接着咱们打包(Webpack
打包进去的文件在dist/dist.js
)在浏览器运行。失常状况下,浏览器应该会过一秒后输入get up
。但理论状况如下,咱们会发现之前网友们经常出现的一个问题——regeneratorRuntime is not defined
:
阐明缺失了 regeneratorRuntime
,咱们再看看Babel
编译后的文件(compile.js
):
咱们发现在全局中,regeneratorRuntime
基本没有定义,所以才报了 regeneratorRuntime is not defined
的错。
如果咱们再手动引入一下import "regenerator-runtime/runtime"
:
import 'regenerator-runtime/runtime';
const sleep = async function() {setTimeout(() => console.log('get up'), 1000);
}
sleep();
此时浏览器输入:
当咱们手动引入当前,浏览器能够失常运行了。
这阐明,在 @babel/core
或@babel/plugin-transform-regenerator
的版本小于 7.18.0
的时候,应用了异步函数(async function() {}
),或者 Generator
这种函数(fuction* myGenerator() {}
)的话,是须要咱们手动引入 regenerator-runtime
这个包的,因为 regenerator-runtime
这个包会为咱们提供 regeneratorRuntime
这个全局对象。
Babel >= 7.18.0
咱们用这个例子 no-import-regenerator-runtime 看看在 Babel 7.18.0
之后为什么不须要手动引入 regenerator-runtime
这个包。(@babel/core
版本为7.20.12
)
ok,来看看咱们的入口文件,这时不再手动引入 regenerator-runtime
这个包:
const sleep = async function() {setTimeout(() => console.log('get up'), 1000);
}
sleep();
编译出包当前在浏览器运行,失去跟上述手动引入 regenerator-runtime
这个包截然不同的成果:
咱们再看看 Babel
编译后的文件:
咱们会发现,regenerator-runtime
包里的内容,会以 局部变量的形式内联注入到咱们的代码中 ,这样咱们就不须要全局提供一个regeneratorRuntime
对象了。
所以,在 Babel >= 7.18.0
当前,咱们间接 import "core-js/stable";
就好
参考文章:
- core-js
- @babel/polyfill
- Inline regenerator-runtime helper
@babel/runtime
官网解释:
@babel/runtime
是一个蕴含Babel
模块化运行时助手的库
在 Babel
编译的时候,会有一些辅助函数,这些函数就是 ES6+
一些语法糖的实现,咱们用这个案例 helper-functions 看看辅助函数是什么。
咱们用 Babel
编译一下 class
这个语法糖:
class People {constructor() {}}
const person = new Person();
编译当前:
咱们先看红色框,它是 Babel
编译后的代码。咱们会发现,编译当前生成很多函数,并且会以内联的形式插入到咱们的代码中,这些函数就是咱们说的 辅助函数。
咱们再看蓝色框,它是 @babel/runtime
的内容,它在node_modules/@babel/runtime/helpers
。
咱们最初来看看红色框,会发现 Babel
编译后的辅助函数,都能够在 @bable/runtime
外面找到,所以 @babel/runtime
是寄存了 Babel
辅助函数的一个汇合包。
参考文章:@babel/runtime
@babel/plugin-transform-runtime
官网解释:一个插件,能够重用
Babel
注入的帮忙程序代码以节俭代码大小
通过下面 @babel/runtime
模块的理解,咱们晓得当咱们应用了一些 ES6+
的语法糖时,Babel
会生成一些辅助函数来编译这些语法糖,并以 内联的形式插入 到代码中。
那如果咱们有 10 个文件都用到了语法糖,那这些辅助函数,是不是会生成 10 次,并内联插入 10 次呢?咱们用这个案例 no-use-transform-runtime 来感受一下。
咱们定义了三个文件,每个文件都用了 class
这个语法糖。
// babel.config.js 配置文件
const presets = ['@babel/preset-env'];
module.exports = {presets};
// Animal.js 文件
export default class Animal {constructor() {}};
// Country.js 文件
export default class Country {constructor() {}};
// index.js 文件
import Animal from "./class/Animal";
import Country from "./class/Country";
class People {constructor() {}};
const lMC = new People();
const cat = new Animal();
const usa = new Country();
最初打包进去文件:
看看红色的框框,咱们会发现实现的办法都是一样的,所以在每个应用到 class
语法糖的文件中,辅助函数都被生成并插入了一次,这些根本反复的代码,无疑是会大大增加咱们的打包体积的。目前打包进去的体积是:6KB
。
为了解决上述的弊病,咱们就得应用 @babel/plugin-transform-runtime
插件。从 @babel/runtime
模块咱们晓得,它外面寄存了 Babel
辅助函数的汇合,@babel/plugin-transform-runtime
会将咱们用到的辅助函数,从 @babel/runtime
中以 require
或者 import
的形式,引入到咱们的文件中,实现复用,从而减小咱们最终输入包的体积。
所以 @babel/runtime
跟@babel/plugin-transform-runtime
两者通常是配合一起应用。
备注:
@babel/plugin-transform-runtime
还有一个配置性能,本文不讲配置,对于配置后续会有文章阐明
咱们用这个案例 use-transform-runtime 看看应用了 @babel/plugin-transform-runtime
插件当前有什么变动。
咱们的案例代码跟上述一样,只是在 babel.config.js
减少了 @babel/plugin-transform-runtime
配置
// babel.config.js 配置文件
// 减少了 @babel/plugin-transform-runtime 配置
const plugins = ['@babel/plugin-transform-runtime']
const presets = ['@babel/preset-env'];
module.exports = {plugins, presets};
// Animal.js 文件
export default class Animal {constructor() {}};
// Country.js 文件
export default class Country {constructor() {}};
// index.js 文件
import Animal from "./class/Animal";
import Country from "./class/Country";
class People {constructor() {}};
const lMC = new People();
const cat = new Animal();
const usa = new Country();
编译跟打包后的文件:
咱们会发现:
- 辅助函数会以
require
援用的形式加到咱们的代码中 - 打包后,辅助函数只用了一次,而且不是插入三次,很好的实现了复用
- 打包进去的体积也变成了
3KB
,很好的放大了最初包的体积(不要小看放大了3KB
,只是因为我用最简略的形式写了ES6+
语法,理论中咱们我的项目必定没那么简略)
最初
因为 Babel
的常识体系切实太大了,所以咱们应该先把 Babel
次要的几个包弄清楚,再深刻配置。对于 Babel
的配置,会后续再出文章。
咱们平时我的项目中 Babel
用到的包,根本就是这篇文章中解说的几个包,这篇文章算是非常具体的介绍了这几个包了。如果大家能把这几个包弄得很分明,Babel
的大部分常识也理解的差不多了。
如果之前对 Babel
还有点懵懵的你,心愿读完这篇文章后,能够很好的了解 Babel
大抵是个什么货色,也能更分明的看懂官网写的内容。
两头有用到 Webpack
,我本人用Webpack5
搭了个脚手架 webpack5-boilerplate,如果你也想理解 Webpack
的常识,也能够看看之前我写的这篇文章—— webpack5 优化的中央及搭建的一些领会。
如果感觉真的有帮忙到,欢送点赞珍藏 ;如果有异同点, 欢送在评论区探讨。