智能助手 

外观
约 777 字大约 3 分钟
2024-07-20
在高版本的 vue cli(webpack5+)加持下, 需要个人做的优化项已经很少了,脚手架已经帮助我们做了很多的优化。
在项目中尽量使用最新的工具,以此来使用最佳的性能。 同时此次测试也不全, 在打包优化方面更需要具体问题具体分析, 根据项目大小进行适当的配置。 在配置时区分开发环境和生产环境。
实现该 loader 的目的是减少开发者在项目中主动添加 try-catch 模块的操作。当代码中有 async 和 await 时在 webpack 打包时自动为代码添加 try-catch。
构建一个 js 文件的解析器(loader),主要实现工具: babel参考链接、loader-utils参考链接
工具函数:
实现代码:
const { parse } = require("@babel/parser")
const traverse = require("@babel/traverse").default
const type = require("@babel/types")
const core = require("@babel/core")
const loaderUtils = require("loader-utils")
// 提供默认的loader option
const DEFAULT_OPTIONS = {
catchCode: (identifier) => `console.error(${identifier})`,
identifier: "error",
finallyCode: null,
}
/**
* source: js源文件
*/
function tryCatchLoader(source) {
let options = loaderUtils.getOptions(this)
options = {
...DEFAULT_OPTIONS,
...options,
}
// 表示是否传入了 catch 块内部的代码
if (typeof options.catchCode === "function") {
options.catchCode = options.catchCode(options.identifier)
}
// 定义即将添加的 try-catch-finally 代码块中的代码
let catchNode = parse(options.catchCode).program.body
let finallyNode =
options.finallyCode && parse(options.finallyCode).program.body
// 1. 生成AST
let ast = parse(source, {
sourceType: "module", // 支持 es6 module
plugins: ["dynamicImport"], // 支持动态 import
})
// 2. 遍历AST, 对 AST进行更改
traverse(ast, {
// 3. 在语法树中锁定 await 表达式类型
AwaitExpression: function (path) {
// 4. 通过 while 递归向上查找 async function 的节点,修改AST
while (path && path.node) {
let parentPath = path.parentPath
// 4.1 确认 await的顶层 async 函数节点
let isAwaitParentNode =
type.isBlockStatement(path.node) && isAsyncFuncNode(parentPath.node)
// 4.2 是否已经有 try-catch
let hasTryCatch =
type.isBlockStatement(path.node) &&
type.isTryStatement(parentPath.node)
if (isAwaitParentNode) {
// 4.3 构建新的AST
let tryCatchAst = type.tryStatement(
path.node,
type.catchClause(
type.identifier(options.identifier),
type.blockStatement(catchNode)
),
finallyNode && type.blockStatement(finallyNode)
)
path.replaceWithMultiple([tryCatchAst])
break
} else if (hasTryCatch) {
break
}
// 循环的变量
path = parentPath
}
},
})
// 5. 给定新的 AST , 并转换
return core.transformFromAstSync(ast, null, {
configFile: false,
}).code
}
/**
* @param AST Node
*/
function isAsyncFuncNode(node) {
const res =
type.isFunctionDeclaration(node, {
// 函数声明
async: true,
}) ||
type.isArrowFunctionExpression(node, {
//箭头函数
async: true,
}) ||
type.isFunctionExpression(node, {
// 函数表达式
async: true,
}) ||
type.isObjectMethod(node, {
// 对象的方法
async: true,
})
return res
}
module.exports = tryCatchLoader
工具函数:
版权归属:tuyongtao1