国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

如何提升VS Code擴展的啟動速度——不只是Webpack

xiaolinbang / 1092人閱讀

摘要:同時它又需要監聽事件,當物聯網設備插入計算機后做出響應。比如以熱啟動打開物聯網項目工作區的啟動時間在表中是毫秒,但是正在運行的擴展頁面中大約是毫秒。當在中應用懶加載時,無論是否使用打包模塊,沒有工作區時啟動速度都遠快于打開物聯網工作區。

概述
擴展可以讓用戶在VS Code中向開發工作流程添加新的語言、調試器和工具。VS Code提供了豐富的可擴展模塊,允許擴展訪問用戶界面、提供擴展功能。

通常情況下VS Code會安裝多個擴展,所以作為一名擴展開發者,我們應該時刻關注擴展的性能,避免拖慢其它擴展,甚至是VS Code的主進程。

下面是我們在開發一款擴展時應該遵循的原則:

避免使用同步方法。同步方法會阻塞整個Node的進程,直到其返回結果。所以,你應該盡可能地使用異步方法。如果發現很難用異步方法替換同步方法,那么你應該考慮一下重構代碼。

只引用你需要的模塊。有一些依賴模塊非常巨大,比如說lodash。通常我們不需要lodash的全部方法,所以引用整個lodash模塊并不合理。lodash的每個方法都有獨立的模塊,你應該只引用你需要的部分。

謹慎對待啟動條件。大多數情況下,你的擴展并不需要啟動。不用使用“*”作為啟動條件。如果你的擴展確實需要一直監聽一些事件,考慮將主要的代碼放在setTimeout里以低優先級運行。

按需加載模塊。import ... from ...是比較常用的引用模塊的方法,但是有時這并不一定是個好的方法。比如一個叫做request-promise的模塊,加載起來會耗費非常多的時間(在我自己這邊測試需要1至2秒),但可只能有在特定的情況下我們才會需要請求遠程的資源,比如本地的緩存過期了。

上面提到的前三個原則很多開發者已經遵守了,在這篇文章中,我們會討論按一種需加載的方法。這種方法要符合我們平時寫TypeScript和JavaScript的習慣,同時也要盡可能減少更改現有代碼的工作量。

按需加載模塊 符合習慣

一般來說,我們在腳本的最頂端使用import來加載模塊,比如下面的代碼:

import * as os from "os";

Node會同步加載指定的模塊,同時阻塞后面的代碼。

我們需要一個新的方法,比如叫做impor吧,用它可以引入模塊,但并不馬上加載這個模塊:

const osModule = impor("os"); // osModule不可訪問,因為os模塊還沒有被加載

為了達到這一目的,我們需要使用Proxy對象。Proxy對象被用來自定義一些基本操作的行為。

我們可以自定義get方法,只有當這個模塊被調用時我們才開始加載它。

get: (_, key, reciver) => {
    if (!mod) {
        mod = require(id);
    }
    return Reflect.get(mod, key, reciver);
}

使用Proxy對象后,osModule是一個Proxy實例,并且只有當我們調用它的一個方法后,os模塊才會被加載。

const osModule = impor("os"); // os模塊還沒有被加載
...
const platform = osModule.platform() // os模塊從這里開始加載

當我們只想使用模塊的一部分時,廣泛使用import {...} for ...的寫法。可是這讓Node不得不訪問這個模塊來檢查其屬性值。這樣getter就會被調用,模塊也會在那個時候被加載。

使用后臺任務加載模塊

按需加載還不夠,我們可以進一步來優化用戶體驗。在擴展啟動和用戶運行命令來加載模塊之間,我們有充足的時間來提前加載模塊。

很容易想到的一個辦法,是創建一個后臺任務來加載隊列里的模塊。

時間線

我們開發了一個名叫Azure IoT Device Workbench的擴展,它可以結合多個Azure服務和流行的物聯網開發板,簡單地進行物聯網項目的開發、編譯、部署和調試。

由于Azure IoT Device Workbench涉及到的范圍非常廣泛,所以這個擴展啟動起來非常繁重。同時它又需要監聽USB事件,當物聯網設備插入計算機后做出響應。

圖一:Azure IoT Device Workbench使用懶加載和正常加載的啟動時間

我們對比了Azure IoT Device Workbench在多種情況下使用懶加載和正常加載的啟動時間。圖一中由上到下的圖表分別是沒有工作區、打開非物聯網項目工作區和打開物聯網項目工作區時啟動。左側的圖表是冷啟動,右側是熱啟動。冷啟動只發生在第一次安裝擴展時,VS Code做一些緩存之后,都將是熱啟動。X軸表示時間,以毫秒為單位。Y軸是已加載的模塊數量。

With normal load, the extension is activated at end of the chart. We find the extension is activated very advanced with lazy load with both cold boot and warm boot, especially when VS Code launches without workspace open.

對于沒有工作區冷啟動的情況,懶加載的啟動速度大約有30倍的提升,熱啟動時有大約20倍的提升。打開非物聯網項目工作區時,冷啟動懶加載比正常加載快了10倍,熱啟動時快20倍。當VS Code打開物聯網項目時,Azure IoT Device Workbench需要引用大量模塊來加載項目,即使這樣,我們冷啟動時也偶兩倍的啟動速度,熱啟動時有3倍的啟動速度。

下面是懶加載的完整時間線:

圖二:Azure IoT Device Workbench使用懶加載的完整時間線

和圖一一樣,圖二中的圖表也表示冷啟動和熱啟動下沒有工作區、打開非物聯網項目工作區和打開物聯網項目工作區。

在圖中可以看到后臺任務加載模塊的加載時間階梯非常清晰。用戶很難注意到這個小動作,擴展啟動得非常順暢。

為了使這個提升性能的方法可以被所有VS Code擴展開發者使用,我們發布了一個名叫impor的Node模塊,并且我們已經將這個模塊用于Azure IoT Device Workbench。你可以對代碼進行很少的更改就將它應用到你的項目中。

模塊打包

幾乎所有的VS Code擴展都有Node模塊依賴。因為Node模塊的工作方式,依賴的曾經可能會非常深。另外,模塊的結果也可能非常復雜,也就是Node模塊黑洞所說的事情。

為了清理Node模塊,我們使用一個非常棒的工具,webpack。

webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關系圖(dependency graph),其中包含應用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 bundle。
Tree shaking
tree shaking 是一個術語,通常用于描述移除 JavaScript 上下文中的未引用代碼(dead-code)。它依賴于 ES2015 模塊系統中的靜態結構特性,例如 importexport。這個術語和概念實際上是興起于 ES2015 模塊打包工具 rollup。

使用webpack進行tree shaking非常簡單。我們需要指定一個入口文件和輸出文件名就可以,剩下的事情webpack會處理好。

使用tree shaking后,沒有被引用的文件,包括JavaScript代碼、markdown文件等等都會被移除。之后webpack會把所有文件整合成一個多帶帶的打包文件。

代碼分離

把所有代碼都合并成一個文件可不是一個好主意。為了與按需加載一同協作,我們需要把代碼分割成多個部分,并且只加載我們需要的部分。

現在,需要一種分離代碼的方法是我們需要解決的問題。一種可行的方案是將每個Node模塊分離成一個文件。不過手動將每個Node模塊的路徑寫進webpack配置文件中是無法接受的。幸好我們可以使用npm-ls來獲取產品模式下所有的Node模塊。這樣在webpack配置文件的輸出部分,我們使用[name].js作為輸出來編譯每個模塊。

應用打包后的模塊

當我們要加載一個模塊時,比如叫happy-broccoli,Node會先試著在node_modules文件夾中查找happy-broccoli.js。如果這個文件不存在,Node接著查找happy-broccoli文件夾下的index.js文件,如果還是找不到,就查看package.json里的main

為了應用打包后的模塊,我們可以把它們放進tsc輸出目錄下的node_modeles文件夾里。

如果哪個模塊不兼容webpack打包,就直接將它復制到輸出目錄的node_modules文件夾里。

這是一個擴展項目結構的例子:

|- src
|  |- extension.ts
|
|- out
|  |- node_modules
|  |  |- happy-broccoli.js
|  |  |- incompatible-with-bundle-module
|  |     |- package.json
|  |
|  |- extension.js
|
|- node_modules
|  |- happy-broccoli
|     |- package.json
|
|  |- incompatible-with-bundle-module
|     |- package.json
|
|- package.json
|- webpack.config.js
|- tsconfig.json

未打包Node模塊時Azure IoT Device Workbench包含了4368個文件,打包后只剩下了343個文件。

Webpack配置實例
"use strict";

const cp = require("child_process");
const fs = require("fs-plus");
const path = require("path");

function getEntry() {
  const entry = {};
  const npmListRes = cp.execSync("npm list -only prod -json", {
    encoding: "utf8"
  });
  const mod = JSON.parse(npmListRes);
  const unbundledModule = ["impor"];
  for (const mod of unbundledModule) {
    const p = "node_modules/" + mod;
    fs.copySync(p, "out/node_modules/" + mod);
  }
  const list = getDependeciesFromNpm(mod);
  const moduleList = list.filter((value, index, self) => {
    return self.indexOf(value) === index &&
        unbundledModule.indexOf(value) === -1 &&
        !/^@types//.test(value);
  });

  for (const mod of moduleList) {
    entry[mod] = "./node_modules/" + mod;
  }

  return entry;
}

function getDependeciesFromNpm(mod) {
  let list = [];
  const deps = mod.dependencies;
  if (!deps) {
    return list;
  }
  for (const m of Object.keys(deps)) {
    list.push(m);
    list = list.concat(getDependeciesFromNpm(deps[m]));
  }
  return list;
}

/**@type {import("webpack").Configuration}*/
const config = {
    target: "node",
    entry: getEntry(),
    output: {
        path: path.resolve(__dirname, "out/node_modules"),
        filename: "[name].js",
        libraryTarget: "commonjs2",
        devtoolModuleFilenameTemplate: "../[resource-path]",
    },
    resolve: {
        extensions: [".js"]
    }
}

module.exports = config;
與典型的webpack解決方案對比

不將整個擴展打包,而是對每個模塊分別打包會帶來很大的好處。使用webpack打包后,擴展極有可能會拋出數十個錯誤。把每個模塊分離開使調試變得非常容易。同時,按需加載指定的模塊也能盡可能地降低對性能的影響。

實驗結果

模塊打包應用在使用懶加載的Azure IoT Device Workbench上,來同正常加載進行對比。

圖三:Azure IoT Device Workbench懶加載打包模塊的啟動時間和正常加載對比

模塊打包大幅減少了啟動時間。對于冷啟動,在一起情況下懶加載甚至加載完所有模塊所消耗的全部時間都比正常加載所需的時間少。

正常 Webpack典型的解決方案* 懶加載 懶加載打包的模塊**
沒有工作區,冷啟動 19474 ms 1116 ms 599 ms 196 ms
沒有工作區,熱啟動 2713 ms 504 ms 118 ms 38 ms
非物聯網項目工作區,冷啟動 11188 ms 1050 ms 858 ms 218 ms
非物聯網項目工作區,熱啟動 4825 ms 530 ms 272 ms 102 ms
物聯網項目工作區,冷啟動 15625 ms 1178 ms 7629 ms 2001 ms
物聯網項目工作區,熱啟動 5186 ms 588 ms 1513 ms 517 ms

*,** Azure IoT Device Workbench需要的一些模塊與webpack不兼容,沒有被打包。

表一:Azure IoT Device Workbench在不同情況下的啟動時間

表一中所示的啟動時間是指擴展入口最開始到activate函數結束之間的時間:

// 開始啟動
import * as vscode from "vscode";
...
export async function activate(context: vscode.ExtensionContext) {
    ...
    // 啟動完成
}
...

通常啟動之前的時間要比VS Code正在運行的擴展頁面中顯示的啟動時間長。比如以熱啟動打開物聯網項目工作區的啟動時間在表中是517毫秒,但是VS Code正在運行的擴展頁面中大約是200毫秒。

典型的webpack解決方案中,啟動時間只有啟動模式有關,因為所有模塊都總是以同樣的方式被加載。當在Azure IoT Device Workbench中應用懶加載時,無論是否使用打包模塊,沒有工作區時啟動速度都遠快于打開物聯網工作區。當我們打開物聯網項目工作區時,大部分模塊都被引用,懶加載帶來的優勢不是很明顯,所以懶加載打包模塊和典型webpack解決方案有相近的啟動時間。

結論

在這篇文章中,提出了一種按需加載打包模塊的方法。一款叫做Azure IoT Device Workbench的繁重擴展被用來在多種情況下測試這個方法。并且它的啟動速度被提升了數十倍。在某些情況下,這個方法比典型的webpack方案帶來了更優異的性能提升。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109512.html

相關文章

  • 如何打造一個令人愉悅前端開發環境(一)

    摘要:我覺得這方面的原因是當時對和的依賴,導致大家對的興趣不弄,錯過了最佳時機,這個其實跟百度自己的的技術棧有很大關系。這個阮一峰對于前端構建的變化吐槽過,說新的構建工具就是的構建工具。 文章來源 最近幾年,前端發展越來越迅速,各種萌新加入了前端這個大家庭,大有趕IOS、超Android的趨勢呀!同時,萌新們提出了各種前端工作問題,除了最基礎的html、css、js三板斧之外,最讓人頭疼的應...

    Yangyang 評論0 收藏0
  • 如何打造一個令人愉悅前端開發環境(一)

    摘要:我覺得這方面的原因是當時對和的依賴,導致大家對的興趣不弄,錯過了最佳時機,這個其實跟百度自己的的技術棧有很大關系。這個阮一峰對于前端構建的變化吐槽過,說新的構建工具就是的構建工具。 文章來源 最近幾年,前端發展越來越迅速,各種萌新加入了前端這個大家庭,大有趕IOS、超Android的趨勢呀!同時,萌新們提出了各種前端工作問題,除了最基礎的html、css、js三板斧之外,最讓人頭疼的應...

    KavenFan 評論0 收藏0
  • Visual Studio Code 斷點調試 Vue

    摘要:個人還是更加習慣于斷點調試。這篇文章將介紹如何配置和來完成直接在斷點調試代碼并且在的調試窗口看到中相同的值。現在就可以在文件的代碼中打斷點進行調試了。 很多人習慣在 Chrome 的調試窗口中調試 Vue 代碼, 或者直接使用 console.log 來觀察變量值, 這是非常痛苦的一件事,需要同時打開至少 3 個窗體。個人還是更加習慣于斷點調試。這篇文章將介紹如何配置 Visual S...

    qpwoeiru96 評論0 收藏0
  • VS Code、ATOM這些開源文本編輯器代碼實現中有哪些奇技淫巧?

    摘要:知乎上也有相關的討論,開發的下一代編輯器莫非已經定義為上一代編輯器了嗎。 這篇是我在知乎的回答,原文在這里:justjavac: VS Code、ATOM這些開源文本編輯器的代碼實現中有哪些奇技淫巧? 研究 V8 比較多,也關注了一下 vscode 和 atom 的性能,每次 vscode、atom 的 change log 我都會看一遍。印象最深的是 vscode 1.14 的一次更...

    adie 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<