Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/flat-bikes-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@lynx-js/lynx-bundle-rslib-config": patch
"@lynx-js/react-umd": patch
---

Support compile main-thread script to bytecode in external bundle
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export interface ExternalBundleWebpackPluginOptions {
buffer: Buffer;
}>;
engineVersion?: string | undefined;
mainThreadChunks?: string[] | undefined;
}

// @public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,8 +453,9 @@ export function defineExternalBundleRslibConfig(
),
],
plugins: [
externalBundleEntryRsbuildPlugin(),
externalBundleRsbuildPlugin(encodeOptions.engineVersion),
externalBundleRsbuildPlugin({
engineVersion: encodeOptions.engineVersion,
}),
],
}
}
Expand All @@ -472,8 +473,12 @@ interface ExposedLayers {
* - `<name>` for background
* - `<name>__main-thread` for main thread
*/
const externalBundleEntryRsbuildPlugin = (): rsbuild.RsbuildPlugin => ({
name: 'lynx:external-bundle-entry',
const externalBundleRsbuildPlugin = ({
engineVersion,
}: {
engineVersion: string | undefined
}): rsbuild.RsbuildPlugin => ({
name: 'lynx:external-bundle',
// ensure dsl plugin has exposed LAYERS
enforce: 'post',
setup(api) {
Expand All @@ -488,75 +493,85 @@ const externalBundleEntryRsbuildPlugin = (): rsbuild.RsbuildPlugin => ({
)
}

api.modifyBundlerChain((chain) => {
// copy entries
const entries = chain.entryPoints.entries() ?? {}
api.modifyBundlerChain(
async (chain, { environment: { name: libName } }) => {
// copy entries
const entries = chain.entryPoints.entries() ?? {}

chain.entryPoints.clear()
chain.entryPoints.clear()

const backgroundEntryName: string[] = []
const mainThreadEntryName: string[] = []
const backgroundEntryName: string[] = []
const mainThreadEntryName: string[] = []
const mainThreadChunks: string[] = []

const addLayeredEntry = (
entryName: string,
entryValue: Rspack.EntryDescription,
) => {
chain
.entry(entryName)
.add(entryValue)
.end()
}
const addLayeredEntry = (
entryName: string,
entryValue: Rspack.EntryDescription,
) => {
const isMainThread = entryValue.layer === LAYERS.MAIN_THREAD
if (isMainThread) {
mainThreadChunks.push(entryName + '.js')
}

Object.entries(entries).forEach(([entryName, entryPoint]) => {
const entryPointValue = entryPoint.values()

for (const value of entryPointValue) {
if (typeof value === 'string' || Array.isArray(value)) {
const mainThreadEntry = `${entryName}__main-thread`
const backgroundEntry = entryName
mainThreadEntryName.push(mainThreadEntry)
backgroundEntryName.push(backgroundEntry)
addLayeredEntry(mainThreadEntry, {
import: value,
layer: LAYERS.MAIN_THREAD,
})
addLayeredEntry(backgroundEntry, {
import: value,
layer: LAYERS.BACKGROUND,
})
} else {
// object
const { layer } = value
if (layer === LAYERS.MAIN_THREAD) {
mainThreadEntryName.push(entryName)
addLayeredEntry(entryName, {
...value,
layer: LAYERS.MAIN_THREAD,
})
} else if (layer === LAYERS.BACKGROUND) {
backgroundEntryName.push(entryName)
addLayeredEntry(entryName, { ...value, layer: LAYERS.BACKGROUND })
} else {
// not specify layer
chain
.entry(entryName)
.add(entryValue)
.end()
}

Object.entries(entries).forEach(([entryName, entryPoint]) => {
const entryPointValue = entryPoint.values()

for (const value of entryPointValue) {
if (typeof value === 'string' || Array.isArray(value)) {
const mainThreadEntry = `${entryName}__main-thread`
const backgroundEntry = entryName
mainThreadEntryName.push(mainThreadEntry)
backgroundEntryName.push(backgroundEntry)
addLayeredEntry(mainThreadEntry, {
...value,
import: value,
layer: LAYERS.MAIN_THREAD,
})
addLayeredEntry(backgroundEntry, {
...value,
import: value,
layer: LAYERS.BACKGROUND,
})
} else {
// object
const { layer } = value
if (layer === LAYERS.MAIN_THREAD) {
mainThreadEntryName.push(entryName)
addLayeredEntry(entryName, {
...value,
layer: LAYERS.MAIN_THREAD,
})
} else if (layer === LAYERS.BACKGROUND) {
backgroundEntryName.push(entryName)
addLayeredEntry(entryName, {
...value,
layer: LAYERS.BACKGROUND,
})
} else {
// not specify layer
const mainThreadEntry = `${entryName}__main-thread`
const backgroundEntry = entryName
mainThreadEntryName.push(mainThreadEntry)
backgroundEntryName.push(backgroundEntry)
addLayeredEntry(mainThreadEntry, {
...value,
layer: LAYERS.MAIN_THREAD,
})
addLayeredEntry(backgroundEntry, {
...value,
layer: LAYERS.BACKGROUND,
})
}
}
}
}
})
// add external bundle wrapper
// dprint-ignore
chain
})
// add external bundle wrapper
// dprint-ignore
chain
.plugin(MainThreadRuntimeWrapperWebpackPlugin.name)
.use(MainThreadRuntimeWrapperWebpackPlugin, [{
test: mainThreadEntryName.map((name) => new RegExp(`${escapeRegex(name)}\\.js$`)),
Expand All @@ -567,20 +582,11 @@ const externalBundleEntryRsbuildPlugin = (): rsbuild.RsbuildPlugin => ({
test: backgroundEntryName.map((name) => new RegExp(`${escapeRegex(name)}\\.js$`)),
}])
.end()
})
},
})

const externalBundleRsbuildPlugin = (
engineVersion: string | undefined,
): rsbuild.RsbuildPlugin => ({
name: 'lynx:gen-external-bundle',
async setup(api) {
const { getEncodeMode } = await import('@lynx-js/tasm')
const { getEncodeMode } = await import('@lynx-js/tasm')

api.modifyBundlerChain((chain, { environment: { name: libName } }) => {
// dprint-ignore
chain
// dprint-ignore
chain
.plugin(ExternalBundleWebpackPlugin.name)
.use(
ExternalBundleWebpackPlugin,
Expand All @@ -589,11 +595,13 @@ const externalBundleRsbuildPlugin = (
bundleFileName: `${libName}.lynx.bundle`,
encode: getEncodeMode(),
engineVersion,
mainThreadChunks,
},
],
)
.end()
})
},
)
},
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ export interface ExternalBundleWebpackPluginOptions {
* @defaultValue '3.5'
*/
engineVersion?: string | undefined

/**
* The main thread chunks of the external bundle.
*
* @defaultValue []
*/
mainThreadChunks?: string[] | undefined
}

const isDebug = (): boolean => {
Expand Down Expand Up @@ -128,6 +135,11 @@ export class ExternalBundleWebpackPlugin {
return ({
...prev,
[cur.name.replace(/\.js$/, '')]: {
...(this.options.mainThreadChunks?.includes(cur.name)
? {
'encoding': 'JsBytecode',
}
: {}),
Comment thread
upupming marked this conversation as resolved.
content: cur.source.source().toString(),
},
})
Expand All @@ -154,6 +166,7 @@ export class ExternalBundleWebpackPlugin {

const compilerOptions: Record<string, unknown> = {
enableFiberArch: true,
useLepusNG: true,
// `lynx.fetchBundle` and `lynx.loadScript` require engineVersion >= 3.5
targetSdkVersion: this.options.engineVersion ?? '3.5',
enableCSSInvalidation: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
const decodedResult = await decodeTemplate(
path.join(fixtureDir, 'dist/utils-dual.lynx.bundle'),
)
expect(Object.keys(decodedResult['custom-sections']).sort()).toEqual([

Check failure on line 123 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Ubuntu) / check

test/external-bundle.test.ts > should build external bundle > should build both main-thread and background code into external bundle

AssertionError: expected [ 'utils' ] to deeply equal [ 'utils', 'utils__main-thread' ] - Expected + Received [ "utils", - "utils__main-thread", ] ❯ test/external-bundle.test.ts:123:66

Check failure on line 123 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Windows) / check

test/external-bundle.test.ts > should build external bundle > should build both main-thread and background code into external bundle

AssertionError: expected [ 'utils' ] to deeply equal [ 'utils', 'utils__main-thread' ] - Expected + Received [ "utils", - "utils__main-thread", ] ❯ test/external-bundle.test.ts:123:66
'utils',
'utils__main-thread',
])
Expand Down Expand Up @@ -150,7 +150,7 @@
const decodedResult = await decodeTemplate(
path.join(fixtureDir, 'dist/utils-m.lynx.bundle'),
)
expect(Object.keys(decodedResult['custom-sections'])).toEqual([

Check failure on line 153 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Ubuntu) / check

test/external-bundle.test.ts > should build external bundle > should only build main-thread code into external bundle

AssertionError: expected [] to deeply equal [ 'utils' ] - Expected + Received - [ - "utils", - ] + [] ❯ test/external-bundle.test.ts:153:59

Check failure on line 153 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Windows) / check

test/external-bundle.test.ts > should build external bundle > should only build main-thread code into external bundle

AssertionError: expected [] to deeply equal [ 'utils' ] - Expected + Received - [ - "utils", - ] + [] ❯ test/external-bundle.test.ts:153:59
'utils',
])
expect(decodedResult['custom-sections']['utils']?.includes('.define('))
Expand Down Expand Up @@ -238,11 +238,27 @@
)

// Check custom-sections for CSS keys
expect(Object.keys(decodedResult['custom-sections']).sort()).toEqual([

Check failure on line 241 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Ubuntu) / check

test/external-bundle.test.ts > should build external bundle > should build css into external bundle

AssertionError: expected [ 'index', 'index:CSS' ] to deeply equal [ 'index', 'index:CSS', …(1) ] - Expected + Received [ "index", "index:CSS", - "index__main-thread", ] ❯ test/external-bundle.test.ts:241:66

Check failure on line 241 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Windows) / check

test/external-bundle.test.ts > should build external bundle > should build css into external bundle

AssertionError: expected [ 'index', 'index:CSS' ] to deeply equal [ 'index', 'index:CSS', …(1) ] - Expected + Received [ "index", "index:CSS", - "index__main-thread", ] ❯ test/external-bundle.test.ts:241:66
'index',
'index:CSS',
'index__main-thread',
])

expect(Array.isArray(decodedResult['custom-sections']['index:CSS'])).toBe(
true,
)
expect(decodedResult['custom-sections']['index:CSS']![0]).toBeTypeOf(
'number',
)

expect(decodedResult['custom-sections']['index']).toBeTypeOf('string')

// MTS should be bytecode
expect(
Array.isArray(decodedResult['custom-sections']['index__main-thread']),
).toBe(true)
expect(decodedResult['custom-sections']['index__main-thread']![0])
.toBeTypeOf('number')
})

it('should include LoadingConsumerModulesRuntimeModule in the main-thread bundle', async () => {
Expand Down Expand Up @@ -270,7 +286,7 @@
)

// Check if the runtime module code injected by LoadingConsumerModulesRuntimeModule is present
expect(decodedResult['custom-sections']['utils__main-thread']).toContain(

Check failure on line 289 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Ubuntu) / check

test/external-bundle.test.ts > should build external bundle > should include LoadingConsumerModulesRuntimeModule in the main-thread bundle

AssertionError: the given combination of arguments (undefined and string) is invalid for this assertion. You can use an array, a map, an object, a set, a string, or a weakset instead of a string ❯ test/external-bundle.test.ts:289:68

Check failure on line 289 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Windows) / check

test/external-bundle.test.ts > should build external bundle > should include LoadingConsumerModulesRuntimeModule in the main-thread bundle

AssertionError: the given combination of arguments (undefined and string) is invalid for this assertion. You can use an array, a map, an object, a set, a string, or a weakset instead of a string ❯ test/external-bundle.test.ts:289:68
'var globalModules = globalThis[Symbol.for(\'__LYNX_WEBPACK_MODULES__\')];',
)
vi.unstubAllEnvs()
Expand Down Expand Up @@ -316,7 +332,7 @@
const prodMainThread = prodResult['custom-sections']['utils__main-thread']!

// The produced artifacts should be different
expect(devMainThread).not.toBe(prodMainThread)

Check failure on line 335 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Ubuntu) / check

test/external-bundle.test.ts > NODE_ENV configuration > should output different artifacts for development and production NODE_ENV

AssertionError: expected undefined not to be undefined // Object.is equality ❯ test/external-bundle.test.ts:335:31

Check failure on line 335 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Windows) / check

test/external-bundle.test.ts > NODE_ENV configuration > should output different artifacts for development and production NODE_ENV

AssertionError: expected undefined not to be undefined // Object.is equality ❯ test/external-bundle.test.ts:335:31

// __DEV__ macro should be replaced differently
expect(devMainThread).toMatch(/isDev:\s*(!0|true)/)
Expand Down Expand Up @@ -401,7 +417,7 @@
const decodedResult = await decodeTemplate(
path.join(fixtureDir, 'dist/utils-reactlynx.lynx.bundle'),
)
expect(Object.keys(decodedResult['custom-sections']).sort()).toEqual([

Check failure on line 420 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Ubuntu) / check

test/external-bundle.test.ts > mount externals library > should mount externals library to lynx by default

AssertionError: expected [ 'utils' ] to deeply equal [ 'utils', 'utils__main-thread' ] - Expected + Received [ "utils", - "utils__main-thread", ] ❯ test/external-bundle.test.ts:420:66

Check failure on line 420 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Windows) / check

test/external-bundle.test.ts > mount externals library > should mount externals library to lynx by default

AssertionError: expected [ 'utils' ] to deeply equal [ 'utils', 'utils__main-thread' ] - Expected + Received [ "utils", - "utils__main-thread", ] ❯ test/external-bundle.test.ts:420:66
'utils',
'utils__main-thread',
])
Expand Down Expand Up @@ -455,7 +471,7 @@
'dist/utils-reactlynx-preset.lynx.bundle',
),
)
expect(Object.keys(decodedResult['custom-sections']).sort()).toEqual([

Check failure on line 474 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Ubuntu) / check

test/external-bundle.test.ts > mount externals library > should apply reactlynx externals preset to the final bundle

AssertionError: expected [ 'utils' ] to deeply equal [ 'utils', 'utils__main-thread' ] - Expected + Received [ "utils", - "utils__main-thread", ] ❯ test/external-bundle.test.ts:474:66

Check failure on line 474 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Windows) / check

test/external-bundle.test.ts > mount externals library > should apply reactlynx externals preset to the final bundle

AssertionError: expected [ 'utils' ] to deeply equal [ 'utils', 'utils__main-thread' ] - Expected + Received [ "utils", - "utils__main-thread", ] ❯ test/external-bundle.test.ts:474:66
'utils',
'utils__main-thread',
])
Expand Down Expand Up @@ -502,7 +518,7 @@
expect(decodedResult['custom-sections']['utils']).toContain(
'globalThis[Symbol.for("__LYNX_EXTERNAL_GLOBAL__")].CustomRuntime.React',
)
expect(decodedResult['custom-sections']['utils__main-thread']).toContain(

Check failure on line 521 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Ubuntu) / check

test/external-bundle.test.ts > mount externals library > should let explicit externals override the reactlynx preset

AssertionError: the given combination of arguments (undefined and string) is invalid for this assertion. You can use an array, a map, an object, a set, a string, or a weakset instead of a string ❯ test/external-bundle.test.ts:521:68

Check failure on line 521 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Windows) / check

test/external-bundle.test.ts > mount externals library > should let explicit externals override the reactlynx preset

AssertionError: the given combination of arguments (undefined and string) is invalid for this assertion. You can use an array, a map, an object, a set, a string, or a weakset instead of a string ❯ test/external-bundle.test.ts:521:68
'globalThis[Symbol.for("__LYNX_EXTERNAL_GLOBAL__")].CustomRuntime.React',
)
expect(decodedResult['custom-sections']['utils']).not.toContain(
Expand Down Expand Up @@ -627,7 +643,7 @@
'dist/utils-reactlynx-globalThis.lynx.bundle',
),
)
expect(Object.keys(decodedResult['custom-sections']).sort()).toEqual([

Check failure on line 646 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Ubuntu) / check

test/external-bundle.test.ts > mount externals library > should mount externals library to globalThis

AssertionError: expected [ 'utils' ] to deeply equal [ 'utils', 'utils__main-thread' ] - Expected + Received [ "utils", - "utils__main-thread", ] ❯ test/external-bundle.test.ts:646:66

Check failure on line 646 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Windows) / check

test/external-bundle.test.ts > mount externals library > should mount externals library to globalThis

AssertionError: expected [ 'utils' ] to deeply equal [ 'utils', 'utils__main-thread' ] - Expected + Received [ "utils", - "utils__main-thread", ] ❯ test/external-bundle.test.ts:646:66
'utils',
'utils__main-thread',
])
Expand Down Expand Up @@ -721,7 +737,7 @@
})

it('should handle macros', () => {
expect(Object.keys(decodedResult['custom-sections']).sort()).toEqual([

Check failure on line 740 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Ubuntu) / check

test/external-bundle.test.ts > pluginReactLynx > should handle macros

AssertionError: expected [ 'utils' ] to deeply equal [ 'utils', 'utils__main-thread' ] - Expected + Received [ "utils", - "utils__main-thread", ] ❯ test/external-bundle.test.ts:740:66

Check failure on line 740 in packages/rspeedy/lynx-bundle-rslib-config/test/external-bundle.test.ts

View workflow job for this annotation

GitHub Actions / Vitest (Windows) / check

test/external-bundle.test.ts > pluginReactLynx > should handle macros

AssertionError: expected [ 'utils' ] to deeply equal [ 'utils', 'utils__main-thread' ] - Expected + Received [ "utils", - "utils__main-thread", ] ❯ test/external-bundle.test.ts:740:66
'utils',
'utils__main-thread',
])
Expand Down
Loading