敝地唤做火焰山,无春无秋,却有八百里火焰,四周围寸草不生。若过得山,就是铜脑盖,铁身躯,也要化成汁哩-《西游记》
这里是Tech 快报,每两周为你带来新鲜的技术资讯,如果想第一时间收到快报更新消息请关注本知识库。 本期快报速览:
头条
Vite 3.0 is out!
vitejs.dev/blog/announ… 去年 2 月 Vite 2 发布,它的采用率不断增长,每周 npm 下载量超过 100 万次,迅速形成了庞大的生态系统。时隔 16 个月 Vite 3 正式发布,让我们一起来探索下新版本都有哪些特点。
开发改进:
- 快速命令行
VITE v3.0.0 ready in 320 ms
➜ Local: http://127.0.0.1:5173/
➜ Network: use --host to expose
- 改进的 WebSocket 连接策略: Vite 3 更改了默认的连接方案, 开箱即用 vite-setup-catalogue.
- 冷启动改进:Vite 现在可以避免在冷启动期间完全重新加载,当插件在抓取初始静态导入的模块时注入导入
- import.meta.glob:import.meta.glob支持被重写,详情阅读Glob 导入指南中的新功能。
- WASM 导入与未来标准保持一致
构建改进:
- SSR 默认使用 ESM 构建
- Improved Relative Base Support
兼容性说明:
- Vite 不再支持已达到 EOL 的 Node.js 12 / 13 / 15。现在需要 Node.js 14.18+ / 16+。
- Vite 现在以 ESM 的形式发布,并带有 ESM 的 CJS 代理以实现兼容性。
- 现代浏览器基线支持原生 ES 模块、原生 ESM 动态导入特性和 import.meta features 的浏览器。
- Chrome >=87
- Firefox >=78
- Safari >=13
- Edge >=88
- 更多说明在迁移指南中了解。
体积减少:
发布大小 | 安装尺寸 | |
---|---|---|
快 2.9.14 | 4.38MB | 19.1MB |
快速 3.0.0 | 3.05MB | 17.8MB |
减少 | -30% | -7% |
精选
浅析 ESLint 原理
ESLint 我们已经非常熟悉了,今天一起来看看它的工作原理。
规则:
{
"rules": {
// 规则示例
"no-console" : 0, // 0 1 2 ('off' 'warn' 'error';)
"quotes" : [ "error" , "single" ]
}
}
规则
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Disallow `with` statements",
recommended: true,
url: "https://eslint.org/docs/rules/no-with"
},
schema: [],
messages: {
unexpectedWith: "Unexpected use of 'with' statement."
}
},
create(context) {
return {
WithStatement(node) {
context.report({ node, messageId: "unexpectedWith" });
}
};
}
};
meta
: 规则的类型,文档,是否推荐规则,是否可修复; creat
:返回一个包含 ESLint 遍历 JavaScript 代码抽象语法树 AST 时,用来访问节点方法的对象( key 的类型决定背后的执行逻辑)
执行过程
execute
函数:解析参数,初始化 ,调用engine.executeOnFiles
读取源代码进行检查,返回报错信息和修复结果。executeOnFiles
函数:该函数输入文件目录,调用verifyText()
函数执行检查,返回 lint 之后的结果。- 迭代所有的文件路径及信息;
- 检查是否忽略的文件,lint缓存 等等一堆操作;
- 调用 verifyText() 函数执行检查
- 储存lint之后的结果
verifyText
函数:调用了linter.verifyAndFix()
函数verifyAndFix
函数:通过一个 do while 循环控制去verify
&fix
/**
* This loop continues until one of the following is true:
*
* 1. No more fixes have been applied.
* 2. Ten passes have been made.
* That means anytime a fix is successfully applied, there will be another pass.
* Essentially, guaranteeing a minimum of two passes.
*/
do {
passNumber++; // 初始值0
// 这个函数就是 verify 在 verify 过程中会把代码转换成ast
debug(`Linting code for ${debugTextDescription} (pass ${passNumber})`);
messages = this.verify(currentText, config, options);
// 这个函数就是 fix
debug(`Generating fixed text for ${debugTextDescription} (pass ${passNumber})`);
fixedResult = SourceCodeFixer.applyFixes(currentText, messages, shouldFix);
/*
* 如果有 syntax errors 就 break.
* 'fixedResult.output' is a empty string.
*/
if (messages.length === 1 && messages[0].fatal) {
break;
}
// keep track if any fixes were ever applied - important for return value
fixed = fixed || fixedResult.fixed;
// 使用fix之后的结果 代替原本的text
currentText = fixedResult.output;
} while (
fixedResult.fixed &&
passNumber < MAX_AUTOFIX_PASSES // 10
);
- 调用
parse
函数,把代码转换成AST:
// 默认的ast解析是espree
const espree = require("espree");
let parserName = DEFAULT_PARSER_NAME; // 'espree'
let parser = espree;
runRules
函数:- 创建一个 eventEmitter 实例。
- 递归遍历 AST,深度优先搜索,把节点添加到 nodeQueue。一个node放入两次,类似于A->B->C->...->C->B->A;
- 遍历 rules,调用 rule.create()(rules中提到的meta和create函数) 拿到事件(selector)映射表,添加事件监听。
- 包装一个 ruleContext 对象,会通过参数,传给 rule.create(),其中包含 report() 函数,每个rule的 handler 都会执行这个函数,抛出问题;
- 调用 rule.create(ruleContext), 遍历其返回的对象,添加事件监听;(如果需要lint计时,则调用process.hrtime()计时);
- 遍历 nodeQueue,触发当前节点事件的回调,调用 NodeEventGenerator 实例里面的函数,触发 emitter.emit()。
运行机制