第三章:代码编译篇(Browserslist
&PostCss
&Babel
)
上一篇:第三章:《统一代码风格篇》(.vscode/setting.json
&EditorConfig
&ESLint
&Stylelint
&Prettier
&husky
&lint-staged
&commitlint
)
所有的源码都在这里(如果觉得对你有帮助,求star支持,感谢!🙏)
6. Browserslist - 🦔在不同前端工具之间共享目标浏览器和Node.js版本的配置
这个东西主要是用来在不同的前端工具之间共享目标浏览器,例如Autoprefixer
、Stylelint
和babel-preset-env
,也就是说它本身其实没有什么功能,是用来配合其它工具一起使用的。一般我们直接通过配置文件列出项目需要支持的浏览器和node版本就可以了(可以直接运行npx browserslist
查看browserslist的配置信息)
- 创建
.browserslistrc
# Browsers that we support
defaults
not IE 11
# maintained node versions
复制代码
注意,这里我没并没有去下载browserslist(
npm i browserslist
),因为browserslist应该始终运用最新的版本!(npx browserslist XXX
)
7. PostCSS - 使用JS插件转换样式
postcss是一个使用JS插件转换样式的工具(通过将它们转换为抽象语法树)。这些插件可以lint您的CSS、支持变量和混合、转换未来的CSS 语法、内联图像等等。这是官方的介绍,有点不太好理解,其实简单来说就是postcss会把css之类的样式文件转化成AST(抽象语法树),然后再通过其它插件给这些样式文件做一些有用的事情,比如自动添加浏览器前缀
- 下载
postcss
和postcss-cli
npm i postcss postcss-cli
复制代码
- 下载
postcss-preset-env
npm i postcss-preset-env
复制代码
postcss-preset-env就是上面我们提到的会用到browserslist(获取项目需要支持的浏览器)和postcss(获取css转化后的AST)的插件之一,它允许您将现代CSS转换为大多数浏览器可以理解的内容,根据您的目标浏览器或运行时环境确定您需要的polyfill
- 创建
.postcssrc.json
{
"plugins": {
"postcss-preset-env": {}
}
}
复制代码
对,这个配置就是这么简单,意思就是在postcss将样式文件转为AST后使用
postcss-preset-env
来让样式文件兼容所有的目标浏览器,最后再转回为样式文件
- 编辑
package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"type-check": "tsc --noemit",
"eslint": "eslint src/**/*.{js,ts}",
"stylelint": "stylelint src/**/*.{css,less,scss}",
"prettier": "prettier src/**/* --write",
"lint": "npm run eslint && npm run stylelint && npm run prettier",
"prepare": "husky install",
+ "postcss": "postcss src/**/*.{css,less,scss} --base src --dir build",
},
复制代码
现在我们可以尝试一下把
.browserslistrc
配置文件中所支持的浏览器改成较低的版本,比如IE浏览器
,然后写一些比较新的css语法,比如::placeholder { color: gray; }
,最后执行npm run postcss
,就可以看到build
目录下会输出处理过的css文件,并且自动添加了浏览器前缀
8. Babel - 是一个JavaScript编译器,立即使用下一代JavaScript
Babel是一个工具链,主要用于将采用ECMAScript 2015+语法编写的代码转换为向后兼容的JavaScript语法,以便能够运行在当前和旧版本的浏览器或其他环境中。这是官方的介绍,简单来说,babel和上面的postcss作用差不多,只不过这里是作用在js文件上的
1. 下载@babel/core
和@babel/cli
npm i @babel/core @babel/cli -D
复制代码
这两个是babel的核心包和命令行包
2. 下载@babel/preset-env
npm i @babel/preset-env -D
复制代码
@babel/preset-env它是一个智能预设,允许您使用最新的JavaScript,而无需微观管理目标环境需要哪些语法转换(以及可选的浏览器polyfill)。其实和上面的postcss-preset-env其实作用差不多,只不过这里用来转译js文件(用于编译ES2015+语法)
3. 下载core-js
和regenerator-runtime
npm i core-js regenerator-runtime -S
复制代码
注意:这两个包是需要下载到dependencies
(生产依赖)中的,因为这是一个需要在你的源码之前运行的 polyfill
core-js(用于填充ECMAScript特性)和regenerator-runtime(需要使用转译的生成器函数)这两个包是为上面的
@babel/preset-env
配置项服务的,主要是用polyfill
来模拟完整的ES2015+环境,比如Object.assign
之类的静态方法,为了添加这些功能polyfill
将添加到全局范围(global scope)和类似String
这样的原生原型(native prototypes)中
4. 下载@babel/plugin-transform-runtime
和@babel/runtime
npm i @babel/plugin-transform-runtime -D
npm i @babel/runtime -S
复制代码
注意:@babel/runtime作为生产依赖项(因为它用于“运行时”)
@babel/plugin-transform-runtime(可以重用babel的注入帮助代码以节省代码大小)和@babel/runtime(所有
babel helpers
都将引用该模块),这两个包是Babel使用非常小的帮助器来处理常见的功能,例如_extend
,默认情况下,这将添加到需要它的每个文件中。这种重复有时是不必要的,尤其是当您的应用程序分布在多个文件中时。这就是@babel/plugin-transform-runtime
插件的用武之地:所有助手都将引用该模块@babel/runtime
,以避免在编译输出中出现重复,运行时将编译到您的构建中。
5. 创建.babel.config.json
{
// 预设
"presets": [
[
"@babel/preset-env",
// 按需导入 polyfills (core-js regenerator-runtime)
{
"useBuiltIns": "usage",
"corejs": "3.6.5"
}
],
// "@babel/preset-typescript"
],
// // 插件
"plugins": [
[
// 自动删除内联 babel helpers 并使用模块导入 (@babel/runtime)
"@babel/plugin-transform-runtime",
{
// 不导入 polyfills (@babel/runtime-corejs3)
"corejs": false
}
]
]
}
复制代码
babel的配置稍微复杂一点,我们可以看到,它的配置主要分为两大部分:(我们可以先把.browserslistrc
配置文件中所支持的浏览器改成较低的版本方便看效果)
-
presets
是预设的意思,可以被看作是一组babel插件和/或options
配置的可共享模块 -
比如
@babel/preset-env
它就是一个预设,主要用来用于编译ES2015+语法,比如我们在index.js文件写一行const a = 1
,运行npx babel src --extensions .js --out-dir lib
,就可以看到lib
目录下会输出处理过的js文件,并且编译成了var a = 1
-
后面是它的配置项,默认它会读取
browserslist
的配置信息进行兼容性编译,"useBuiltIns": "usage"
将检查你的所有代码,以便查找目标环境中缺失的功能,然后只把必须的 polyfill 包含进来,"corejs": "3.6.5"
是显示指定要使用的corejs版本,比如我们在index.js文件写一行Object.assign({}, { a: 1 })
,运行刚刚的命令,就可以看到lib
目录下会输出处理过的js文件,并且为我们自动从core.js
中引入了object.assign
的polyfill
-
plugins
是插件的意思,通过将插件(或预设)应用到您的配置文件来启用Babel的代码转换 -
比如
@babel/plugin-transform-runtime
它就是一个插件,主要用来重用babel的注入帮助代码以节省代码大小,比如我们在index.js文件写一行class A { }
,运行刚刚的命令,就可以看到lib
目录下会输出处理过的js文件,并且可以看到一些辅助函数会从@babel/runtime
导入进来。然后把这行配置注释掉再运行一次命令,对比看一下两次的输出文件,可以很明显的看到第二次的结果会复杂很多,可以看到一些辅助函数都变成了在文件声明的了,这意味着每个包含类的文件每次都会重复这些辅助函数 -
后面是它的配置项,
"corejs": false
表示不在这里使用polyfills
(如果需要在这里使用需要把刚刚下载的@babel/runtime
换成@babel/runtime-corejs3
),而是交给上面的@babel/preset-env
去处理,它们之间的区别是在这里使用不会污染全局作用域,虽然这对于应用程序或命令行工具来说可能没问题,但如果您的代码是一个您打算发布以供其他人使用的库,或者您无法完全控制代码运行的环境,那么它就会成为一个问题。感兴趣的同学可以尝试一下对比一下
6. 编辑package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"type-check": "tsc --noemit",
"eslint": "eslint src/**/*.{js,ts}",
"stylelint": "stylelint src/**/*.{css,less,scss}",
"prettier": "prettier src/**/* --write",
"lint": "npm run eslint && npm run stylelint && npm run prettier",
"prepare": "husky install",
"postcss": "postcss src/**/*.{css,less,scss} --base src --dir build",
+ "babel": "babel src --extensions .js,.ts --out-dir lib",
},
复制代码
这里新增一条脚本命令用来遍历src目录下的所有js文件,然后通过babel进行编译