@@ -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] ;
4850const 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
6769const 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}
280273async 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 ) ;
0 commit comments