axetroy/blog

我是如何把vscode扩展的启动速度提升80倍的

Opened this issue · 2 comments

重新编辑,重发

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

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

Screen shot

代码很简单也很少,用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 倍

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

我在 nextjs 用了好多仅在浏览器用的模块, 用这种方法解决了总算解决了服务端路由的时候会引入浏览器模块的问题

我去。速度快这么多