Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy webServer from Typescript to VS Code #165771

Merged
merged 10 commits into from
Nov 14, 2022
Merged

Conversation

sandersn
Copy link
Member

@sandersn sandersn commented Nov 8, 2022

Previously, Typescript packaged the host/session combo needed for running vscode on the web into tsserver.js. tsserver.js would only execute normally if process was defined globally. Otherwise it would assume that it was running in a webworker and listen for a startup message. However, after Typescript's module conversion, building tsserver is much simpler if it remains a pure node executable (@jakebailey can explain). The code for the web is a completely separate 500-line chunk that was appended after the bulk of tsserver, so it's easily separable.

This change copies webServer to the typescript language extension and switches vscode to package tsserverlibrary.js for the web instead of tsserver.js. We'll follow it up with a change that removes webServer.ts from tsserver.js in Typescript 5.0, which will slim down our build considerably. It also prepares the way for my update of the web host to use vscode-wasm as a virtual filesystem. It's structured exactly the same way--so it's likely that I'll eventually put the code from my update into the new webServer.ts file from this PR.

Note: Reads better with whitespace ignored.

Some notes:

  1. postinstall.mjs now retains tsserverlibrary.js. But tsserver.js is still needed for building for the desktop. @jakebailey will 5.0 remove some of the cost of this duplication? (I'm not actually sure of the cost either)
  2. I put webServer.ts in extensions/typescript-language-features/web/webServer.ts and it builds with a separate tsconfig.
  3. I switched tsserver.web.js over to use normal webpack. This required touching build infrastructure to support multiple entries in one file.
  4. I put all the code into one file without namespaces, which made it easier to manually bundle. I'll probably split it into more than one file at some point, but the file breaks in the Typescript repo didn't make much sense.
  5. I refer to lots of internals, which is not great for the long term. We should consider whether some of them should be made public or packaged for public consumption.
    5a. getLogLevel is only available on tsserver.js, so I copied its content over. I copied a few trivial things like const noop = () => {}.
  6. I moved the existing code over mostly unchanged, except to add ts.server. prefixes where needed. Vscode's build settings are stricter than typescript's so I had change a couple of places because of that.

Not working.
Also not correctly formatted, I'll do that later.
It works now
@sandersn
Copy link
Member Author

sandersn commented Nov 8, 2022

@mjbvz @jakebailey I think you are the interested parties here.

@mjbvz mjbvz added this to the November 2022 milestone Nov 8, 2022
@jakebailey
Copy link
Member

This is the related TS issue for the package size savings: microsoft/TypeScript#51440

Copy link
Collaborator

@mjbvz mjbvz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for looking into this. Added a few comments but excited to see this happening!

And prepare for getting rid of dynamicImportCompat.js hack
Instead of using CopyPlugin.

1. Shipping multiple entrypoints in a single file required fixes to
build code.
2. There are a couple of warnings from `require` calls in
tsserverlibrary.js. Those are not relevant since they're in non-web
code, but I haven't figured how to turn them off; they are fully dynamic
so `externals` didn't work.
const config = typeof configOrFn === 'function' ? configOrFn({}, {}) : configOrFn;
if (outputRoot) {
config.output.path = path.join(outputRoot, path.relative(path.dirname(configPath), config.output.path));
}
webpackConfigs.push(config);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the webpack configs. None of them pass functions, which is good, because this code double-pushed function configs.
Nothing sets outputRoot that I could see, so the if (outputRoot) code is just-in-case. I left it because I don't know what it's supposed to do.

// packaging depends on that and this must always be like it
filename: '[name].js',
path: path.join(__dirname, 'dist', 'browser'),
libraryTarget: undefined,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withBrowserDefaults sets libraryTarget: commonjs, which is not correct for tsserver.web.js. I don't know if it's correct for any callers, but there are lots of them so I didn't change it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's correct for all callers because they should all be extensions, which even on web are CJS (they are executed in a funky eval environment).

transform: async (content) => {
const dynamicImportCompatPath = path.join(__dirname, '..', 'node_modules', 'typescript', 'lib', 'dynamicImportCompat.js');
const prefix = fs.existsSync(dynamicImportCompatPath) ? fs.readFileSync(dynamicImportCompatPath) : undefined;
const output = await Terser.minify(content.toString());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withBrowserDefaults doesn't minify because it sets mode: none, but there's a comment that says mode: production will minify. So I didn't include a minify entry in tsserver.web.js' config.

@sandersn
Copy link
Member Author

sandersn commented Nov 11, 2022

@mjbvz I addressed your comments, and switched away from CopyPlugin in webpack, so can you take a look at the new commits and the follow-up comments I posted with them?

@mjbvz mjbvz merged commit cb43019 into microsoft:main Nov 14, 2022
@mjbvz
Copy link
Collaborator

mjbvz commented Nov 14, 2022

Thank you @sandersn! Let's merge this and test it out further in the next insiders

@sandersn sandersn deleted the tsserver-webhost branch November 14, 2022 22:40
hediet added a commit that referenced this pull request Nov 15, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Dec 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants