Appearance
Babel + TS + ESLint 构建 js 环境
开发中我们很少直接去接触babel,但是babel对于前端开发来说,目前是不可缺少的一部分。我们想要使用ES6+的语法,想要使用TypeScript,开发React项目,它们都是离不开Babel的。
Stage-x
首先我们需要了解 ES 规范,它是由 TC39 组织制定。
TC39 遵循的原则是:分阶段加入不同的语言特性,新流程涉及四个不同的 Stage
- Stage 0:strawman(稻草人),任何尚未提交作为正式提案的讨论、想法变更或者补充都被认为是第 0 阶段的" 稻草人";
- Stage 1:proposal(提议),提案已经被正式化,并期望解决此问题,还需要观察与其他提案的相互影响;
- Stage 2:draft(草稿),Stage 2 的提案应提供规范初稿、草稿。此时,语言的实现者开始观察 runtime 的具体 实现是否合理;
- Stage 3:candidate(候补),Stage 3 提案是建议的候选提案。在这个高级阶段,规范的编辑人员和评审人员必 须在最终规范上签字。Stage 3 的提案不会有太大的改变,在对外发布之前只是修正一些问题;
- Stage 4:finished(完成),进入 Stage 4 的提案将包含在 ECMAScript 的下一个修订版中
Babel
Babel
是一个工具链,主要用于旧浏览器或者缓解中将ECMAScript 2015+
代码转换为向后兼容版本的 JavaScript
。它包括:语法转换、源代码转换、Polyfill实现目标缓解缺少的功能等。
例如:(箭头函数转普通函数)
js
// 使用 Babel 转译前
arr.map(item => item + 1)
// 转译后
arr.map(function (item){
return item + 1;
})
提示:Babel 还提供了一个在线版的 REPL 页面,读者可在 babeljs.io/repl 实时体验功能效果。
需要借助 babel-loader
来实现转译功能
安装
@babel/core
: babel 核心代码 必须安装
@babel/preset-env
: babel 预设,
bash
npm i -D @babel/core @babel/preset-env babel-loader
使用:可以在 module.rule
中进行配置,也可以新建 .babelrc
配置文件进行配置
js
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
],
},
原理
编译器的工作流程:
- 解析阶段(Parsing)
- 转换阶段(Transformation)
- 生成阶段(Code Generation)
可以查看一个开源的小型编译器 是如何实现的
具体工作流程
原生代码 -> 词法分析 -> tokens 数组 -> 语法分析(成为parsing) -> AST 抽象语法树 -> 遍历 -> 访问 -> 应用插件 -> 新的AST抽象语法树 -> 目标源代码
预设 preset
常见的预设有:
babel-preset-react
:包含 React 常用插件的规则集,支持preset-flow
、syntax-jsx
、transform-react-jsx
等;@babel/preset-typescript
:用于转译 TypeScript 代码的规则集@babel/babel-preset-env
:更智能的预设,无需考虑环境因素,让包体积更小
babel-preset-env
可以配置目标浏览器 browserslist ,不同浏览器的兼容是不一样的,打包出来的代码也可能是不一样的
js
options: {
presets: [
['@babel/preset-env', {
// targets: 'last 2 version',
targets: {
'chrome': '88'
}
}]
],
},
在 babel7 之前,我们能看到使用这样配置 stage 预设
js
{
"presets": ["stage-0"]
}
在 babel7 以及之后,建议使用 preset-env
来设置
polyfill
polyfill 可以理解为补丁的意思,可以帮助我们更好的使用 JavaScript。比如我们使用了一些语法特性(例如:Promise, Generator, Symbol等以及实例方法例如 Array.prototype.includes等)但是某些浏览器压根不认识这些特性,必然会报错。就可以使用 polyfill 来打补丁。
- babel 7.4.0 之前,可以使用 @babel/polyfill 包来进行打补丁,现在不推荐了
- babel 7.4.0 之后,可以通过 core-js 和 regenerator-runtime 来完成polyfill 的使用
bash
npm i core-js regenerator-runtime
我们需要在 babel
的配置文件中,比如 babel.config.js
文件中进行配置,给preset-env
配置一些属性
- useBuiltIns:设置以什么样的方式来使用polyfill。
- entry 表示会根据 browserslist 目标导入所有的polyfill,但是对应的包也会变大
- usage 表示在使用的时候按需导入,需要排除
node_modules
:exclude: /node_modules/
- false 表示不使用 polyfill 进行适配,这个时候也就不需要使用 corejs 来指定版本了
- corejs:设置corejs的版本,目前使用较多的是3.x的版本,比如我使用的是3.38.x的版本;
- 另外corejs可以设置是否对提议阶段的特性进行支持;
- 设置 proposals属性为true即可
js
presets: [
['@babel/preset-env', {
targets: 'last 2 version',
useBuiltIns: 'entry',
corejs: 3.8
}]
],
]
TypeScript
Webpack
有很多种接入 TypeScript
的方法,包括 ts-loader
、awesome-ts-loader
、 babel-loader
。通常可使用 ts-loader
构建 TypeScript
代码
bash
npm i -D typescript ts-loader
使用命令初始化 ts 配置文件
bash
npx tsc --init
使用 ts-loader
js
{
test: /\.ts$/,
exclude: /node_modules/,
use: 'ts-loader'
},
除了可以使用TypeScript Compiler
来编译TypeScript
之外,我们也可以使用Babel。推荐使用preset :
@babel/preset-typescript
bash
npm i -D @babel/preset-typescript
js
presets: [
['@babel/preset-env', {
targets: 'last 2 version',
useBuiltIns: 'usage',
corejs: 3
}],
['@babel/preset-typescript']
],
js
{
test: /\.ts$/,
exclude: /node_modules/,
use: 'babel-loader'
}
不过,@babel/preset-typescript
只是简单完成代码转换,并未做类似 ts-loader
的类型检查工作。
我们使用Babel
来完成代码的转换,使用 tsc
来进行类型的检查。
json
{
"scripts": {
"build": "webpack",
"type-check": "tsc --noEmit"
},
}
ESLint
安装
bash
npm i -D eslint
初始化配置文件
bash
npx eslint --init
选择自己所需的配置
如果每次校验时,都需要执行一次npm run eslint
就有点麻烦了,所以我们可以使用一个VSCode
的插件: ESLint
。它会找出这些风格不一致的地方,并予以告警
编译时对代码进行检测可以使用 eslint-loader
或者 eslint-webpack-plugin
bash
npm i -D eslint-webpack-plugin eslint-loader
除常规 JavaScript 代码风格检查外,我们还可以使用适当的 ESLint 插件、配置集实现更丰富的检查、格式化功能
eslint-config-airbnb
:Airbnb 提供的代码风格规则集,算得上 ESLint 生态第一个成名的规则集合eslint-config-standard
:Standard.js 代码风格规则集,史上最便捷的统一代码风格的方式eslint-plugin-vue
:实现对 Vue SFC 文件的代码风格检查eslint-plugin-react
:实现对 React 代码风格检查@typescript-eslint/eslint-plugin
:实现对 TypeScript 代码风格检查eslint-plugin-sonarjs
:基于Sonar
的代码质量检查工具,提供圈复杂度、代码重复率等检测功能