diff --git a/.changeset/align-lynx-terminology.md b/.changeset/align-lynx-terminology.md new file mode 100644 index 0000000000..1684d66150 --- /dev/null +++ b/.changeset/align-lynx-terminology.md @@ -0,0 +1,9 @@ +--- +"@lynx-js/web-constants": patch +"@lynx-js/web-core": patch +"@lynx-js/react-webpack-plugin": patch +"@lynx-js/template-webpack-plugin": patch +"@lynx-js/react-rsbuild-plugin": patch +--- + +Align codebase terminology with the official Lynx specification. Add new preferred type aliases (`LynxBundle`, `BundleLoader`, `DecodedBundle`, `BundleSectionLabel`, `BundleHooks`, `LynxBundlePlugin`, `LynxBundlePluginOptions`) and deprecate legacy names. diff --git a/packages/rspeedy/plugin-config/src/pluginLynxConfig.ts b/packages/rspeedy/plugin-config/src/pluginLynxConfig.ts index bd33fae236..709b488d38 100644 --- a/packages/rspeedy/plugin-config/src/pluginLynxConfig.ts +++ b/packages/rspeedy/plugin-config/src/pluginLynxConfig.ts @@ -113,9 +113,9 @@ export function pluginLynxConfig( api.modifyBundlerChain(chain => { const exposed = api.useExposed< - { LynxTemplatePlugin: typeof LynxTemplatePlugin } + { LynxBundlePlugin: typeof LynxTemplatePlugin } >( - Symbol.for('LynxTemplatePlugin'), + Symbol.for('LynxBundlePlugin'), ) if (!exposed) { @@ -131,7 +131,7 @@ export function pluginLynxConfig( throw new Error( `\ -[pluginLynxConfig] No \`LynxTemplatePlugin\` exposed to ${ +[pluginLynxConfig] No \`LynxBundlePlugin\` exposed to ${ link( 'the plugin API', 'https://rsbuild.rs/plugins/dev/core#apiexpose', @@ -150,7 +150,7 @@ See ${ ) } - const { LynxTemplatePlugin: LynxTemplatePluginClass } = exposed + const { LynxBundlePlugin: LynxTemplatePluginClass } = exposed chain.plugin('lynx:config').use(LynxConfigWebpackPlugin, [ { diff --git a/packages/rspeedy/plugin-config/test/pluginLynxConfig.test.ts b/packages/rspeedy/plugin-config/test/pluginLynxConfig.test.ts index 56ff340b53..e9b33359a3 100644 --- a/packages/rspeedy/plugin-config/test/pluginLynxConfig.test.ts +++ b/packages/rspeedy/plugin-config/test/pluginLynxConfig.test.ts @@ -24,7 +24,7 @@ describe('pluginLynxConfig', () => { await expect(() => rspeedy.initConfigs()).rejects .toThrowErrorMatchingInlineSnapshot(` - [Error: [pluginLynxConfig] No \`LynxTemplatePlugin\` exposed to the plugin API (​https://rsbuild.rs/plugins/dev/core#apiexpose​). + [Error: [pluginLynxConfig] No \`LynxBundlePlugin\` exposed to the plugin API (​https://rsbuild.rs/plugins/dev/core#apiexpose​). Please upgrade Rspeedy and plugins to latest version. @@ -50,7 +50,7 @@ describe('pluginLynxConfig', () => { await expect(() => rspeedy.initConfigs()).rejects .toThrowErrorMatchingInlineSnapshot(` - [Error: [pluginLynxConfig] No \`LynxTemplatePlugin\` exposed to the plugin API (​https://rsbuild.rs/plugins/dev/core#apiexpose​). + [Error: [pluginLynxConfig] No \`LynxBundlePlugin\` exposed to the plugin API (​https://rsbuild.rs/plugins/dev/core#apiexpose​). Please upgrade @lynx-js/react-rsbuild-plugin to latest version. @@ -80,7 +80,7 @@ describe('pluginLynxConfig', () => { await expect(() => rspeedy.initConfigs()).rejects .toThrowErrorMatchingInlineSnapshot(` - [Error: [pluginLynxConfig] No \`LynxTemplatePlugin\` exposed to the plugin API (​https://rsbuild.rs/plugins/dev/core#apiexpose​). + [Error: [pluginLynxConfig] No \`LynxBundlePlugin\` exposed to the plugin API (​https://rsbuild.rs/plugins/dev/core#apiexpose​). Please upgrade @lynx-js/vue-rsbuild-plugin to latest version. @@ -104,8 +104,8 @@ describe('pluginLynxConfig', () => { { name: 'test', setup(api: RsbuildPluginAPI) { - api.expose(Symbol.for('LynxTemplatePlugin'), { - LynxTemplatePlugin, + api.expose(Symbol.for('LynxBundlePlugin'), { + LynxBundlePlugin: LynxTemplatePlugin, }) }, }, diff --git a/packages/rspeedy/plugin-react/etc/react-rsbuild-plugin.api.md b/packages/rspeedy/plugin-react/etc/react-rsbuild-plugin.api.md index 8ff1f93e37..8bc0bf5eab 100644 --- a/packages/rspeedy/plugin-react/etc/react-rsbuild-plugin.api.md +++ b/packages/rspeedy/plugin-react/etc/react-rsbuild-plugin.api.md @@ -4,16 +4,19 @@ ```ts +import type { BundleHooks } from '@lynx-js/template-webpack-plugin'; import { LAYERS } from '@lynx-js/react-webpack-plugin'; import type { LynxTemplatePlugin as LynxTemplatePlugin_2 } from '@lynx-js/template-webpack-plugin'; import type { RsbuildPlugin } from '@rsbuild/core'; -import type { TemplateHooks } from '@lynx-js/template-webpack-plugin'; // @public export interface AddComponentElementConfig { compilerOnly: boolean } +export { BundleHooks } +export { BundleHooks as TemplateHooks } + // @public export interface CompatVisitorConfig { addComponentElement: boolean | AddComponentElementConfig @@ -48,13 +51,13 @@ export interface ExtractStrConfig { export { LAYERS } -// Warning: (ae-missing-release-tag) "LynxTemplatePlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface LynxTemplatePlugin { +// @public +interface LynxBundlePlugin { // (undocumented) getLynxTemplatePluginHooks: typeof LynxTemplatePlugin_2.getLynxTemplatePluginHooks; } +export { LynxBundlePlugin } +export { LynxBundlePlugin as LynxTemplatePlugin } // @public export function pluginReactLynx(userOptions?: PluginReactLynxOptions): RsbuildPlugin[]; @@ -93,6 +96,4 @@ export interface ShakeVisitorConfig { retainProp: Array } -export { TemplateHooks } - ``` diff --git a/packages/rspeedy/plugin-react/src/index.ts b/packages/rspeedy/plugin-react/src/index.ts index ad6b3e3360..7e478e16d5 100644 --- a/packages/rspeedy/plugin-react/src/index.ts +++ b/packages/rspeedy/plugin-react/src/index.ts @@ -9,8 +9,8 @@ */ import type { + BundleHooks, LynxTemplatePlugin as InnerLynxTemplatePlugin, - TemplateHooks, } from '@lynx-js/template-webpack-plugin' export { pluginReactLynx } from './pluginReactLynx.js' @@ -24,14 +24,24 @@ export type { ShakeVisitorConfig, } from '@lynx-js/react-transform' -interface LynxTemplatePlugin { +/** + * The exposed Lynx Bundle Plugin API. + * + * @public + */ +interface LynxBundlePlugin { getLynxTemplatePluginHooks: typeof InnerLynxTemplatePlugin.getLynxTemplatePluginHooks } // We only export types here -// It is encouraged to use `api.useExposed(Symbol.for('LynxTemplatePlugin'))` +// It is encouraged to use `api.useExposed(Symbol.for('LynxBundlePlugin'))` // to access the actual API -export type { LynxTemplatePlugin, TemplateHooks } +export type { LynxBundlePlugin } +export type { BundleHooks } +/** @deprecated Use {@link LynxBundlePlugin} instead. */ +export type { LynxBundlePlugin as LynxTemplatePlugin } +/** @deprecated Use {@link BundleHooks} instead. */ +export type { BundleHooks as TemplateHooks } export { LAYERS } from '@lynx-js/react-webpack-plugin' diff --git a/packages/rspeedy/plugin-react/src/pluginReactLynx.ts b/packages/rspeedy/plugin-react/src/pluginReactLynx.ts index c73b921824..c57531f10d 100644 --- a/packages/rspeedy/plugin-react/src/pluginReactLynx.ts +++ b/packages/rspeedy/plugin-react/src/pluginReactLynx.ts @@ -197,7 +197,8 @@ export interface PluginReactLynxOptions { enableRemoveCSSScope?: boolean | undefined /** - * This flag controls when MainThread (Lepus) transfers control to Background after the first screen + * This flag controls when Main Thread Script (MTS) transfers + * control to Background Thread Script (BTS) after the first screen. * * This flag has two options: * @@ -205,8 +206,8 @@ export interface PluginReactLynxOptions { * * `"jsReady"`: Transfer when background (JS Runtime) is ready * - * After handing over control, MainThread (Lepus) runtime can no longer respond to data updates, - * and data updates will be forwarded to background (JS Runtime) and processed __asynchronously__ + * After handing over control, Main Thread Script (MTS) runtime can no longer respond to data updates, + * and data updates will be forwarded to Background Thread Script (BTS) and processed __asynchronously__ * * @defaultValue "immediately" */ @@ -252,8 +253,8 @@ export interface PluginReactLynxOptions { targetSdkVersion?: string /** - * Merge same string literals in JS and Lepus to reduce output bundle size. - * Set to `false` to disable. + * Merge same string literals in JS and Main Thread Script (MTS) + * to reduce output bundle size. Set to `false` to disable. * * @defaultValue false */ @@ -389,15 +390,15 @@ export function pluginReactLynx( } api.expose(Symbol.for('LAYERS'), LAYERS) - // Only expose `LynxTemplatePlugin.getLynxTemplatePluginHooks` to avoid - // other breaking changes in `LynxTemplatePlugin` - // breaks `pluginReactLynx` - api.expose(Symbol.for('LynxTemplatePlugin'), { - LynxTemplatePlugin: { + const exposedLynxBundlePlugin = { + LynxBundlePlugin: { getLynxTemplatePluginHooks: LynxTemplatePlugin .getLynxTemplatePluginHooks.bind(LynxTemplatePlugin), }, - }) + } + api.expose(Symbol.for('LynxBundlePlugin'), exposedLynxBundlePlugin) + // Backward compat: expose under old symbol too + api.expose(Symbol.for('LynxTemplatePlugin'), exposedLynxBundlePlugin) const require = createRequire(import.meta.url) const { version } = require('../package.json') as { version: string } diff --git a/packages/rspeedy/plugin-react/test/config.test.ts b/packages/rspeedy/plugin-react/test/config.test.ts index 3c0e9559ff..4801e806d5 100644 --- a/packages/rspeedy/plugin-react/test/config.test.ts +++ b/packages/rspeedy/plugin-react/test/config.test.ts @@ -1925,6 +1925,7 @@ describe('Config', () => { lynx: {}, }, plugins: [ + pluginStubRspeedyAPI(), pluginReactLynx({ defineDCE: { define: { __SOME_MACRO__: 'false' } }, }), @@ -1957,6 +1958,7 @@ describe('Config', () => { lynx: {}, }, plugins: [ + pluginStubRspeedyAPI(), pluginReactLynx({ defineDCE: { define: { diff --git a/packages/rspeedy/plugin-react/test/expose.test.ts b/packages/rspeedy/plugin-react/test/expose.test.ts index 894604fe9f..83eb3b759b 100644 --- a/packages/rspeedy/plugin-react/test/expose.test.ts +++ b/packages/rspeedy/plugin-react/test/expose.test.ts @@ -12,7 +12,7 @@ describe('Expose', () => { test('LynxTemplatePlugin', async () => { const { pluginReactLynx } = await import('../src/index.js') - let expose: { LynxTemplatePlugin: LynxTemplatePlugin } | undefined + let expose: { LynxBundlePlugin: LynxTemplatePlugin } | undefined let beforeEncodeArgs: | Parameters[1]>[0] | undefined @@ -31,8 +31,8 @@ describe('Expose', () => { name: 'pluginThatUsesTemplateHooks', setup(api) { expose = api.useExposed< - { LynxTemplatePlugin: LynxTemplatePlugin } - >(Symbol.for('LynxTemplatePlugin')) + { LynxBundlePlugin: LynxTemplatePlugin } + >(Symbol.for('LynxBundlePlugin')) api.modifyBundlerChain(chain => { const PLUGIN_NAME = 'pluginThatUsesTemplateHooks' chain.plugin(PLUGIN_NAME).use({ @@ -40,7 +40,7 @@ describe('Expose', () => { compiler.hooks.compilation.tap( PLUGIN_NAME, compilation => { - const templateHooks = expose!.LynxTemplatePlugin + const templateHooks = expose!.LynxBundlePlugin .getLynxTemplatePluginHooks( compilation as unknown as Parameters< LynxTemplatePlugin['getLynxTemplatePluginHooks'] @@ -67,7 +67,7 @@ describe('Expose', () => { await rsbuild.initConfigs() expect(expose).toMatchInlineSnapshot(` { - "LynxTemplatePlugin": { + "LynxBundlePlugin": { "getLynxTemplatePluginHooks": [Function], }, } diff --git a/packages/web-platform/web-constants/src/endpoints.ts b/packages/web-platform/web-constants/src/endpoints.ts index 313e53c66c..a8804971fa 100644 --- a/packages/web-platform/web-constants/src/endpoints.ts +++ b/packages/web-platform/web-constants/src/endpoints.ts @@ -95,6 +95,13 @@ export const flushElementTreeEndpoint = createRpcEndpoint< void >('flushElementTree', false, true); +/** + * Calls a method on the Main Thread Script (MTS) runtime. + * + * @remarks + * `callLepusMethod` is a legacy endpoint name. "Lepus" is the legacy term + * for Main Thread Script (MTS) in the Lynx specification. + */ export const callLepusMethodEndpoint = createRpcEndpoint< [name: string, data: unknown], void diff --git a/packages/web-platform/web-constants/src/types/LynxModule.ts b/packages/web-platform/web-constants/src/types/LynxModule.ts index 356bb36ca5..2ea68eeabf 100644 --- a/packages/web-platform/web-constants/src/types/LynxModule.ts +++ b/packages/web-platform/web-constants/src/types/LynxModule.ts @@ -18,7 +18,16 @@ export type ElementTemplateData = { dataset?: Record; }; -export interface LynxTemplate { +/** + * Represents a Lynx Bundle — the compiled artifact containing all necessary + * resources (stylesheet, scripts, serialized element tree) for a Lynx + * application to run. + * + * @remarks + * This interface corresponds to the "Bundle" concept in the official Lynx + * specification. + */ +export interface LynxBundle { styleInfo: StyleInfo; pageConfig: PageConfig; customSections: { @@ -28,10 +37,27 @@ export interface LynxTemplate { }; }; cardType?: string; + /** + * Main Thread Script (MTS) — code that runs on the main thread (UI thread). + * + * @remarks + * In the official Lynx specification this is called "Main Thread Script" + * (MTS). The field name `lepusCode` is a legacy artifact that cannot be + * renamed as it is part of the wire format. + */ lepusCode: { root: string; [key: string]: string; }; + /** + * Background Thread Script (BTS) — code that runs on the background thread. + * + * @remarks + * In the official Lynx specification this is called "Background Thread + * Script" (BTS). The field name `manifest` is a legacy artifact that cannot + * be renamed as it is part of the wire format. The key `'/app-service.js'` + * is a conventional entry point name for BTS. + */ manifest: { '/app-service.js': string; [key: string]: string; @@ -41,6 +67,11 @@ export interface LynxTemplate { appType: 'card' | 'lazy'; } +/** + * @deprecated Use {@link LynxBundle} instead. + */ +export type LynxTemplate = LynxBundle; + export type BTSChunkEntry = ( postMessage: undefined, module: { exports: unknown }, diff --git a/packages/web-platform/web-constants/src/types/TemplateLoader.ts b/packages/web-platform/web-constants/src/types/TemplateLoader.ts index f7a9736d61..07dfea3a08 100644 --- a/packages/web-platform/web-constants/src/types/TemplateLoader.ts +++ b/packages/web-platform/web-constants/src/types/TemplateLoader.ts @@ -1,3 +1,11 @@ -import type { LynxTemplate } from './LynxModule.js'; +import type { LynxBundle } from './LynxModule.js'; -export type TemplateLoader = (url: string) => Promise; +/** + * Loads a Lynx Bundle from the given URL. + */ +export type BundleLoader = (url: string) => Promise; + +/** + * @deprecated Use {@link BundleLoader} instead. + */ +export type TemplateLoader = BundleLoader; diff --git a/packages/web-platform/web-core-wasm/tests/decode.spec.ts b/packages/web-platform/web-core-wasm/tests/decode.spec.ts index 3fc09d4363..7c93139bd7 100644 --- a/packages/web-platform/web-core-wasm/tests/decode.spec.ts +++ b/packages/web-platform/web-core-wasm/tests/decode.spec.ts @@ -3,7 +3,7 @@ import { decodeTemplate } from '../ts/server/decode.js'; import { MagicHeader0, MagicHeader1, - TemplateSectionLabel, + BundleSectionLabel, } from '../ts/constants.js'; import * as wasm from '../ts/server/wasm.js'; @@ -138,7 +138,7 @@ describe('decodeTemplate', () => { const buffer = createTemplate({ sections: [ { - label: TemplateSectionLabel.Configurations, + label: BundleSectionLabel.Configurations, content: new Uint8Array(content), }, ], @@ -154,7 +154,7 @@ describe('decodeTemplate', () => { const buffer = createTemplate({ sections: [ - { label: TemplateSectionLabel.LepusCode, content }, + { label: BundleSectionLabel.MainThreadScript, content }, ], }); @@ -172,7 +172,7 @@ describe('decodeTemplate', () => { const buffer = createTemplate({ sections: [ - { label: TemplateSectionLabel.StyleInfo, content }, + { label: BundleSectionLabel.StyleInfo, content }, ], }); @@ -189,7 +189,7 @@ describe('decodeTemplate', () => { const buffer = createTemplate({ sections: [ - { label: TemplateSectionLabel.CustomSections, content: customData }, + { label: BundleSectionLabel.CustomSections, content: customData }, ], }); diff --git a/packages/web-platform/web-core-wasm/tests/encode.spec.ts b/packages/web-platform/web-core-wasm/tests/encode.spec.ts index 669fdfbbb2..309c99eb73 100644 --- a/packages/web-platform/web-core-wasm/tests/encode.spec.ts +++ b/packages/web-platform/web-core-wasm/tests/encode.spec.ts @@ -14,7 +14,7 @@ import { decode_style_info, } from '../binary/encode/encode.js'; import { encode, TasmJSONInfo } from '../ts/encode/webEncoder.js'; -import { TemplateSectionLabel } from '../ts/constants.js'; +import { BundleSectionLabel } from '../ts/constants.js'; describe('RawStyleInfo', () => { test('should encode StyleRule correctly', () => { @@ -389,7 +389,7 @@ describe('webEncoder', () => { offset += 4; const length = view.getUint32(offset, true); offset += 4; - if (label === TemplateSectionLabel.ElementTemplates) { + if (label === BundleSectionLabel.ElementTemplates) { throw new Error('ElementTemplates section should not be present'); } offset += length; diff --git a/packages/web-platform/web-core-wasm/ts/client/decodeWorker/decode.worker.ts b/packages/web-platform/web-core-wasm/ts/client/decodeWorker/decode.worker.ts index 30dd1b7993..f8b4614899 100644 --- a/packages/web-platform/web-core-wasm/ts/client/decodeWorker/decode.worker.ts +++ b/packages/web-platform/web-core-wasm/ts/client/decodeWorker/decode.worker.ts @@ -1,5 +1,5 @@ import { - TemplateSectionLabel, + BundleSectionLabel, MagicHeader0, MagicHeader1, } from '../../constants.js'; @@ -208,7 +208,7 @@ async function handleStream( } switch (label) { - case TemplateSectionLabel.Configurations: { + case BundleSectionLabel.Configurations: { config = overrideConfig ? { ...decodeJSONMap(content), ...overrideConfig } : decodeJSONMap(content); @@ -217,7 +217,7 @@ async function handleStream( ); break; } - case TemplateSectionLabel.StyleInfo: { + case BundleSectionLabel.StyleInfo: { await wasmModuleLoadedPromise; const buffer = wasmInstance.decode_style_info( content, @@ -238,7 +238,7 @@ async function handleStream( ); break; } - case TemplateSectionLabel.LepusCode: { + case BundleSectionLabel.MainThreadScript: { const codeMap = decodeBinaryMap(content); const isLazy = config['isLazy'] === 'true'; const blobMap: Record = {}; @@ -262,14 +262,14 @@ async function handleStream( ); break; } - case TemplateSectionLabel.ElementTemplates: { + case BundleSectionLabel.ElementTemplates: { postMessage( { type: 'section', label, url, data: content } as MainMessage, [content.buffer], ); break; } - case TemplateSectionLabel.CustomSections: { + case BundleSectionLabel.CustomSections: { postMessage( { type: 'section', label, url, data: content.buffer } as MainMessage, { @@ -278,7 +278,7 @@ async function handleStream( ); break; } - case TemplateSectionLabel.Manifest: { + case BundleSectionLabel.BackgroundThreadScript: { const codeMap = decodeBinaryMap(content); const blobMap: Record = {}; for (const [key, code] of Object.entries(codeMap)) { @@ -322,7 +322,7 @@ async function handleJSON( ); postMessage({ type: 'section', - label: TemplateSectionLabel.Configurations, + label: BundleSectionLabel.Configurations, url, data: config, } as MainMessage); @@ -338,7 +338,7 @@ async function handleJSON( postMessage( { type: 'section', - label: TemplateSectionLabel.StyleInfo, + label: BundleSectionLabel.StyleInfo, url, data: buffer.buffer, config, @@ -368,7 +368,7 @@ async function handleJSON( } postMessage({ type: 'section', - label: TemplateSectionLabel.LepusCode, + label: BundleSectionLabel.MainThreadScript, url, data: blobMap, config, @@ -387,7 +387,7 @@ async function handleJSON( } postMessage({ type: 'section', - label: TemplateSectionLabel.Manifest, + label: BundleSectionLabel.BackgroundThreadScript, url, data: blobMap, } as MainMessage); @@ -402,7 +402,7 @@ async function handleJSON( // So passing object is fine! postMessage({ type: 'section', - label: TemplateSectionLabel.CustomSections, + label: BundleSectionLabel.CustomSections, url, data: json.customSections, } as MainMessage); diff --git a/packages/web-platform/web-core-wasm/ts/client/mainthread/TemplateManager.ts b/packages/web-platform/web-core-wasm/ts/client/mainthread/TemplateManager.ts index 03ceb139d1..b9aae67598 100644 --- a/packages/web-platform/web-core-wasm/ts/client/mainthread/TemplateManager.ts +++ b/packages/web-platform/web-core-wasm/ts/client/mainthread/TemplateManager.ts @@ -4,7 +4,7 @@ * LICENSE file in the root directory of this source tree. */ -import { TemplateSectionLabel } from '../../constants.js'; +import { BundleSectionLabel } from '../../constants.js'; import type { LynxViewInstance } from './LynxViewInstance.js'; import type { MainMessage, @@ -194,13 +194,13 @@ export class TemplateManager { ]); const { label, data, url, config } = msg; switch (label) { - case TemplateSectionLabel.Configurations: { + case BundleSectionLabel.Configurations: { instance.backgroundThread.markTiming('decode_start'); this.#setConfig(url, data); instance.onPageConfigReady(data); break; } - case TemplateSectionLabel.StyleInfo: { + case BundleSectionLabel.StyleInfo: { const resource = new StyleSheetResource( new Uint8Array(data as ArrayBuffer), document, @@ -212,18 +212,18 @@ export class TemplateManager { instance.onStyleInfoReady(url); break; } - case TemplateSectionLabel.LepusCode: { + case BundleSectionLabel.MainThreadScript: { const blobMap = data as Record; this.#setLepusCode(url, blobMap); instance.onMTSScriptsLoaded(url, config!['isLazy'] === 'true'); break; } - case TemplateSectionLabel.CustomSections: { + case BundleSectionLabel.CustomSections: { this.#setCustomSection(url, data); break; } - case TemplateSectionLabel.Manifest: { + case BundleSectionLabel.BackgroundThreadScript: { const blobMap = data as Record; this.#setBackgroundCode(url, blobMap); instance.onBTSScriptsLoaded(url); diff --git a/packages/web-platform/web-core-wasm/ts/constants.ts b/packages/web-platform/web-core-wasm/ts/constants.ts index 3010a36055..5b97fda70a 100644 --- a/packages/web-platform/web-core-wasm/ts/constants.ts +++ b/packages/web-platform/web-core-wasm/ts/constants.ts @@ -51,10 +51,20 @@ export const LynxEventNameToW3cCommon: Record = export const MagicHeader0 = /*#__PURE__*/ 0x41524453; // 'SDRA' export const MagicHeader1 = /*#__PURE__*/ 0x464F5257; // 'WROF' -export const TemplateSectionLabel = /*#__PURE__*/ { - Manifest: 1, +/** + * Section labels used in the binary Lynx Bundle encoding format. + * + * @remarks + * `BackgroundThreadScript` corresponds to "Manifest" in legacy code. + * `MainThreadScript` corresponds to "LepusCode" in legacy code. + * Wire values are unchanged. + */ +export const BundleSectionLabel = /*#__PURE__*/ { + /** Background Thread Script (BTS). Legacy name: "Manifest". */ + BackgroundThreadScript: 1, StyleInfo: 2, - LepusCode: 3, + /** Main Thread Script (MTS). Legacy name: "LepusCode". */ + MainThreadScript: 3, CustomSections: 4, ElementTemplates: 5, Configurations: 6, diff --git a/packages/web-platform/web-core-wasm/ts/encode/webEncoder.ts b/packages/web-platform/web-core-wasm/ts/encode/webEncoder.ts index 788509423e..77013d7598 100644 --- a/packages/web-platform/web-core-wasm/ts/encode/webEncoder.ts +++ b/packages/web-platform/web-core-wasm/ts/encode/webEncoder.ts @@ -9,7 +9,7 @@ import { encodeCSS } from './encodeCSS.js'; import { MagicHeader0, MagicHeader1, - TemplateSectionLabel, + BundleSectionLabel, } from '../constants.js'; function encodeAsJSON(map: Record): Uint8Array { @@ -61,10 +61,18 @@ function encodeStringMap(map: Record): Uint8Array { export type TasmJSONInfo = { styleInfo: Record; + /** + * Background Thread Script (BTS) chunks. + * @remarks The field name `manifest` is a legacy artifact. + */ manifest: Record; cardType: string; appType: string; pageConfig: Record; + /** + * Main Thread Script (MTS) chunks. + * @remarks The field name `lepusCode` is a legacy artifact. + */ lepusCode: Record; customSections: Record; customSections?: Record; backgroundCode?: Record; styleSheet?: StyleSheetResource; } + +/** + * @deprecated Use {@link DecodedBundle} instead. + */ +export type DecodedTemplate = DecodedBundle; diff --git a/packages/web-platform/web-core/src/index.ts b/packages/web-platform/web-core/src/index.ts index 62fb7b9c60..2e8a210121 100644 --- a/packages/web-platform/web-core/src/index.ts +++ b/packages/web-platform/web-core/src/index.ts @@ -3,4 +3,6 @@ // LICENSE file in the root directory of this source tree. export { createLynxView } from './apis/createLynxView.js'; export { LynxView } from './apis/LynxView.js'; +/** @deprecated Use {@link LynxBundle} instead. `LynxTemplate` is a legacy name. */ export type { LynxTemplate } from '@lynx-js/web-constants'; +export type { LynxBundle } from '@lynx-js/web-constants'; diff --git a/packages/web-platform/web-mainthread-apis/ts/createMainThreadGlobalThis.ts b/packages/web-platform/web-mainthread-apis/ts/createMainThreadGlobalThis.ts index 204b86e90f..9430ee4b7b 100644 --- a/packages/web-platform/web-mainthread-apis/ts/createMainThreadGlobalThis.ts +++ b/packages/web-platform/web-mainthread-apis/ts/createMainThreadGlobalThis.ts @@ -147,6 +147,7 @@ export interface MainThreadRuntimeConfig { pageConfig: PageConfig; globalProps: unknown; callbacks: MainThreadRuntimeCallbacks; + /** The Lynx Bundle (legacy field name: `lynxTemplate`). */ lynxTemplate: LynxTemplate; browserConfig: BrowserConfig; tagMap: Record; @@ -676,6 +677,13 @@ export function createMainThreadGlobalThis( ); }; + /** + * Loads a Main Thread Script (MTS) chunk by path. + * + * @remarks + * `__LoadLepusChunk` is a legacy function name. "Lepus" is the legacy term + * for Main Thread Script (MTS) in the Lynx specification. + */ const __LoadLepusChunk: (path: string) => boolean = (path) => { try { path = lepusCode?.[path] ?? path; diff --git a/packages/web-platform/web-mainthread-apis/ts/crossThreadHandlers/registerCallLepusMethodHandler.ts b/packages/web-platform/web-mainthread-apis/ts/crossThreadHandlers/registerCallLepusMethodHandler.ts index 7711437548..16fd5f5bc2 100644 --- a/packages/web-platform/web-mainthread-apis/ts/crossThreadHandlers/registerCallLepusMethodHandler.ts +++ b/packages/web-platform/web-mainthread-apis/ts/crossThreadHandlers/registerCallLepusMethodHandler.ts @@ -7,6 +7,12 @@ import { type Rpc, } from '@lynx-js/web-constants'; +/** + * Registers a handler for calling Main Thread Script (MTS) methods. + * + * @remarks + * "Lepus" in the function name is a legacy term for Main Thread Script (MTS). + */ export function registerCallLepusMethodHandler( rpc: Rpc, runtime: MainThreadGlobalThis, diff --git a/packages/webpack/react-webpack-plugin/src/ReactWebpackPlugin.ts b/packages/webpack/react-webpack-plugin/src/ReactWebpackPlugin.ts index b1a37f6d9c..3a1f96ee01 100644 --- a/packages/webpack/react-webpack-plugin/src/ReactWebpackPlugin.ts +++ b/packages/webpack/react-webpack-plugin/src/ReactWebpackPlugin.ts @@ -44,8 +44,8 @@ interface ReactWebpackPluginOptions { mainThreadChunks?: string[] | undefined; /** - * Merge same string literals in JS and Lepus to reduce output bundle size. - * Set to `false` to disable. + * Merge same string literals in JS and Main Thread Script (MTS) + * to reduce output bundle size. Set to `false` to disable. * * @defaultValue false */ diff --git a/packages/webpack/react-webpack-plugin/src/loaders/options.ts b/packages/webpack/react-webpack-plugin/src/loaders/options.ts index 5c70935dda..e5a87eb04b 100644 --- a/packages/webpack/react-webpack-plugin/src/loaders/options.ts +++ b/packages/webpack/react-webpack-plugin/src/loaders/options.ts @@ -15,6 +15,7 @@ import type { const PLUGIN_NAME = 'react:webpack'; const JSX_IMPORT_SOURCE = { + // `lepus` is a legacy path segment for Main Thread Script (MTS). MAIN_THREAD: '@lynx-js/react/lepus', BACKGROUND: '@lynx-js/react', }; diff --git a/packages/webpack/template-webpack-plugin/etc/template-webpack-plugin.api.md b/packages/webpack/template-webpack-plugin/etc/template-webpack-plugin.api.md index 1d2994c9d1..ddecb38aed 100644 --- a/packages/webpack/template-webpack-plugin/etc/template-webpack-plugin.api.md +++ b/packages/webpack/template-webpack-plugin/etc/template-webpack-plugin.api.md @@ -14,6 +14,40 @@ import { cssChunksToMap } from '@lynx-js/css-serializer'; import { Plugins } from '@lynx-js/css-serializer'; import { SyncWaterfallHook } from '@rspack/lite-tapable'; +// @public +export interface BundleHooks { + // @alpha + afterEmit: AsyncSeriesWaterfallHook<{ + outputName: string; + }>; + // @alpha + asyncChunkName: SyncWaterfallHook; + // @alpha + beforeEmit: AsyncSeriesWaterfallHook<{ + finalEncodeOptions: EncodeOptions; + debugInfo: string; + template: Buffer; + outputName: string; + mainThreadAssets: Asset[]; + cssChunks: Asset[]; + entryNames: string[]; + }>; + // @alpha + beforeEncode: AsyncSeriesWaterfallHook<{ + encodeData: EncodeRawData; + filenameTemplate: string; + entryNames: string[]; + }>; + // @alpha + encode: AsyncSeriesBailHook<{ + encodeOptions: EncodeOptions; + intermediate?: string; + }, { + buffer: Buffer; + debugInfo: string; + }>; +} + export { CSS } // Warning: (ae-missing-release-tag) "CSSPlugins" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -34,50 +68,19 @@ export interface EncodeOptions { type?: 'lazy'; content: string | Record; }>; - // (undocumented) lepusCode: { root: string | undefined; lepusChunk: Record; filename: string | undefined; }; - // (undocumented) manifest: Record; } // @public -export class LynxEncodePlugin { - constructor(options?: LynxEncodePluginOptions | undefined); - apply(compiler: Compiler): void; - static BEFORE_EMIT_STAGE: number; - static BEFORE_ENCODE_STAGE: number; - static defaultOptions: Readonly>; - static ENCODE_STAGE: number; - // (undocumented) - protected options?: LynxEncodePluginOptions | undefined; -} - -// @public -export interface LynxEncodePluginOptions { - // Warning: (ae-forgotten-export) The symbol "InlineChunkConfig" needs to be exported by the entry point index.d.ts - // - // (undocumented) - inlineScripts?: InlineChunkConfig | undefined; -} +export const LynxBundlePlugin: typeof LynxTemplatePlugin; // @public -export class LynxTemplatePlugin { - constructor(options?: LynxTemplatePluginOptions | undefined); - apply(compiler: Compiler): void; - static convertCSSChunksToMap(cssChunks: string[], plugins: CSS.Plugin[], enableCSSSelector: boolean): { - cssMap: Record; - cssSource: Record; - }; - static defaultOptions: Readonly>; - static getLynxTemplatePluginHooks(compilation: Compilation): TemplateHooks; -} - -// @public -export interface LynxTemplatePluginOptions { +export interface LynxBundlePluginOptions { chunks?: 'all' | string[]; cssPlugins: CSS.Plugin[]; customCSSInheritanceList: string[] | undefined; @@ -103,39 +106,47 @@ export interface LynxTemplatePluginOptions { } // @public -export interface TemplateHooks { - // @alpha - afterEmit: AsyncSeriesWaterfallHook<{ - outputName: string; - }>; - // @alpha - asyncChunkName: SyncWaterfallHook; - // @alpha - beforeEmit: AsyncSeriesWaterfallHook<{ - finalEncodeOptions: EncodeOptions; - debugInfo: string; - template: Buffer; - outputName: string; - mainThreadAssets: Asset[]; - cssChunks: Asset[]; - entryNames: string[]; - }>; - // @alpha - beforeEncode: AsyncSeriesWaterfallHook<{ - encodeData: EncodeRawData; - filenameTemplate: string; - entryNames: string[]; - }>; - // @alpha - encode: AsyncSeriesBailHook<{ - encodeOptions: EncodeOptions; - intermediate?: string; - }, { - buffer: Buffer; - debugInfo: string; - }>; +export class LynxEncodePlugin { + constructor(options?: LynxEncodePluginOptions | undefined); + apply(compiler: Compiler): void; + static BEFORE_EMIT_STAGE: number; + static BEFORE_ENCODE_STAGE: number; + static defaultOptions: Readonly>; + static ENCODE_STAGE: number; + // (undocumented) + protected options?: LynxEncodePluginOptions | undefined; +} + +// @public +export interface LynxEncodePluginOptions { + // Warning: (ae-forgotten-export) The symbol "InlineChunkConfig" needs to be exported by the entry point index.d.ts + // + // (undocumented) + inlineScripts?: InlineChunkConfig | undefined; } +// @public @deprecated +export class LynxTemplatePlugin { + constructor(options?: LynxBundlePluginOptions | undefined); + apply(compiler: Compiler): void; + static convertCSSChunksToMap(cssChunks: string[], plugins: CSS.Plugin[], enableCSSSelector: boolean): { + cssMap: Record; + cssSource: Record; + }; + static defaultOptions: Readonly>; + static getLynxTemplatePluginHooks(compilation: Compilation): BundleHooks; +} + +// Warning: (ae-missing-release-tag) "LynxTemplatePluginOptions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public @deprecated (undocumented) +export type LynxTemplatePluginOptions = LynxBundlePluginOptions; + +// Warning: (ae-missing-release-tag) "TemplateHooks" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public @deprecated (undocumented) +export type TemplateHooks = BundleHooks; + // Warning: (ae-missing-release-tag) "WebEncodePlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -155,6 +166,6 @@ export class WebEncodePlugin { // Warnings were encountered during analysis: // -// lib/LynxTemplatePlugin.d.ts:68:9 - (ae-forgotten-export) The symbol "EncodeRawData" needs to be exported by the entry point index.d.ts +// lib/LynxTemplatePlugin.d.ts:89:9 - (ae-forgotten-export) The symbol "EncodeRawData" needs to be exported by the entry point index.d.ts ``` diff --git a/packages/webpack/template-webpack-plugin/src/LynxEncodePlugin.ts b/packages/webpack/template-webpack-plugin/src/LynxEncodePlugin.ts index 405c401c10..0d0b9cf41b 100644 --- a/packages/webpack/template-webpack-plugin/src/LynxEncodePlugin.ts +++ b/packages/webpack/template-webpack-plugin/src/LynxEncodePlugin.ts @@ -179,7 +179,8 @@ export class LynxEncodePluginImpl { } encodeData.manifest = { - // `app-service.js` is the entry point of a template. + // `/app-service.js` is the conventional entry point name for + // Background Thread Script (BTS) in a Lynx Bundle. // All the initial chunks will be loaded **synchronously**. // // ``` @@ -235,6 +236,7 @@ export class LynxEncodePluginImpl { }); } + /** Conventional BTS entry point name in a Lynx Bundle. */ #APP_SERVICE_NAME = '/app-service.js'; #appServiceBanner(): string { const loadScriptBanner = `(function(){'use strict';function n({tt}){`; diff --git a/packages/webpack/template-webpack-plugin/src/LynxTemplatePlugin.ts b/packages/webpack/template-webpack-plugin/src/LynxTemplatePlugin.ts index 38c8287030..11ec8ff2b0 100644 --- a/packages/webpack/template-webpack-plugin/src/LynxTemplatePlugin.ts +++ b/packages/webpack/template-webpack-plugin/src/LynxTemplatePlugin.ts @@ -25,6 +25,12 @@ import { RuntimeGlobals } from '@lynx-js/webpack-runtime-globals'; import { createLynxAsyncChunksRuntimeModule } from './LynxAsyncChunksRuntimeModule.js'; +/** + * @deprecated The name `OriginManifest` is a legacy artifact. "Manifest" here + * refers to Background Thread Script (BTS) chunks in the official Lynx + * specification. Use the inline record type directly or see + * {@link EncodeOptions.manifest}. + */ export type OriginManifest = Record; compilerOptions: Record; + /** + * Main Thread Script (MTS) and its associated chunks. + * + * @remarks + * In the official Lynx specification this is called "Main Thread Script" + * (MTS). The field name `lepusCode` is a legacy artifact. The inner + * `lepusChunk` field holds additional MTS chunks. + */ lepusCode: { root: string | undefined; lepusChunk: Record; @@ -51,10 +72,10 @@ export interface EncodeOptions { [k: string]: unknown; } -const LynxTemplatePluginHooksMap = new WeakMap(); +const LynxTemplatePluginHooksMap = new WeakMap(); /** - * To allow other plugins to alter the Template, this plugin executes + * To allow other plugins to alter the Bundle, this plugin executes * {@link https://github.com/webpack/tapable | tapable} hooks. * * @example @@ -80,7 +101,7 @@ const LynxTemplatePluginHooksMap = new WeakMap(); * * @public */ -export interface TemplateHooks { +export interface BundleHooks { /** * Get the real name of an async chunk. The files with the same `asyncChunkName` will be placed in the same template. * @@ -141,7 +162,7 @@ export interface TemplateHooks { * Add hooks to the webpack compilation object to allow foreign plugins to * extend the LynxTemplatePlugin */ -function createLynxTemplatePluginHooks(): TemplateHooks { +function createLynxTemplatePluginHooks(): BundleHooks { return { asyncChunkName: new SyncWaterfallHook(['pluginArgs']), beforeEncode: new AsyncSeriesWaterfallHook(['pluginArgs']), @@ -152,11 +173,11 @@ function createLynxTemplatePluginHooks(): TemplateHooks { } /** - * The options for LynxTemplatePlugin + * The options for {@link LynxTemplatePlugin}. * * @public */ -export interface LynxTemplatePluginOptions { +export interface LynxBundlePluginOptions { /** * The file to write the template to. * Supports subdirectories eg: `assets/template.js`. @@ -304,7 +325,11 @@ interface EncodeRawData { [k: string]: string | boolean; }; /** - * main-thread + * Main Thread Script (MTS) assets. + * + * @remarks + * The field name `lepusCode` is a legacy artifact. In the official Lynx + * specification this is called "Main Thread Script" (MTS). */ lepusCode: { root: Asset | undefined; @@ -312,7 +337,11 @@ interface EncodeRawData { filename: string | undefined; }; /** - * background thread + * Background Thread Script (BTS) assets. + * + * @remarks + * The field name `manifest` is a legacy artifact. In the official Lynx + * specification this is called "Background Thread Script" (BTS). */ manifest: Record; css: { @@ -332,17 +361,25 @@ interface EncodeRawData { } /** - * LynxTemplatePlugin + * The core webpack / rspack plugin that orchestrates Lynx Bundle assembly and + * encoding. + * + * @remarks + * In the official Lynx specification the output artifact is called a "Bundle". + * The class name `LynxTemplatePlugin` is a legacy artifact. + * + * @deprecated Use {@link LynxBundlePlugin} instead. This alias is retained for + * backward compatibility. * * @public */ export class LynxTemplatePlugin { - constructor(private options?: LynxTemplatePluginOptions | undefined) {} + constructor(private options?: LynxBundlePluginOptions | undefined) {} /** * Returns all public hooks of the Lynx template webpack plugin for the given compilation */ - static getLynxTemplatePluginHooks(compilation: Compilation): TemplateHooks { + static getLynxTemplatePluginHooks(compilation: Compilation): BundleHooks { let hooks = LynxTemplatePluginHooksMap.get(compilation); // Setup the hooks only once if (hooks === undefined) { @@ -375,8 +412,8 @@ export class LynxTemplatePlugin { * * @public */ - static defaultOptions: Readonly> = Object - .freeze>({ + static defaultOptions: Readonly> = Object + .freeze>({ filename: '[name].bundle', lazyBundleFilename: 'async/[name].[fullhash].bundle', intermediate: '.rspeedy', @@ -464,7 +501,7 @@ class LynxTemplatePluginImpl { constructor( compiler: Compiler, - options: Required, + options: Required, ) { this.#options = options; @@ -1025,7 +1062,7 @@ class LynxTemplatePluginImpl { return assets; } - #options: Required; + #options: Required; } interface AssetsInformationByGroups { @@ -1066,3 +1103,24 @@ export function predicateNonHotModuleReplacementAsset( ?? assetMetaInformation.development ); } + +// --------------------------------------------------------------------------- +// Deprecated aliases — retained for backward compatibility. +// --------------------------------------------------------------------------- + +/** + * Preferred canonical plugin name aligned with the official Lynx specification. + * + * @public + */ +export const LynxBundlePlugin: typeof LynxTemplatePlugin = LynxTemplatePlugin; + +/** + * @deprecated Use {@link BundleHooks} instead. + */ +export type TemplateHooks = BundleHooks; + +/** + * @deprecated Use {@link LynxBundlePluginOptions} instead. + */ +export type LynxTemplatePluginOptions = LynxBundlePluginOptions; diff --git a/packages/webpack/template-webpack-plugin/src/WebEncodePlugin.ts b/packages/webpack/template-webpack-plugin/src/WebEncodePlugin.ts index eca646e4b3..fc0a81f1f1 100644 --- a/packages/webpack/template-webpack-plugin/src/WebEncodePlugin.ts +++ b/packages/webpack/template-webpack-plugin/src/WebEncodePlugin.ts @@ -68,7 +68,7 @@ export class WebEncodePlugin { Object.assign(encodeData, { manifest: { - // `app-service.js` is the entry point of a template. + // `/app-service.js` is the conventional BTS entry point in a Lynx Bundle. '/app-service.js': content, }, customSections: encodeData.customSections, diff --git a/packages/webpack/template-webpack-plugin/src/index.ts b/packages/webpack/template-webpack-plugin/src/index.ts index 50969e31ac..e004b6b068 100644 --- a/packages/webpack/template-webpack-plugin/src/index.ts +++ b/packages/webpack/template-webpack-plugin/src/index.ts @@ -11,10 +11,12 @@ import { Plugins } from '@lynx-js/css-serializer'; import * as CSS from '@lynx-js/css-serializer'; -export { LynxTemplatePlugin } from './LynxTemplatePlugin.js'; +export { LynxTemplatePlugin, LynxBundlePlugin } from './LynxTemplatePlugin.js'; export type { LynxTemplatePluginOptions, + LynxBundlePluginOptions, TemplateHooks, + BundleHooks, EncodeOptions, } from './LynxTemplatePlugin.js'; export { LynxEncodePlugin } from './LynxEncodePlugin.js';