Skip to content

Commit f13f0b3

Browse files
committed
Bundle extension files using ESBuild
This bundles the extension files using esbuild, as recommended by VSCode. This reduces the size of the extension from 34MB to less than 5MB. Gulp will still run TypeScript to check types, but will not use the TypeScript compiler output in the bundle. Tests are now run separately, outside of Gulp, so their data doesn't need to be copied anymore. See: https://code.visualstudio.com/api/working-with-extensions/bundling-extension
1 parent 9cf5088 commit f13f0b3

16 files changed

Lines changed: 844 additions & 75 deletions

extensions/ql-vscode/.vscodeignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ gulpfile.js/**
1414
tsconfig.json
1515
.prettierrc
1616
vsc-extension-quickstart.md
17+
node_modules/**

extensions/ql-vscode/gulpfile.ts/appInsights.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export function injectAppInsightsKey() {
1313
}
1414

1515
// replace the key
16-
return src(["out/telemetry.js"])
16+
return src(["out/extension.js"])
1717
.pipe(replace(/REPLACE-APP-INSIGHTS-KEY/, process.env.APP_INSIGHTS_KEY))
1818
.pipe(dest("out/"));
1919
}

extensions/ql-vscode/gulpfile.ts/deploy.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,27 @@ const packageFiles = [
2222
"language-configuration.json",
2323
"snippets.json",
2424
"media",
25-
"node_modules",
2625
"out",
2726
"workspace-databases-schema.json",
2827
];
2928

29+
async function copyDirectory(
30+
sourcePath: string,
31+
destPath: string,
32+
): Promise<void> {
33+
console.log(`copying ${sourcePath} to ${destPath}`);
34+
await copy(sourcePath, destPath);
35+
}
36+
3037
async function copyPackage(
3138
sourcePath: string,
3239
destPath: string,
3340
): Promise<void> {
34-
for (const file of packageFiles) {
35-
console.log(
36-
`copying ${resolve(sourcePath, file)} to ${resolve(destPath, file)}`,
37-
);
38-
await copy(resolve(sourcePath, file), resolve(destPath, file));
39-
}
41+
await Promise.all(
42+
packageFiles.map((file) =>
43+
copyDirectory(resolve(sourcePath, file), resolve(destPath, file)),
44+
),
45+
);
4046
}
4147

4248
export async function deployPackage(
@@ -88,6 +94,12 @@ export async function deployPackage(
8894
);
8995
await copyPackage(sourcePath, distPath);
9096

97+
// This is necessary for vsce to know the dependencies
98+
await copyDirectory(
99+
resolve(sourcePath, "node_modules"),
100+
resolve(distPath, "node_modules"),
101+
);
102+
91103
return {
92104
distPath,
93105
name: packageJson.name,

extensions/ql-vscode/gulpfile.ts/index.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
1-
import { series, parallel } from "gulp";
2-
import { compileTypeScript, watchTypeScript, cleanOutput } from "./typescript";
1+
import { parallel, series } from "gulp";
2+
import {
3+
compileEsbuild,
4+
watchEsbuild,
5+
checkTypeScript,
6+
watchCheckTypeScript,
7+
cleanOutput,
8+
} from "./typescript";
39
import { compileTextMateGrammar } from "./textmate";
4-
import { copyTestData, watchTestData } from "./tests";
510
import { compileView, watchView } from "./webpack";
611
import { packageExtension } from "./package";
712
import { injectAppInsightsKey } from "./appInsights";
813

914
export const buildWithoutPackage = series(
1015
cleanOutput,
1116
parallel(
12-
compileTypeScript,
17+
compileEsbuild,
18+
checkTypeScript,
1319
compileTextMateGrammar,
1420
compileView,
15-
copyTestData,
1621
),
1722
);
1823

24+
export const watch = parallel(watchEsbuild, watchCheckTypeScript, watchView);
25+
1926
export {
2027
cleanOutput,
2128
compileTextMateGrammar,
22-
watchTypeScript,
29+
watchEsbuild,
30+
watchCheckTypeScript,
2331
watchView,
24-
compileTypeScript,
25-
copyTestData,
26-
watchTestData,
32+
compileEsbuild,
33+
checkTypeScript,
2734
injectAppInsightsKey,
2835
compileView,
2936
};

extensions/ql-vscode/gulpfile.ts/package.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { deployPackage } from "./deploy";
33
import { spawn } from "child-process-promise";
44

55
export async function packageExtension(): Promise<void> {
6-
const deployedPackage = await deployPackage(resolve("package.json"));
6+
const deployedPackage = await deployPackage(
7+
resolve(__dirname, "../package.json"),
8+
);
79
console.log(
810
`Packaging extension '${deployedPackage.name}@${deployedPackage.version}'...`,
911
);
@@ -16,7 +18,7 @@ export async function packageExtension(): Promise<void> {
1618
`${deployedPackage.name}-${deployedPackage.version}.vsix`,
1719
),
1820
];
19-
const proc = spawn("./node_modules/.bin/vsce", args, {
21+
const proc = spawn(resolve(__dirname, "../node_modules/.bin/vsce"), args, {
2022
cwd: deployedPackage.distPath,
2123
});
2224
proc.childProcess.stdout!.on("data", (data) => {

extensions/ql-vscode/gulpfile.ts/tests.ts

Lines changed: 0 additions & 21 deletions
This file was deleted.

extensions/ql-vscode/gulpfile.ts/textmate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { src, dest } from "gulp";
1+
import { dest, src } from "gulp";
22
import { load } from "js-yaml";
33
import { obj } from "through2";
4-
import * as PluginError from "plugin-error";
4+
import PluginError from "plugin-error";
55
import * as Vinyl from "vinyl";
66

77
/**

extensions/ql-vscode/gulpfile.ts/typescript.ts

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { gray, red } from "ansi-colors";
2-
import { dest, watch } from "gulp";
3-
import { init, write } from "gulp-sourcemaps";
4-
import * as ts from "gulp-typescript";
5-
import * as del from "del";
2+
import { dest, src, watch } from "gulp";
3+
import esbuild from "gulp-esbuild";
4+
import ts from "gulp-typescript";
5+
import del from "del";
66

77
function goodReporter(): ts.reporter.Reporter {
88
return {
@@ -35,20 +35,35 @@ export function cleanOutput() {
3535
: Promise.resolve();
3636
}
3737

38-
export function compileTypeScript() {
39-
return tsProject
40-
.src()
41-
.pipe(init())
42-
.pipe(tsProject(goodReporter()))
38+
export function compileEsbuild() {
39+
return src("./src/extension.ts")
4340
.pipe(
44-
write(".", {
45-
includeContent: false,
46-
sourceRoot: ".",
41+
esbuild({
42+
outfile: "extension.js",
43+
bundle: true,
44+
external: ["vscode", "fsevents"],
45+
format: "cjs",
46+
platform: "node",
47+
target: "es2020",
48+
sourcemap: "linked",
49+
loader: {
50+
".node": "copy",
51+
},
4752
}),
4853
)
4954
.pipe(dest("out"));
5055
}
5156

52-
export function watchTypeScript() {
53-
watch("src/**/*.ts", compileTypeScript);
57+
export function watchEsbuild() {
58+
watch("src/**/*.ts", compileEsbuild);
59+
}
60+
61+
export function checkTypeScript() {
62+
// This doesn't actually output the TypeScript files, it just
63+
// runs the TypeScript compiler and reports any errors.
64+
return tsProject.src().pipe(tsProject(goodReporter()));
65+
}
66+
67+
export function watchCheckTypeScript() {
68+
watch("src/**/*.ts", checkTypeScript);
5469
}

extensions/ql-vscode/gulpfile.ts/webpack.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { resolve } from "path";
22
import * as webpack from "webpack";
3-
import * as MiniCssExtractPlugin from "mini-css-extract-plugin";
3+
import MiniCssExtractPlugin from "mini-css-extract-plugin";
44

55
export const config: webpack.Configuration = {
66
mode: "development",

extensions/ql-vscode/gulpfile.ts/webpack.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as webpack from "webpack";
1+
import webpack from "webpack";
22
import { config } from "./webpack.config";
33

44
export function compileView(cb: (err?: Error) => void) {

0 commit comments

Comments
 (0)