使用 Webapck 優化 VS Code 外掛載入效能

jdneo發表於2018-12-31

Webpack 這一 JS 模組打包神器相信大家都不陌生了。由於 VS Code 外掛大部分也都是 JS/TS 程式碼 + 依賴庫的形式,因此也可以使用 Webpack 打包,優化效能。

VS Code 外掛的開發者們不妨嘗試一下 Webpack 為自己外掛所帶來的驚喜!

增加 Webpack 相關依賴庫

npm install --save-dev webpack webpack-cli ts-loader
複製程式碼

使用 ts-loader 是由於我的外掛是基於 TypeScript 編寫的。

新增 Webpack 配置檔案

//@ts-check

'use strict';

const path = require('path');

/**@type {import('webpack').Configuration}*/
const config = {
    // VS Code 外掛執行於 Node.js 上下文中
    // ? -> https://webpack.js.org/configuration/node/
    target: 'node',
    node: {
        __dirname: false,
        __filename: false,
    },
    // 外掛的執行入口。
    // ? -> https://webpack.js.org/configuration/entry-context/
    entry: './src/extension.ts',
    // 我們將打包後的檔案儲存於 'dist' 目錄下
    // ? -> https://webpack.js.org/configuration/output/
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'extension.js',
        libraryTarget: "commonjs2",
        devtoolModuleFilenameTemplate: "../[resource-path]",
    },
    externals: {
        // 'vscode'模組由 VS Code 執行時提供,可以將其排除避免打包檔案過大
        // ? -> https://webpack.js.org/configuration/externals/
        vscode: "commonjs vscode",
    },
    devtool: 'source-map',
    // 解析 TypeScript 和 JavaScript 檔案
    // ? -> https://github.com/TypeStrong/ts-loader
    resolve: {
        extensions: ['.ts', '.js'],
    },
    module: {
        rules: [{
            test: /\.ts$/,
            exclude: /node_modules/,
            use: [{
                loader: 'ts-loader',
            }]
        }]
    },
}
module.exports = config;
複製程式碼

由於我們會使用打包後的輸出檔案作為外掛的程式碼,因此務必要記得修改 package.json 中的外掛主程式入口,例如:"main": "./out/src/extension" 修改為 "main": "./dist/extension"

不要忘記將 dist 目錄新增到 .gitignore 中。

優化開發體驗

另外,我們可以更新開發外掛時所用的 Launch Configuration 來優化開發體驗。

更新 launch.json

launch.json 檔案存放了我們平時除錯外掛時的配置資訊:

{
    "version": "0.1.0",
    "configurations": [
        {
            "name": "Launch Extension",
            "type": "extensionHost",
            "request": "launch",
            "runtimeExecutable": "${execPath}",
            "args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
            "stopOnEntry": false,
            "sourceMaps": true,
            // 注意這裡需要使用 Webpack 的輸出檔案路徑。
            "outFiles": [ "${workspaceRoot}/dist/**/*.js" ],
            // 在 Launch 之前的前置任務,定義見下文。
            "preLaunchTask": "npm: watch"
        }
    ]
}
複製程式碼

定義 npm:watch 並建立 tasks.json

首先我們在 package.json 中定義 watch 任務:

"scripts:" {
    ...
    "watch": "webpack --mode development --watch --info-verbosity verbose"
    ...
}
複製程式碼

這裡我們讓 Webpack 以 watch 模式監聽我們對程式碼的修改,並實時地對程式碼進行打包,並讓其以 verbose 模式輸出更多的打包資訊。這是為什麼呢?因為我們可以利用這些輸出資訊讓 VS Code 知道打包已經完成了。

為了做到這一點,我們需要在 task.json 中建立一個監聽輸出的任務,這樣就可讓 VS Code 在 Webpack 完成打包後,自動啟動我們的外掛進行除錯:

{
    "version": "2.0.0",
    "tasks": [
        {
            // 定義 npm: watch
            "type": "npm",
            "script": "watch",
            "problemMatcher": {
                "owner": "typescript",
                "pattern":[
                    {
                        "regexp": "\\[tsl\\] ERROR",
                        "file": 1,
                        "location": 2,
                        "message": 3
                    }
                ],
                "background": {
                    "activeOnStart": true,
                    // 通過對 Webpack 的輸出內容進行匹配,得知編譯是否完成
                    "beginsPattern": "Compilation \\w+ starting…",
                    "endsPattern": "Compilation\\s+finished"
                }
            },
            "isBackground": true,
            "presentation": {
                "reveal": "never"
            },
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
複製程式碼

更新 vscode:prepublish 指令碼

vscode:prepublish 是定義在 package.json 中的一段指令碼,這段指令碼會在生成 VS Code 外掛安裝包之前執行:

"scripts:" {
    ...
    // 使用 VSCE 生成外掛時的前置指令碼,讓 Webpack 打包
    "vscode:prepublish": "webpack --mode production"
    ...
}
複製程式碼

點此檢視更多關於 vscode:prepublish 的介紹。

更新 .vscodeignore

類似於 .gitignore, .vscodeignore 列出了在生成 VS Code 外掛安裝包時,所有不需要放入安裝包中的檔案及目錄,這裡我們可以增加下列幾項:

  • dist/**/*.map.map 檔案僅在本地除錯時需要用到。
  • webpack.config.js:Webpack 的配置檔案也不需要放入安裝包當中。
  • node_modules:由於使用 Webpack 對依賴庫進行了打包,因此我們不再需要將 node_modules 放入安裝包當中了,這將極大縮小安裝包的大小。

效果

至此我們就已經大功告成了,那麼使用了 Webpack 究竟能對 VS Code 外掛的效能產生多大的影響呢?我們以 Java Test Runner 為例:

安裝包大小 載入時間
未使用 Webpack 9.8M ~2000ms
使用 Webpack 1.9M ~200ms

在使用 Webpack 後,安裝包的大小由原先的 9.8M 縮減到了 1.9M (在這其中還包含了一些 .jar 檔案,真正的 extension.js 在解壓後,僅為 900KB 左右)。

效能上,我們利用 VS Code 自帶的效能檢測工具檢視外掛載入所用的時間,在我的電腦上,Java Test Runner 的載入時間由原先的 2000ms 縮短到了 200ms 左右,前後相差近 10 倍,可以說效果非常顯著了。

如果你也是 VS Code 外掛的開發者,那就不要猶豫,讓 Webpack 帶你的外掛起飛吧!

最後

VS Code Team 官方提供了使用 Webpack 的樣例程式碼,感興趣的童靴可以直接檢視。

最後的最後

打一波小小的廣告。我們 Team 目前致力於一系列 VS Code 中的 Java 開發外掛,所有專案均為開源專案,歡迎有興趣的童鞋下載試用:

可以通過提 Issue?的方式給我們提出修改建議,喜歡的話也可以打 ⭐️支援哦!

相關文章