Skip to content

Commit

Permalink
Add build option: generatePreloadJsList (#56)
Browse files Browse the repository at this point in the history
* Add build option: generatePreloadJsList

* Update api

* Update version to 2.2.4
  • Loading branch information
dumganhar authored Feb 22, 2024
1 parent 4abce10 commit 8969619
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 4 deletions.
4 changes: 4 additions & 0 deletions .api/public.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
/**
Expand Down
17 changes: 16 additions & 1 deletion modules/build-engine/src/engine-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -301,9 +302,14 @@ export async function buildJsEngine(options: Required<buildEngine.Options>): 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());
// }
Expand Down Expand Up @@ -433,8 +439,13 @@ export async function buildJsEngine(options: Required<buildEngine.Options>): Pro

const rollupOutput = await rollupBuild.write(rollupOutputOptions);

const outputJSFileNames = [];
const validEntryChunks: Record<string, string> = {};
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;
Expand All @@ -445,6 +456,10 @@ export async function buildJsEngine(options: Required<buildEngine.Options>): 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 = {};
Expand Down
Original file line number Diff line number Diff line change
@@ -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<RenderChunkResult> {

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,
};
},
};
}
5 changes: 5 additions & 0 deletions modules/build-engine/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down

0 comments on commit 8969619

Please sign in to comment.