这是我参与「第四届青训营 」笔记创作活动的的第3天
何为预处理?
预处理一般是指在程序源代码被翻译为目标代码的过程中,生成之前的过程。典型地,由预处理器(preprocessor) 对程序源代码文本进行处理,得到的结果再由编译器核心进一步编译。这个过程并不对程序的源代码进行解析,但它把源代码分割或处理成为特定的单位——(用C/C++的术语来说是)预处理记号(preprocessing token)用来支持语言特性(如C/C++的宏调用)。
上方为官方解释,但我认为对于前端来说,预处理器就是将高级别的JS或CSS代码转换为低级别JS或CSS代码的一个工具而已。 主要分两类:
- JS预处理器
- CSS预处理器
JS预处理器
典型Babel
Babel 是一个工具链,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
下面列出的是 Babel 能为你做的事情:
1.语法转换
2.通过 Polyfill 方式在目标环境中添加缺失的特性 (通过 @babel/polyfill 模块)
3.源码转换 (codemods)
工作流程
大致可以分为三个阶段:
parsing:内部的 babylon 负责将es6代码进行语法分析和词法分析后转换成抽象语法树
transforming:内部的 babel-traverse 负责对抽象语法树进行变换操作
printing:内部的 babel-generator 负责生成对应的代码
插件 plugins
babel 本身是一个工具链,而最终的实现是用来完成的,插件是一个 js 程序用来指示 babel 怎么对 js 进行转换。 插件分两种:
转换插件:用于转换代码,比如 arrow-functions 转换钩子函数
语法插件:用于解析特定类型的语法,比如 jsx。使用转换插件时会自动启用对应的语法插件。
预设 presets
另外插件组成的数组叫预设,可以一次性使用多个插件并共享选项。
常用预设 preset-env
preset-env是一组babel相关的plugin集合(如将箭头函数转换为function,let, const转换为var等一些列插件的集合)。
注意!这里的转换仅限于语法上的转换,而不涉及到API的转换,如
Promise,Array.prototype.includes等都不能转换。这就需要引出@bable/polyfill
引入@bable/polyfill方式如下:
module.exports = {
presets: [
[
"@babel/env",
{
useBuiltIns: "usage", // 实现按需加载
corejs: {
version: 3,
/**
core-js 选项
可选值为:false, 2, 3 or { version: 2 | 3, proposals: boolean }, defaults to false.
通过提供了一个沙箱环境,利用 core-js 中实现的别名来 polyfill 对应功能,避免了污染全局。各个可选值表示以及对应依赖的 runtime helper 包分别为
false 不会 polyfill,@babel/runtime
2,依赖 core-js2,只支持全局变量和静态属性,@babel/runtime-corejs2
3,在 2 的基础上添加了实例属性,并且可以利用 proposals 选项启用提案的 polyfill,@babel/runtime-corejs3
**/
proposals: true
}
}
]
],
plugins: []
};
新起之秀SWC
SWC 是一个可扩展的基于 Rust 的平台,适用于下一代快速开发工具。它被Next.js,Parcel和Deno等工具以及Vercel,ByteDance,腾讯,Shopify等公司使用。
SWC 可用于编译和捆绑。对于编译,它采用使用现代JavaScript功能的JavaScript TypeScript文件,并输出所有主要浏览器都支持的有效代码。
SWC在单个线程上比Babel快20倍,在四个内核上比Babel快70倍。
CSS预处理器
Postcss
Postcss 是一个使用js插件来转换样式的工具,Postcss 的插件会检查你的css。
其中最常用的插件莫过于 autoprefixer 这个插件了,这个插件会添加浏览器前缀,避免了手动写-webkit-这样的代码。 在 Postcss 中还有很多好用的插件,比如可以自动转换 px 来进行适配不同显示器的 postcss-px-to-viewport,可以自动对Css属性依照设定的规则进行排序的 postcss-sorting 等等。
当然这已经在上篇所说的Vite中集成了
Autoprefixer
不加任何prefix的通常写法。
.example {
display: grid;
transition: all .5s;
user-select: none;
background: linear-gradient(to bottom, white, black);
}
Autoprefixer将使用基于当前浏览器支持的特性和属性数据去为你添加前缀。
你可以尝试下Autoprefixer的demo:Autoprefixer CSS online
由上图可以看出,像没有浏览器差异已经完全符合W3C标准的css2.1属性display,position等,Autoprefixer不会为其加前缀,而像css3属性transform就会为其加前缀,其中--webkit是chrome和safari前缀,--ms则是ie的前缀,像firefox由于已经实现了对transform的W3C标准化,因此使用transform即可。
因此Autoprefixer是一个非常有用的加速前端开发的一个工具。
使用配置(搭配打包工具)
由于我们项目使用Vite,咱只给出Vite配置,如下:
import vue from "@vitejs/plugin-vue";
import path from "path";
import { defineConfig } from "vite";
import autoprefixer from "autoprefixer";
import legacy from "@vitejs/plugin-legacy";
// https://vitejs.dev/config/
export default defineConfig({
css: {
postcss: {
plugins: [autoprefixer()],
},
},
plugins: [
vue({
reactivityTransform: true,
}),
legacy(),
],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});
需注意在 package.json 中配置 browserslist
{
"name": "@balabala/monitor-frontend",
"version": "1.0.0",
"type": "module",
"license": "MIT",
"scripts": {
"dev": "lerna bootstrap && scripty",
"build": "lerna bootstrap && scripty",
"preview": "lerna bootstrap && scripty",
"type-check": "vue-tsc --noEmit"
},
"dependencies": {
"@balabala/monitor-api": "^1.0.0",
"dayjs": "^1.11.4",
"echarts": "^5.3.3",
"font-awesome": "^4.7.0",
"normalize.css": "^8.0.1",
"pinia": "^2.0.19",
"vue": "^3.2.37",
"vue-datepicker-local": "^1.0.19",
"vue-echarts": "^6.2.3",
"vue-router": "^4.1.3"
},
"devDependencies": {
"@types/echarts": "^4.9.16",
"@vitejs/plugin-legacy": "^2.0.0",
"@vitejs/plugin-vue": "^3.0.0",
"autoprefixer": "^10.4.8",
"eslint-plugin-vue": "^9.3.0",
"vite": "^3.0.0",
"vue-tsc": "^0.38.4"
},
"browserslist": {
"production": [
"defaults",
"not IE 11"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version",
"last 1 edge version",
"last 1 ie version"
]
}
}