Skip to content

Commit c1a3c2f

Browse files
committed
Switch view to ESBuild
This switches the view code from Webpack to ESBuild to unify the build systems for the extension and view code. There are no changes in behavior, except that some features are now not supported (like dynamic require/import) and importing the `classnames` package fails. However, these were really easy to fix and don't hinder the further development of the view code, so I've just fixed those instances.
1 parent c210a7f commit c1a3c2f

File tree

8 files changed

+82
-145
lines changed

8 files changed

+82
-145
lines changed

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@ import {
88
copyWasmFiles,
99
} from "./typescript";
1010
import { compileTextMateGrammar } from "./textmate";
11-
import { compileView, watchView } from "./webpack";
1211
import { packageExtension } from "./package";
1312
import { injectAppInsightsKey } from "./appInsights";
13+
import {
14+
checkViewTypeScript,
15+
compileViewEsbuild,
16+
watchViewCheckTypeScript,
17+
watchViewEsbuild,
18+
} from "./view";
1419

1520
export const buildWithoutPackage = series(
1621
cleanOutput,
@@ -19,23 +24,30 @@ export const buildWithoutPackage = series(
1924
copyWasmFiles,
2025
checkTypeScript,
2126
compileTextMateGrammar,
22-
compileView,
27+
compileViewEsbuild,
28+
checkViewTypeScript,
2329
),
2430
);
2531

26-
export const watch = parallel(watchEsbuild, watchCheckTypeScript, watchView);
32+
export const watch = parallel(
33+
watchEsbuild,
34+
watchCheckTypeScript,
35+
watchViewEsbuild,
36+
watchViewCheckTypeScript,
37+
);
2738

2839
export {
2940
cleanOutput,
3041
compileTextMateGrammar,
3142
watchEsbuild,
3243
watchCheckTypeScript,
33-
watchView,
44+
watchViewEsbuild,
3445
compileEsbuild,
3546
copyWasmFiles,
3647
checkTypeScript,
3748
injectAppInsightsKey,
38-
compileView,
49+
compileViewEsbuild,
50+
checkViewTypeScript,
3951
};
4052
export default series(
4153
buildWithoutPackage,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import esbuild from "gulp-esbuild";
44
import { createProject, reporter } from "gulp-typescript";
55
import del from "del";
66

7-
function goodReporter(): reporter.Reporter {
7+
export function goodReporter(): reporter.Reporter {
88
return {
99
error: (error, typescript) => {
1010
if (error.tsFile) {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { dest, src, watch } from "gulp";
2+
import esbuild from "gulp-esbuild";
3+
import { createProject } from "gulp-typescript";
4+
import { goodReporter } from "./typescript";
5+
6+
const tsProject = createProject("src/view/tsconfig.json");
7+
8+
export function compileViewEsbuild() {
9+
return src("./src/view/webview.tsx")
10+
.pipe(
11+
esbuild({
12+
outfile: "webview.js",
13+
bundle: true,
14+
format: "iife",
15+
platform: "browser",
16+
target: "chrome114", // Electron 25, VS Code 1.85
17+
jsx: "automatic",
18+
sourcemap: "linked",
19+
sourceRoot: "..",
20+
loader: {
21+
".ttf": "file",
22+
},
23+
}),
24+
)
25+
.pipe(dest("out"));
26+
}
27+
28+
export function watchViewEsbuild() {
29+
watch("src/view/**/*.ts", compileViewEsbuild);
30+
}
31+
32+
export function checkViewTypeScript() {
33+
// This doesn't actually output the TypeScript files, it just
34+
// runs the TypeScript compiler and reports any errors.
35+
return tsProject.src().pipe(tsProject(goodReporter()));
36+
}
37+
38+
export function watchViewCheckTypeScript() {
39+
watch("src/view/**/*.ts", checkViewTypeScript);
40+
}

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

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

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

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

extensions/ql-vscode/src/view/common/icon/Codicon.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from "react";
22
import { styled } from "styled-components";
3-
import * as classNames from "classnames";
43

54
type Props = {
65
name: string;
@@ -18,7 +17,7 @@ export const Codicon = ({ name, label, className, slot }: Props) => (
1817
role="img"
1918
aria-label={label}
2019
title={label}
21-
className={classNames("codicon", `codicon-${name}`, className)}
20+
className={`codicon codicon-${name}${className ? ` ${className}` : ""}`}
2221
slot={slot}
2322
/>
2423
);

extensions/ql-vscode/src/view/common/icon/LoadingIcon.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from "react";
22
import { Codicon } from "./Codicon";
3-
import * as classNames from "classnames";
43

54
type Props = {
65
label?: string;
@@ -11,6 +10,6 @@ export const LoadingIcon = ({ label = "Loading...", className }: Props) => (
1110
<Codicon
1211
name="loading"
1312
label={label}
14-
className={classNames(className, "codicon-modifier-spin")}
13+
className={`${className ? `${className} ` : ""}codicon-modifier-spin`}
1514
/>
1615
);

extensions/ql-vscode/src/view/webview.tsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,27 @@ import { StrictMode } from "react";
33
import { createRoot } from "react-dom/client";
44
import { vscode } from "./vscode-api";
55

6+
import { registerUnhandledErrorListener } from "./common/errors";
67
import { WebviewDefinition } from "./webview-definition";
78

9+
import compareView from "./compare";
10+
import dataFlowPathsView from "./data-flow-paths";
11+
import methodModelingView from "./method-modeling";
12+
import modelEditorView from "./model-editor";
13+
import resultsView from "./results";
14+
import variantAnalysisView from "./variant-analysis";
15+
816
// Allow all views to use Codicons
917
import "@vscode/codicons/dist/codicon.css";
10-
import { registerUnhandledErrorListener } from "./common/errors";
18+
19+
const views: Record<string, WebviewDefinition> = {
20+
compare: compareView,
21+
"data-flow-paths": dataFlowPathsView,
22+
"method-modeling": methodModelingView,
23+
"model-editor": modelEditorView,
24+
results: resultsView,
25+
"variant-analysis": variantAnalysisView,
26+
};
1127

1228
const render = () => {
1329
registerUnhandledErrorListener();
@@ -25,10 +41,11 @@ const render = () => {
2541
return;
2642
}
2743

28-
// It's a lot harder to use dynamic imports since those don't import the CSS
29-
// and require a less strict CSP policy
30-
// eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-dynamic-require
31-
const view: WebviewDefinition = require(`./${viewName}/index.tsx`).default;
44+
const view: WebviewDefinition = views[viewName];
45+
if (!view) {
46+
console.error(`Could not find view with name "${viewName}"`);
47+
return;
48+
}
3249

3350
const root = createRoot(element);
3451
root.render(

0 commit comments

Comments
 (0)