Skip to content

Commit 1842d76

Browse files
authored
fix: Use ESM internally but bundle the extension as CommonJS. (#247)
1 parent 722b206 commit 1842d76

36 files changed

+218
-457
lines changed

build/add-js-extensions.mjs

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

build/esbuild/build.ts

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -43,25 +43,27 @@ const deskTopNodeModulesToExternalize = [
4343
// Lazy loaded modules.
4444
'vscode-languageclient/node',
4545
'@jupyterlab/nbformat',
46-
'vscode-jsonrpc'
46+
'vscode-jsonrpc',
47+
// vega-lite uses top-level await (through vega-canvas), must be external
48+
'vega-lite'
4749
];
4850
const commonExternals = [
4951
'log4js',
5052
'vscode',
5153
'commonjs',
52-
'module', // Node.js builtin module for createRequire (ESM support)
53-
'node:os', // Node.js builtin (use node: prefix for ESM)
54-
'ansi-regex', // Used by regexp utils
55-
'node:crypto',
56-
'node:fs/promises',
57-
'node:path',
5854
'vscode-jsonrpc', // Used by a few modules, might as well pull this out, instead of duplicating it in separate bundles.
5955
// Ignore telemetry specific packages that are not required.
6056
'applicationinsights-native-metrics',
6157
'@opentelemetry/tracing',
6258
'@azure/opentelemetry-instrumentation-azure-sdk',
6359
'@opentelemetry/instrumentation',
64-
'@azure/functions-core'
60+
'@azure/functions-core',
61+
// Node.js builtins (with node: prefix)
62+
'node:crypto',
63+
'node:fs/promises',
64+
'node:os',
65+
'node:path',
66+
'ansi-regex' // Used by regexp utils
6567
];
6668
// Create separate copies to avoid shared-state mutations
6769
const webExternals = [...commonExternals];
@@ -237,20 +239,23 @@ function createConfig(
237239
}
238240
const isPreRelease = isDevbuild || process.env.IS_PRE_RELEASE_VERSION_OF_JUPYTER_EXTENSION === 'true';
239241
const releaseVersionScriptFile = isPreRelease ? 'release.pre-release.js' : 'release.stable.js';
240-
const alias = {
242+
const alias: Record<string, string> = {
241243
moment: path.join(extensionFolder, 'build', 'webpack', 'moment.js'),
242244
'vscode-jupyter-release-version': path.join(__dirname, releaseVersionScriptFile)
243245
};
246+
// Use ESM entry for jsonc-parser to avoid UMD internal require() issues when bundling
244247
if (target === 'desktop') {
245248
alias['jsonc-parser'] = path.join(extensionFolder, 'node_modules', 'jsonc-parser', 'lib', 'esm', 'main.js');
246249
}
250+
// Desktop builds use CommonJS for VS Code/Cursor compatibility
251+
// Web builds use ESM for browser compatibility
247252
const config: SameShape<BuildOptions, BuildOptions> = {
248253
entryPoints: [source],
249254
outfile,
250255
bundle: true,
251256
external,
252257
alias,
253-
format: 'esm',
258+
format: target === 'desktop' ? 'cjs' : 'esm',
254259
metafile: isDevbuild && !watch,
255260
define,
256261
target: target === 'desktop' ? 'node18' : 'es2018',
@@ -263,18 +268,6 @@ function createConfig(
263268
loader: target === 'desktop' ? {} : loader
264269
};
265270

266-
// Add createRequire banner for desktop ESM builds to support external CommonJS modules
267-
if (target === 'desktop') {
268-
config.banner = {
269-
js: `import { createRequire as __createRequire } from 'module';
270-
import { fileURLToPath as __fileURLToPath } from 'url';
271-
import { dirname as __getDirname } from 'path';
272-
const require = __createRequire(import.meta.url);
273-
const __filename = __fileURLToPath(import.meta.url);
274-
const __dirname = __getDirname(__filename);`
275-
};
276-
}
277-
278271
return config;
279272
}
280273
async function build(source: string, outfile: string, options: { watch: boolean; target: 'desktop' | 'web' }) {
@@ -451,18 +444,10 @@ async function buildAll() {
451444
{ target: 'desktop', watch: isWatchMode }
452445
)
453446
);
454-
builders.push(
455-
build(
456-
path.join(extensionFolder, 'src', 'extension.node.proxy.ts'),
457-
path.join(extensionFolder, 'dist', 'extension.node.proxy.js'),
458-
// This file almost never ever changes, hence no need to watch this.
459-
{ target: 'desktop', watch: false }
460-
)
461-
);
462447
builders.push(
463448
...deskTopNodeModulesToExternalize
464-
// zeromq will be manually bundled.
465-
.filter((module) => !['zeromq', 'zeromqold', 'vscode-jsonrpc'].includes(module))
449+
// zeromq will be manually bundled, vega-lite uses top-level await (can't be CJS bundled)
450+
.filter((module) => !['zeromq', 'zeromqold', 'vscode-jsonrpc', 'vega-lite'].includes(module))
466451

467452
.map(async (module) => {
468453
const fullPath = require.resolve(module);

build/fix-directory-imports.mjs

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

0 commit comments

Comments
 (0)