重新编辑,重发

最近沉迷 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 倍

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