重新编辑,重发
最近沉迷 vscode 扩展无法自拔,开启写了新坑,也维护旧扩展。
其中就有这么一个扩展是这样的: 显示导入的包版本号。
代码很简单也很少,用Babel/Typescript/vue-component
分别解析对应的文件,然后标注版本号。
然而就是这么功能简单的扩展,启动速度居然超过其他所有稍微复杂一点的扩展。
启动速度 2431ms
这不科学呀, 到底是慢在哪里呢?
分析了一下 profile
文件后,发现不是我写的代码慢,而是慢在了加载的第三方库
Typescript 的通病
Typescript 跟随 ECMA 标准,import 必须放在顶部.
import * as ts from 'typescript';
export function parser() {
// 这里是你的业务逻辑
ts.parser();
}
问题就在于这. typescript
在编译成javascript
之后
const ts = require("typescript")
export.parser = function parser() {
// 这里是你的业务逻辑
ts.parser()
}
我们都知道require 函数加载模块都是同步进行的, 也就是我还没使用parser
函数的时候,就加载这个模块了。
而第三方模块加载,根据不同的包,加载时间各不相同。因为有些包,会在加载的时候做一些同步的初始化操作
// 某第三方包
// 这里做一些同步操作
// 例如定义map,for循环之类的
// 导出函数
export default function() {}
而恰巧,Typescript 和 Babel/Babel-types 都有大量的这种操作, 导致拖慢了扩展初始化速度.
解决方案
问: 能不能在我使用这个函数的时候,才导入相应的包? 答: require 就可以
- import * as ts from 'typescript';
export function parser() {
// 这里是你的业务逻辑
+ const ts = require('typescript');
ts.parser();
}
问题就来了,require
的模块是没有类型。那使用typescript
开发的体验就不是很好了.
我们稍微改造一下
- import * as ts from 'typescript';
+ import TS = require('typescript'); // 这里只是导入类型而已
export function parser() {
// 这里是你的业务逻辑
+ const ts:typeof TS = require('typescript'); // 给require的模块附上类型
ts.parser();
}
OK! 大功告成,就这么简单。
结果对比
在我把这个简单的扩展按照上面的方式重构一遍之后,来看一下启动速度
更改后启动速度竟然仅用了31ms
, 比之前快了 80 倍
最后愿天下没有拖慢速度的扩展,宇宙第一编辑器已经够慢了
感觉很优秀啊
@chinahsj 那你负责秀啊
硬核,赞
赞
装上了 cooool
==那个import = 不是只引入类型 后面也没必要重复 再require 加载速度快了只是因为impoert 是静态加载 require是运行时加载
👍 这个应该叫懒加载或惰性加载。以前PHP做框架,这个都还挺重要的
import * as TS from 'typescript';
import TS = require('typescript');
这两个是一样的,只不过这个TS的变量只能用在类型定义上,这样才能做到动态加载,如果用在一些会被转换成js的表达式上。还是会一开始就引入这个包
这样更好:
import * as TS from 'typescript'
export function parser() {
// 这里是你的业务逻辑
const ts: typeof TS = require('typescript')
ts.parser()
}
需要注意的是,其它地方不能调用 TS 的对象,否则 tsc 编译的时候就会在顶部导入模块实例(现在是仅仅用于编译阶段的类型检查,而实际是在 parse() 方法中动态导入)
你把我秀到了