Skip to content

Commit 62ece16

Browse files
feat(language-server): Dynamically download TypeScript from CDN on Web (#71)
1 parent a70e8f4 commit 62ece16

File tree

6 files changed

+50
-20
lines changed

6 files changed

+50
-20
lines changed

.npmrc

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

packages/language-server/src/browser/index.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,25 @@ export function startLanguageServer(connection: vscode.Connection, ...plugins: L
2828
return { dispose: () => clearTimeout(handle) };
2929
},
3030
},
31-
loadTypescript() {
32-
return require('typescript'); // force bundle because not support load by user config in web
31+
async loadTypeScript(options) {
32+
const tsdkUri = options.typescript?.tsdkUrl;
33+
if (!tsdkUri) {
34+
return;
35+
}
36+
const _module = globalThis.module;
37+
globalThis.module = { exports: {} } as typeof _module;
38+
await import(`${tsdkUri}/lib/typescript.js`);
39+
const ts = globalThis.module.exports;
40+
globalThis.module = _module;
41+
return ts as typeof import('typescript/lib/tsserverlibrary');
3342
},
34-
async loadTypescriptLocalized(tsdk, locale) {
43+
async loadTypeScriptLocalized(options, locale) {
44+
const tsdkUri = options.typescript?.tsdkUrl;
45+
if (!tsdkUri) {
46+
return;
47+
}
3548
try {
36-
const uri = fileNameToUri(`${tsdk}/${locale}/diagnosticMessages.generated.json`);
49+
const uri = fileNameToUri(`${tsdkUri}/${locale}/diagnosticMessages.generated.json`);
3750
const json = await httpSchemaRequestHandler(uri);
3851
if (json) {
3952
return JSON.parse(json);

packages/language-server/src/common/server.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ export function startCommonLanguageServer(connection: vscode.Connection, _plugin
3131
let plugins: ReturnType<LanguageServerPlugin>[];
3232
let documents: ReturnType<typeof createDocuments>;
3333
let context: ServerContext;
34+
let ts: typeof import('typescript/lib/tsserverlibrary') | undefined;
35+
let tsLocalized: {} | undefined;
36+
let cancelTokenHost: ReturnType<typeof createCancellationTokenHost>;
3437

3538
const didChangeWatchedFilesCallbacks = new Set<vscode.NotificationHandler<vscode.DidChangeWatchedFilesParams>>();
3639

@@ -59,9 +62,12 @@ export function startCommonLanguageServer(connection: vscode.Connection, _plugin
5962
},
6063
},
6164
};
62-
plugins = context.server.plugins.map(plugin => plugin(options, {
63-
typescript: options.typescript ? context.server.runtimeEnv.loadTypescript(options.typescript.tsdk) : undefined
64-
}));
65+
ts = await context.server.runtimeEnv.loadTypeScript(options);
66+
tsLocalized = initParams.locale
67+
? await context.server.runtimeEnv.loadTypeScriptLocalized(options, initParams.locale)
68+
: undefined;
69+
cancelTokenHost = createCancellationTokenHost(options.cancellationPipeName);
70+
plugins = context.server.plugins.map(plugin => plugin(options, { typescript: ts }));
6571
documents = createDocuments(context.server.runtimeEnv, connection);
6672

6773
if (options.l10n) {
@@ -232,10 +238,6 @@ export function startCommonLanguageServer(connection: vscode.Connection, _plugin
232238

233239
async function createLanguageServiceHost() {
234240

235-
const ts = options.typescript ? context.server.runtimeEnv.loadTypescript(options.typescript.tsdk) : undefined;
236-
const tsLocalized = options.typescript && initParams.locale ? await context.server.runtimeEnv.loadTypescriptLocalized(options.typescript.tsdk, initParams.locale) : undefined;
237-
const cancelTokenHost = createCancellationTokenHost(options.cancellationPipeName);
238-
239241
workspaces = createWorkspaces({
240242
...context,
241243
workspaces: {

packages/language-server/src/node/index.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,11 @@ export function startLanguageServer(connection: vscode.Connection, ...plugins: L
9292
return { dispose: () => clearImmediate(handle) };
9393
},
9494
},
95-
loadTypescript(tsdk) {
95+
loadTypeScript(options) {
96+
const tsdk = options.typescript?.tsdk;
97+
if (!tsdk) {
98+
return;
99+
}
96100
for (const name of ['./typescript.js', './tsserverlibrary.js']) {
97101
try {
98102
return require(require.resolve(name, { paths: [tsdk] }));
@@ -108,7 +112,11 @@ export function startLanguageServer(connection: vscode.Connection, ...plugins: L
108112

109113
throw new Error(`Can't find typescript.js or tsserverlibrary.js in ${tsdk}`);
110114
},
111-
async loadTypescriptLocalized(tsdk, locale) {
115+
async loadTypeScriptLocalized(options, locale) {
116+
const tsdk = options.typescript?.tsdk;
117+
if (!tsdk) {
118+
return;
119+
}
112120
try {
113121
const path = require.resolve(`./${locale}/diagnosticMessages.generated.json`, { paths: [tsdk] });
114122
return require(path);

packages/language-server/src/types.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ export interface Timer {
1414
export interface RuntimeEnvironment {
1515
uriToFileName(uri: string): string;
1616
fileNameToUri(fileName: string): string;
17-
loadTypescript(tsdk: string): typeof import('typescript/lib/tsserverlibrary');
18-
loadTypescriptLocalized(tsdk: string, locale: string): Promise<{} | undefined>;
17+
loadTypeScript(options: InitializationOptions): Promise<typeof import('typescript/lib/tsserverlibrary') | undefined>;
18+
loadTypeScriptLocalized(options: InitializationOptions, locale: string): Promise<{} | undefined>;
1919
fs: FileSystem;
2020
// https://github.com/microsoft/vscode/blob/7927075f89db213bc6e2182fa684d514d69e2359/extensions/html-language-features/server/src/htmlServer.ts#L53-L56
2121
timer: Timer;
@@ -53,9 +53,16 @@ export enum DiagnosticModel {
5353
export interface InitializationOptions {
5454
typescript?: {
5555
/**
56-
* Absolute path to node_modules/typescript/lib
56+
* Absolute path to node_modules/typescript/lib, available for node
5757
*/
5858
tsdk: string;
59+
/**
60+
* URI to node_modules/typescript/lib, available for web
61+
* @example "https://cdn.jsdelivr.net/npm/typescript"
62+
* @example "https://cdn.jsdelivr.net/npm/typescript@latest"
63+
* @example "https://cdn.jsdelivr.net/npm/typescript@5.0.0"
64+
*/
65+
tsdkUrl: string;
5966
};
6067
l10n?: {
6168
location: string; // uri

pnpm-lock.yaml

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)