如何从0开始搭建1个前端项目?第三章(代码编译篇 - Browserslist&PostCss&Babel)

如何从0开始搭建1个前端项目?第三章(代码编译篇 - Browserslist&PostCss&Babel)

第三章:代码编译篇(Browserslist&PostCss&Babel

上一篇:第三章:《统一代码风格篇》.vscode/setting.json&EditorConfig&ESLint&Stylelint&Prettier&husky&lint-staged&commitlint

favicon.svg 所有的源码都在这里(如果觉得对你有帮助,求star支持,感谢!🙏)

6. Browserslist - 🦔在不同前端工具之间共享目标浏览器和Node.js版本的配置

这个东西主要是用来在不同的前端工具之间共享目标浏览器,例如AutoprefixerStylelintbabel-preset-env,也就是说它本身其实没有什么功能,是用来配合其它工具一起使用的。一般我们直接通过配置文件列出项目需要支持的浏览器和node版本就可以了(可以直接运行npx browserslist查看browserslist的配置信息)

  1. 创建.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(抽象语法树),然后再通过其它插件给这些样式文件做一些有用的事情,比如自动添加浏览器前缀

  1. 下载postcsspostcss-cli
npm i postcss postcss-cli
复制代码
  1. 下载postcss-preset-env
npm i postcss-preset-env
复制代码

postcss-preset-env就是上面我们提到的会用到browserslist(获取项目需要支持的浏览器)和postcss(获取css转化后的AST)的插件之一,它允许您将现代CSS转换为大多数浏览器可以理解的内容,根据您的目标浏览器或运行时环境确定您需要的polyfill

  1. 创建.postcssrc.json
{
  "plugins": {
    "postcss-preset-env": {}
  }
}
复制代码

对,这个配置就是这么简单,意思就是在postcss将样式文件转为AST后使用postcss-preset-env来让样式文件兼容所有的目标浏览器,最后再转回为样式文件

  1. 编辑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-jsregenerator-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.assignpolyfill

  • 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进行编译

favicon.svg 所有的源码都在这里(如果觉得对你有帮助,求star支持,感谢!🙏)

下一篇:第四章《代码打包篇》webpack

分类:
前端