From c7caef00ea8c33e5ef5309708b6bc479987d37ed Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 27 Sep 2024 08:05:06 +0200 Subject: [PATCH] esm - make `optimize.ts` ESM only --- build/gulpfile.editor.js | 7 +-- build/gulpfile.reh.js | 30 ++++-------- build/gulpfile.vscode.js | 30 ++++-------- build/gulpfile.vscode.web.js | 8 +--- build/lib/optimize.js | 29 ++++-------- build/lib/optimize.ts | 90 ++++++++---------------------------- build/lib/util.js | 75 ------------------------------ build/lib/util.ts | 90 ------------------------------------ 8 files changed, 48 insertions(+), 311 deletions(-) diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js index 9bd00fec66d..0a6231dbfb0 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.js @@ -92,13 +92,10 @@ const compileEditorAMDTask = task.define('compile-editor-amd', compilation.compi const optimizeEditorAMDTask = task.define('optimize-editor-amd', optimize.optimizeTask( { out: 'out-editor', - amd: { + esm: { src: 'out-editor-build', entryPoints: editorEntryPoints, - resources: editorResources, - header: BUNDLED_FILE_HEADER, - bundleInfo: true, - languages + resources: editorResources } } )); diff --git a/build/gulpfile.reh.js b/build/gulpfile.reh.js index fba7d43ec64..de6d7b4c2ae 100644 --- a/build/gulpfile.reh.js +++ b/build/gulpfile.reh.js @@ -148,10 +148,10 @@ const serverWithWebEntryPoints = [ ...webEntryPoints, ].flat(); -const commonJSEntryPoints = [ +const bootstrapEntryPoints = [ 'out-build/server-main.js', 'out-build/server-cli.js', - 'out-build/bootstrap-fork.js', + 'out-build/bootstrap-fork.js' ]; function getNodeVersion() { @@ -436,7 +436,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa } result = inlineMeta(result, { - targetPaths: commonJSEntryPoints, + targetPaths: bootstrapEntryPoints, packageJsonFn: () => packageJsonContents, productJsonFn: () => productJsonContents }); @@ -460,28 +460,14 @@ function tweakProductForServerWeb(product) { optimize.optimizeTask( { out: `out-vscode-${type}`, - amd: { + esm: { src: 'out-build', - entryPoints: (type === 'reh' ? serverEntryPoints : serverWithWebEntryPoints).flat(), - otherSources: [], + entryPoints: [ + ...(type === 'reh' ? serverEntryPoints : serverWithWebEntryPoints), + ...bootstrapEntryPoints + ], resources: type === 'reh' ? serverResources : serverWithWebResources, - inlineAmdImages: true, - bundleInfo: undefined, fileContentMapper: createVSCodeWebFileContentMapper('.build/extensions', type === 'reh-web' ? tweakProductForServerWeb(product) : product) - }, - commonJS: { - src: 'out-build', - entryPoints: commonJSEntryPoints, - platform: 'node', - external: [ - 'minimist', - // We cannot inline `product.json` from here because - // it is being changed during build time at a later - // point in time (such as `checksums`) - // We have a manual step to inline these later. - '../product.json', - '../package.json' - ] } } ) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index f281970a453..9cbbc377ca2 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -126,7 +126,7 @@ const windowBootstrapFiles = [ 'out-build/bootstrap-window.js' ]; -const commonJSEntryPoints = [ +const bootstrapEntryPoints = [ 'out-build/main.js', 'out-build/cli.js', 'out-build/bootstrap-fork.js' @@ -141,27 +141,13 @@ const optimizeVSCodeTask = task.define('optimize-vscode', task.series( optimize.optimizeTask( { out: 'out-vscode', - amd: { + esm: { src: 'out-build', - entryPoints: vscodeEntryPoints, - resources: vscodeResources, - bundleInfo: undefined - }, - commonJS: { - src: 'out-build', - entryPoints: commonJSEntryPoints, - platform: 'node', - external: [ - 'electron', - 'minimist', - 'original-fs', - // We cannot inline `product.json` from here because - // it is being changed during build time at a later - // point in time (such as `checksums`) - // We have a manual step to inline these later. - '../product.json', - '../package.json', - ] + entryPoints: [ + ...vscodeEntryPoints, + ...bootstrapEntryPoints + ], + resources: vscodeResources }, manual: [ { src: [...windowBootstrapFiles, 'out-build/vs/code/electron-sandbox/workbench/workbench.js'], out: 'vs/code/electron-sandbox/workbench/workbench.js' }, @@ -444,7 +430,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op } result = inlineMeta(result, { - targetPaths: commonJSEntryPoints, + targetPaths: bootstrapEntryPoints, packageJsonFn: () => packageJsonContents, productJsonFn: () => productJsonContents }); diff --git a/build/gulpfile.vscode.web.js b/build/gulpfile.vscode.web.js index 3617fa37faa..ce65c7e028b 100644 --- a/build/gulpfile.vscode.web.js +++ b/build/gulpfile.vscode.web.js @@ -164,14 +164,10 @@ const optimizeVSCodeWebTask = task.define('optimize-vscode-web', task.series( optimize.optimizeTask( { out: 'out-vscode-web', - amd: { + esm: { src: 'out-build', - entryPoints: vscodeWebEntryPoints.flat(), - otherSources: [], + entryPoints: vscodeWebEntryPoints, resources: vscodeWebResources, - externalLoaderInfo: util.createExternalLoaderConfig(product.webEndpointUrl, commit, quality), - inlineAmdImages: true, - bundleInfo: undefined, fileContentMapper: createVSCodeWebFileContentMapper('.build/web/extensions', product) } } diff --git a/build/lib/optimize.js b/build/lib/optimize.js index 4fabac42716..7beeac2c6bf 100644 --- a/build/lib/optimize.js +++ b/build/lib/optimize.js @@ -15,23 +15,19 @@ const fs = require("fs"); const pump = require("pump"); const VinylFile = require("vinyl"); const bundle = require("./bundle"); -const i18n_1 = require("./i18n"); const postcss_1 = require("./postcss"); const esbuild = require("esbuild"); const sourcemaps = require("gulp-sourcemaps"); const REPO_ROOT_PATH = path.join(__dirname, '../..'); -const DEFAULT_FILE_HEADER = [ - '/*!--------------------------------------------------------', - ' * Copyright (C) Microsoft Corporation. All rights reserved.', - ' *--------------------------------------------------------*/' -].join('\n'); -function optimizeESMTask(opts, cjsOpts) { +function optimizeESMTask(opts) { const resourcesStream = es.through(); // this stream will contain the resources const bundlesStream = es.through(); // this stream will contain the bundled files - const entryPoints = opts.entryPoints; - if (cjsOpts) { - cjsOpts.entryPoints.forEach(entryPoint => entryPoints.push({ name: path.parse(entryPoint).name })); - } + const entryPoints = opts.entryPoints.map(entryPoint => { + if (typeof entryPoint === 'string') { + return { name: path.parse(entryPoint).name }; + } + return entryPoint; + }); const allMentionedModules = new Set(); for (const entryPoint of entryPoints) { allMentionedModules.add(entryPoint.name); @@ -133,7 +129,7 @@ function optimizeESMTask(opts, cjsOpts) { // bundle output (JS, CSS, SVG...) es.readArray(output.files).pipe(bundlesStream); // forward all resources - gulp.src(opts.resources, { base: `${opts.src}`, allowEmpty: true }).pipe(resourcesStream); + gulp.src(opts.resources ?? [], { base: `${opts.src}`, allowEmpty: true }).pipe(resourcesStream); }); const result = es.merge(bundlesStream, resourcesStream); return result @@ -141,12 +137,7 @@ function optimizeESMTask(opts, cjsOpts) { sourceRoot: undefined, addComment: true, includeContent: true - })) - .pipe(opts.languages && opts.languages.length ? (0, i18n_1.processNlsFiles)({ - out: opts.src, - fileHeader: opts.header || DEFAULT_FILE_HEADER, - languages: opts.languages - }) : es.through()); + })); } function optimizeManualTask(options) { const concatenations = options.map(opt => { @@ -159,7 +150,7 @@ function optimizeManualTask(options) { function optimizeTask(opts) { return function () { const optimizers = []; - optimizers.push(optimizeESMTask(opts.amd, opts.commonJS)); + optimizers.push(optimizeESMTask(opts.esm)); if (opts.manual) { optimizers.push(optimizeManualTask(opts.manual)); } diff --git a/build/lib/optimize.ts b/build/lib/optimize.ts index 2721f020012..8da31db05dc 100644 --- a/build/lib/optimize.ts +++ b/build/lib/optimize.ts @@ -12,47 +12,25 @@ import * as fs from 'fs'; import * as pump from 'pump'; import * as VinylFile from 'vinyl'; import * as bundle from './bundle'; -import { Language, processNlsFiles } from './i18n'; -import * as util from './util'; import { gulpPostcss } from './postcss'; import * as esbuild from 'esbuild'; import * as sourcemaps from 'gulp-sourcemaps'; const REPO_ROOT_PATH = path.join(__dirname, '../..'); -export interface IOptimizeAMDTaskOpts { +export interface IOptimizeESMTaskOpts { /** * The folder to read files from. */ src: string; /** - * (for AMD files, will get bundled and get Copyright treatment) + * The entry points to bundle. */ - entryPoints: bundle.IEntryPoint[]; + entryPoints: Array; /** - * (svg, etc.) + * Other resources to consider (svg, etc.) */ - resources: string[]; - /** - * Additional info we append to the end of the loader - */ - externalLoaderInfo?: util.IExternalLoaderInfo; - /** - * (true by default - append css and nls to loader) - */ - bundleLoader?: boolean; - /** - * (basically the Copyright treatment) - */ - header?: string; - /** - * (emit bundleInfo.json file) - */ - bundleInfo: boolean; - /** - * Language configuration. - */ - languages?: Language[]; + resources?: string[]; /** * File contents interceptor * @param contents The contents of the file @@ -61,20 +39,16 @@ export interface IOptimizeAMDTaskOpts { fileContentMapper?: (contents: string, path: string) => string; } -const DEFAULT_FILE_HEADER = [ - '/*!--------------------------------------------------------', - ' * Copyright (C) Microsoft Corporation. All rights reserved.', - ' *--------------------------------------------------------*/' -].join('\n'); - -function optimizeESMTask(opts: IOptimizeAMDTaskOpts, cjsOpts?: IOptimizeCommonJSTaskOpts): NodeJS.ReadWriteStream { +function optimizeESMTask(opts: IOptimizeESMTaskOpts): NodeJS.ReadWriteStream { const resourcesStream = es.through(); // this stream will contain the resources const bundlesStream = es.through(); // this stream will contain the bundled files - const entryPoints = opts.entryPoints; - if (cjsOpts) { - cjsOpts.entryPoints.forEach(entryPoint => entryPoints.push({ name: path.parse(entryPoint).name })); - } + const entryPoints = opts.entryPoints.map(entryPoint => { + if (typeof entryPoint === 'string') { + return { name: path.parse(entryPoint).name }; + } + return entryPoint; + }); const allMentionedModules = new Set(); for (const entryPoint of entryPoints) { @@ -198,7 +172,7 @@ function optimizeESMTask(opts: IOptimizeAMDTaskOpts, cjsOpts?: IOptimizeCommonJS es.readArray(output.files).pipe(bundlesStream); // forward all resources - gulp.src(opts.resources, { base: `${opts.src}`, allowEmpty: true }).pipe(resourcesStream); + gulp.src(opts.resources ?? [], { base: `${opts.src}`, allowEmpty: true }).pipe(resourcesStream); }); const result = es.merge( @@ -211,31 +185,7 @@ function optimizeESMTask(opts: IOptimizeAMDTaskOpts, cjsOpts?: IOptimizeCommonJS sourceRoot: undefined, addComment: true, includeContent: true - })) - .pipe(opts.languages && opts.languages.length ? processNlsFiles({ - out: opts.src, - fileHeader: opts.header || DEFAULT_FILE_HEADER, - languages: opts.languages - }) : es.through()); -} - -export interface IOptimizeCommonJSTaskOpts { - /** - * The paths to consider for optimizing. - */ - entryPoints: string[]; - /** - * The folder to read files from. - */ - src: string; - /** - * ESBuild `platform` option: https://esbuild.github.io/api/#platform - */ - platform: 'browser' | 'node' | 'neutral'; - /** - * ESBuild `external` option: https://esbuild.github.io/api/#external - */ - external: string[]; + })); } export interface IOptimizeManualTaskOpts { @@ -266,13 +216,9 @@ export interface IOptimizeTaskOpts { */ out: string; /** - * Optimize AMD modules (using our AMD loader). - */ - amd: IOptimizeAMDTaskOpts; - /** - * Optimize CommonJS modules (using esbuild). - */ - commonJS?: IOptimizeCommonJSTaskOpts; + * Optimize ESM modules (using esbuild). + */ + esm: IOptimizeESMTaskOpts; /** * Optimize manually by concatenating files. */ @@ -282,7 +228,7 @@ export interface IOptimizeTaskOpts { export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStream { return function () { const optimizers: NodeJS.ReadWriteStream[] = []; - optimizers.push(optimizeESMTask(opts.amd, opts.commonJS)); + optimizers.push(optimizeESMTask(opts.esm)); if (opts.manual) { optimizers.push(optimizeManualTask(opts.manual)); diff --git a/build/lib/util.js b/build/lib/util.js index 0433a469b1d..82e4189dd1a 100644 --- a/build/lib/util.js +++ b/build/lib/util.js @@ -21,11 +21,8 @@ exports.rreddir = rreddir; exports.ensureDir = ensureDir; exports.rebase = rebase; exports.filter = filter; -exports.versionStringToNumber = versionStringToNumber; exports.streamToPromise = streamToPromise; exports.getElectronVersion = getElectronVersion; -exports.acquireWebNodePaths = acquireWebNodePaths; -exports.createExternalLoaderConfig = createExternalLoaderConfig; const es = require("event-stream"); const _debounce = require("debounce"); const _filter = require("gulp-filter"); @@ -299,14 +296,6 @@ function filter(fn) { result.restore = es.through(); return result; } -function versionStringToNumber(versionStr) { - const semverRegex = /(\d+)\.(\d+)\.(\d+)/; - const match = versionStr.match(semverRegex); - if (!match) { - throw new Error('Version string is not properly formatted: ' + versionStr); - } - return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10); -} function streamToPromise(stream) { return new Promise((c, e) => { stream.on('error', err => e(err)); @@ -319,68 +308,4 @@ function getElectronVersion() { const msBuildId = /^ms_build_id="(.*)"$/m.exec(npmrc)[1]; return { electronVersion, msBuildId }; } -function acquireWebNodePaths() { - const root = path.join(__dirname, '..', '..'); - const webPackageJSON = path.join(root, '/remote/web', 'package.json'); - const webPackages = JSON.parse(fs.readFileSync(webPackageJSON, 'utf8')).dependencies; - const distroWebPackageJson = path.join(root, '.build/distro/npm/remote/web/package.json'); - if (fs.existsSync(distroWebPackageJson)) { - const distroWebPackages = JSON.parse(fs.readFileSync(distroWebPackageJson, 'utf8')).dependencies; - Object.assign(webPackages, distroWebPackages); - } - const nodePaths = {}; - for (const key of Object.keys(webPackages)) { - const packageJSON = path.join(root, 'node_modules', key, 'package.json'); - const packageData = JSON.parse(fs.readFileSync(packageJSON, 'utf8')); - // Only cases where the browser is a string are handled - let entryPoint = typeof packageData.browser === 'string' ? packageData.browser : packageData.main; - // On rare cases a package doesn't have an entrypoint so we assume it has a dist folder with a min.js - if (!entryPoint) { - // TODO @lramos15 remove this when jschardet adds an entrypoint so we can warn on all packages w/out entrypoint - if (key !== 'jschardet') { - console.warn(`No entry point for ${key} assuming dist/${key}.min.js`); - } - entryPoint = `dist/${key}.min.js`; - } - // Remove any starting path information so it's all relative info - if (entryPoint.startsWith('./')) { - entryPoint = entryPoint.substring(2); - } - else if (entryPoint.startsWith('/')) { - entryPoint = entryPoint.substring(1); - } - // Search for a minified entrypoint as well - if (/(? boolean): FilterStream { return result; } -export function versionStringToNumber(versionStr: string) { - const semverRegex = /(\d+)\.(\d+)\.(\d+)/; - const match = versionStr.match(semverRegex); - if (!match) { - throw new Error('Version string is not properly formatted: ' + versionStr); - } - - return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10); -} - export function streamToPromise(stream: NodeJS.ReadWriteStream): Promise { return new Promise((c, e) => { stream.on('error', err => e(err)); @@ -390,83 +380,3 @@ export function getElectronVersion(): Record { const msBuildId = /^ms_build_id="(.*)"$/m.exec(npmrc)![1]; return { electronVersion, msBuildId }; } - -export function acquireWebNodePaths() { - const root = path.join(__dirname, '..', '..'); - const webPackageJSON = path.join(root, '/remote/web', 'package.json'); - const webPackages = JSON.parse(fs.readFileSync(webPackageJSON, 'utf8')).dependencies; - - const distroWebPackageJson = path.join(root, '.build/distro/npm/remote/web/package.json'); - if (fs.existsSync(distroWebPackageJson)) { - const distroWebPackages = JSON.parse(fs.readFileSync(distroWebPackageJson, 'utf8')).dependencies; - Object.assign(webPackages, distroWebPackages); - } - - const nodePaths: { [key: string]: string } = {}; - for (const key of Object.keys(webPackages)) { - const packageJSON = path.join(root, 'node_modules', key, 'package.json'); - const packageData = JSON.parse(fs.readFileSync(packageJSON, 'utf8')); - // Only cases where the browser is a string are handled - let entryPoint: string = typeof packageData.browser === 'string' ? packageData.browser : packageData.main; - - // On rare cases a package doesn't have an entrypoint so we assume it has a dist folder with a min.js - if (!entryPoint) { - // TODO @lramos15 remove this when jschardet adds an entrypoint so we can warn on all packages w/out entrypoint - if (key !== 'jschardet') { - console.warn(`No entry point for ${key} assuming dist/${key}.min.js`); - } - - entryPoint = `dist/${key}.min.js`; - } - - // Remove any starting path information so it's all relative info - if (entryPoint.startsWith('./')) { - entryPoint = entryPoint.substring(2); - } else if (entryPoint.startsWith('/')) { - entryPoint = entryPoint.substring(1); - } - - // Search for a minified entrypoint as well - if (/(?