From d8466282471f3fa17241ee24ee39187b71029269 Mon Sep 17 00:00:00 2001 From: James Chen Date: Mon, 29 Jan 2024 18:25:47 +0800 Subject: [PATCH 1/3] Add build option: generatePreloadJsList --- modules/build-engine/src/engine-js/index.ts | 17 ++++- .../systemjs-named-register-plugin.ts | 65 +++++++++++++++++++ modules/build-engine/src/index.ts | 5 ++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 modules/build-engine/src/engine-js/rollup-plugins/systemjs-named-register-plugin.ts diff --git a/modules/build-engine/src/engine-js/index.ts b/modules/build-engine/src/engine-js/index.ts index 44a67830..fa5cbbc2 100644 --- a/modules/build-engine/src/engine-js/index.ts +++ b/modules/build-engine/src/engine-js/index.ts @@ -10,6 +10,7 @@ import type { buildEngine } from '../index'; import { externalWasmLoader } from './rollup-plugins/external-wasm-loader'; import { StatsQuery } from '@ccbuild/stats-query'; import { filePathToModuleRequest } from '@ccbuild/utils'; +import { rpNamedChunk } from './rollup-plugins/systemjs-named-register-plugin'; // import babel import babel = Transformer.core; @@ -301,9 +302,14 @@ export async function buildJsEngine(options: Required): Pro skipPreflightCheck: true, ...babelOptions, }), - ); + // The named-registered format of `System.register('cocos-js/cc.js', [], function() {...})` needs to be generated when the feature of preloading JS list is enabled. + // Otherwise, we will generate the default register code without name like `System.register([], function() {...})`. + if (options.generatePreloadJsList) { + rollupPlugins.push(rpNamedChunk()); + } + // if (options.progress) { // rollupPlugins.unshift(rpProgress()); // } @@ -433,8 +439,13 @@ export async function buildJsEngine(options: Required): Pro const rollupOutput = await rollupBuild.write(rollupOutputOptions); + const outputJSFileNames = []; const validEntryChunks: Record = {}; for (const output of rollupOutput.output) { + if (options.generatePreloadJsList && output.fileName.endsWith('js')) { + outputJSFileNames.push(output.fileName); + } + if (output.type === 'chunk') { if (output.isEntry) { const chunkName = output.name; @@ -445,6 +456,10 @@ export async function buildJsEngine(options: Required): Pro } } + if (options.generatePreloadJsList) { + fs.outputFileSync(ps.join(options.out, 'engine-js-list.json'), JSON.stringify(outputJSFileNames, undefined, 2)); + } + Object.assign(result.exports, validEntryChunks); result.dependencyGraph = {}; diff --git a/modules/build-engine/src/engine-js/rollup-plugins/systemjs-named-register-plugin.ts b/modules/build-engine/src/engine-js/rollup-plugins/systemjs-named-register-plugin.ts new file mode 100644 index 00000000..5837bfd5 --- /dev/null +++ b/modules/build-engine/src/engine-js/rollup-plugins/systemjs-named-register-plugin.ts @@ -0,0 +1,65 @@ +import { babel as Transformer } from '@ccbuild/transformer'; +import babel = Transformer.core; + +import { rollup as Bundler } from '@ccbuild/bundler'; +import rollup = Bundler.core; + +interface Options { + name: string; +} + +function toNamedRegister( + { types }: typeof babel, + options: Options, +): babel.PluginObj { + // options.name 为上面代码传递进来的 chunkId + if (!options || !options.name) { + throw new Error('\'name\' options is required.'); + } + + return { + visitor: { + CallExpression: (path): void => { + if (types.isMemberExpression(path.node.callee) && + types.isIdentifier(path.node.callee.object) && path.node.callee.object.name === 'System' && + types.isIdentifier(path.node.callee.property) && path.node.callee.property.name === 'register' && + path.node.arguments.length === 2) { + // 当发现 System.register([], function (exports, module) {}); 的时候,插入当前 chunk 的名称,变为: + // System.register('my_chunk_name', [], function (exports, module) {}); + path.node.arguments.unshift(types.stringLiteral(options.name)); + } + }, + }, + }; +} + +function getChunkUrl(chunk: rollup.RenderedChunk): string { + return `cocos-js/${chunk.fileName}`; +} + +type RenderChunkResult = { code: string; map?: rollup.SourceMapInput } | string | null | undefined; + +export function rpNamedChunk(): rollup.Plugin { + return { + name: 'named-chunk', + renderChunk: async function(this, code, chunk, options): Promise { + + const chunkId = getChunkUrl(chunk); + // 这里输入为 System.register([], function(){...}); 格式的 code + // 输出的 transformResult.code 为 System.register('chunk_id', [], function(){...}); 格式 + const transformResult = await babel.transformAsync(code, { + sourceMaps: true, // 这里需要强制为 true 吗? + compact: false, + plugins: [[toNamedRegister, { name: chunkId }]], + }); + if (!transformResult) { + this.warn('Failed to render chunk.'); + return null; + } + return { + code: transformResult.code!, + map: transformResult.map, + }; + }, + }; +} diff --git a/modules/build-engine/src/index.ts b/modules/build-engine/src/index.ts index b9d33bd1..0a63a11e 100644 --- a/modules/build-engine/src/index.ts +++ b/modules/build-engine/src/index.ts @@ -202,6 +202,11 @@ export namespace buildEngine { // * Whether force SUPPORT_JIT to the specified value. // */ // forceJitValue?: boolean, + + /** + * Whether to generate a json file that contains all output script file paths. + */ + generatePreloadJsList?: boolean; } export interface Result { From d3ee351cd1fa8bb72574b3f46ea1849fbe49a837 Mon Sep 17 00:00:00 2001 From: James Chen Date: Mon, 29 Jan 2024 18:36:56 +0800 Subject: [PATCH 2/3] Update api --- .api/public.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.api/public.d.ts b/.api/public.d.ts index 8384a59e..17225530 100644 --- a/.api/public.d.ts +++ b/.api/public.d.ts @@ -122,6 +122,10 @@ declare module "@cocos/ccbuild" { * @default false */ preserveType?: boolean; + /** + * Whether to generate a json file that contains all output script file paths. + */ + generatePreloadJsList?: boolean; } export interface Result { /** From e99db5d7e038075a97f341d115907c659d02b036 Mon Sep 17 00:00:00 2001 From: James Chen Date: Tue, 30 Jan 2024 14:03:23 +0800 Subject: [PATCH 3/3] Update version to 2.2.4 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d5b07c71..c98a2d4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@cocos/ccbuild", - "version": "2.2.3", + "version": "2.2.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@cocos/ccbuild", - "version": "2.2.3", + "version": "2.2.4", "hasInstallScript": true, "license": "MIT", "workspaces": [ diff --git a/package.json b/package.json index 079c7f3f..e819e99c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cocos/ccbuild", - "version": "2.2.3", + "version": "2.2.4", "description": "The next generation of build tool for Cocos engine.", "main": "./lib/index.js", "types": "./lib/index.d.ts",