我是如何把vscode扩展的启动速度提升80倍的
发布于 5 年前 作者 axetroy 5977 次浏览 来自 分享

重新编辑,重发

最近沉迷 vscode 扩展无法自拔,开启写了新坑,也维护旧扩展。

其中就有这么一个扩展是这样的: 显示导入的包版本号。

js ts vue

代码很简单也很少,用Babel/Typescript/vue-component分别解析对应的文件,然后标注版本号。

然而就是这么功能简单的扩展,启动速度居然超过其他所有稍微复杂一点的扩展。

2019-03-05 02 20 51

启动速度 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! 大功告成,就这么简单。

结果对比

在我把这个简单的扩展按照上面的方式重构一遍之后,来看一下启动速度

2019-03-05 02 21 57

更改后启动速度竟然仅用了31ms, 比之前快了 80 倍

最后愿天下没有拖慢速度的扩展,宇宙第一编辑器已经够慢了

10 回复

感觉很优秀啊

@chinahsj 那你负责秀啊

==那个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() 方法中动态导入)

你把我秀到了

回到顶部