附录:babel配置详解
上文编译script、ts、tsx内容使用的是babel,提到了会使用本地的配置文件:

主要就是配置了一个presets,presets即babel的预设,作用是方便使用一些共享配置,可以简单了解为包含了一组插件,babel的转换是通过各种插件进行的,所以使用预设可以免去自己配置插件,可以使用本地的预设,也可以使用发布在npm包里的预设,预设可以传递参数,比如上图,使用的是@varlet/cli包里附带的一个预设:

预设其实就是一个js文件,导出一个函数,这个函数可以接受两个参数,api可以访问babel自身导出的所有模块,同时附带了一些配置文件指定的api,options为使用预设时传入的参数,这个函数需要返回一个对象,这个对象就是具体的配置。
// varlet-cli/src/config/babel.config.ts
module.exports = (api?: ConfigAPI, options: PresetOption = {}) => {
if (api) {
// 设置不要缓存该配置,每次都执行函数重新获取
api.cache.never()
}
// 判断打包格式
const isCommonJS = process.env.NODE_ENV === 'test' || process.env.BABEL_MODULE === 'commonjs'
return {
presets: [
[
require.resolve('@babel/preset-env'),
{
// 编译为commonjs模块类型时需要将ESM模块语法转换成commonjs模块语法,否则保留ESM模块语法
modules: isCommonJS ? 'commonjs' : false,
loose: options.loose,// 是否允许@babel/preset-env预设中配置的插件开启松散转换,https://cloud.tencent.com/developer/article/1418101
},
],
require.resolve('@babel/preset-typescript'),
require('./babel.sfc.transform'),
],
plugins: [
[
require.resolve('@vue/babel-plugin-jsx'),
{
enableObjectSlots: options.enableObjectSlots,
},
],
],
}
}
export default module.exports
又配置了三个预设,无限套娃,@babel/preset-env预设是一个智能预设,会根据你的目标环境自动判断需要转换哪些语法,@babel/preset-typescript用来支持ts语法,babel.sfc.transform是varlet自己编写的,用来转换Vue单文件。
还配置了一个babel-plugin-jsx插件,用来在Vue中支持JSX语法。
预设和插件的应用顺序是有规定的:
- 插件在预设之前运行
- 多个插件按从第一个到最后一个顺序运行
- 多个预设按从最后一个到第一个顺序运行
基于此我们可以大致窥探一下整个转换流程,首先运行插件@vue/babel-plugin-jsx转换JSX语法,然后运行预设babel.sfc.transform:
// varlet-cli/src/config/babel.sfc.transform.ts
import { readFileSync } from 'fs'
import { declare } from '@babel/helper-plugin-utils'
module.exports = declare(() => ({
overrides: [
{
test: (file: string) => {
if (/.vue$/.test(file)) {
const code = readFileSync(file, 'utf8')
return code.includes('lang="ts"') || code.includes("lang='ts'")
}
return false
},
plugins: ['@babel/plugin-transform-typescript'],
},
],
}))
通过babel的overrides选项来根据条件注入配置,当处理的是Vue单文件的内容,并且使用的是ts语法,那么就会注入一个插件@babel/plugin-transform-typescript,用于转换ts语法,非Vue单文件会忽略这个配置,进入下一个preset:@babel/preset-typescript,这个预设也包含了前面的@babel/plugin-transform-typescript插件,但是这个预设只会在.ts文件才会启用ts插件,所以前面才需要自行判断Vue单文件并手动配置ts插件,ts语法转换完毕后最后会进入@babel/preset-env,进行js语法的转换。