External Bundle
3.5
Info
Loading CSS files from an External Bundle requires Lynx 3.7 or later.
External Bundle lets you build a Lynx bundle once and load it from multiple Lynx apps at runtime. Use it when you want to share ReactLynx components or common business bundles across apps.
Compared with Chunk Splitting, External Bundle is for cross-application reuse, while Chunk Splitting is for splitting code inside one app.
This workflow has two parts:
- Use
@lynx-js/lynx-bundle-rslib-config to build the external bundle.
- Use
@lynx-js/external-bundle-rsbuild-plugin to load it in the host app.
Install
npm install @lynx-js/lynx-bundle-rslib-config @lynx-js/external-bundle-rsbuild-plugin @lynx-js/react-umd @rslib/core -D
yarn add @lynx-js/lynx-bundle-rslib-config @lynx-js/external-bundle-rsbuild-plugin @lynx-js/react-umd @rslib/core -D
pnpm add @lynx-js/lynx-bundle-rslib-config @lynx-js/external-bundle-rsbuild-plugin @lynx-js/react-umd @rslib/core -D
bun add @lynx-js/lynx-bundle-rslib-config @lynx-js/external-bundle-rsbuild-plugin @lynx-js/react-umd @rslib/core -D
deno add npm:@lynx-js/lynx-bundle-rslib-config npm:@lynx-js/external-bundle-rsbuild-plugin npm:@lynx-js/react-umd npm:@rslib/core -D
Build An External Bundle
For a ReactLynx component bundle, the recommended setup is:
rslib-comp-lib.config.ts
import { defineExternalBundleRslibConfig } from '@lynx-js/lynx-bundle-rslib-config';
import { pluginReactLynx } from '@lynx-js/react-rsbuild-plugin';
export default defineExternalBundleRslibConfig({
id: 'comp-lib',
source: {
entry: {
'./App.js': './external-bundle/CompLib.tsx',
},
},
plugins: [pluginReactLynx()],
output: {
externalsPresets: {
reactlynx: true,
},
},
});
externalsPresets.reactlynx maps the standard ReactLynx requests for you, so a ReactLynx component bundle can depend on the shared runtime directly.
Run the build with:
npm exec rslib build --config rslib-comp-lib.config.ts
yarn exec rslib build --config rslib-comp-lib.config.ts
pnpm exec rslib build --config rslib-comp-lib.config.ts
bun exec rslib build --config rslib-comp-lib.config.ts
deno exec npm:rslib npm:build --config npm:rslib-comp-lib.config.ts
Load It In The Host App
Use the same request key in the app:
lynx.config.ts
import { pluginExternalBundle } from '@lynx-js/external-bundle-rsbuild-plugin';
import { pluginQRCode } from '@lynx-js/qrcode-rsbuild-plugin';
import { pluginReactLynx } from '@lynx-js/react-rsbuild-plugin';
import { defineConfig } from '@lynx-js/rspeedy';
export default defineConfig({
plugins: [
pluginReactLynx(),
pluginQRCode(),
pluginExternalBundle({
externalsPresets: {
reactlynx: true,
},
externals: {
'./App.js': 'comp-lib.lynx.bundle',
},
}),
],
});
This shorthand is equivalent to the following expanded config:
externals: {
'./App.js': {
bundlePath: 'comp-lib.lynx.bundle',
libraryName: './App.js',
background: { sectionPath: './App.js' },
mainThread: { sectionPath: './App.js__main-thread' },
async: true,
},
}
If your section names already match the request key, this is the smallest recommended setup.
When To Set globalObject
In most projects, you can omit globalObject.
Set globalObject: 'globalThis' only when your app enables a shared globalThis across background-thread runtimes and you want later bundles to reuse externals that have already been loaded there.
Use it on both sides when needed:
rslib-comp-lib.config.ts
output: {
externalsPresets: {
reactlynx: true,
},
globalObject: 'globalThis',
}
lynx.config.ts
pluginExternalBundle({
externalsPresets: {
reactlynx: true,
},
externals: {
'./App.js': 'comp-lib.lynx.bundle',
},
globalObject: 'globalThis',
});
Why @lynx-js/react-umd Is Needed
@lynx-js/react-umd ships the prebuilt ReactLynx runtime bundles used by the built-in reactlynx preset.
When you enable externalsPresets.reactlynx in pluginExternalBundle(), the plugin will automatically resolve @lynx-js/react-umd/dev or @lynx-js/react-umd/prod based on NODE_ENV, emit react.lynx.bundle, and load it through the current runtime public path.
For most projects, this means:
- install
@lynx-js/react-umd
- enable
reactlynx
- let the preset provide the ReactLynx runtime mapping
Extend Presets
Use the same preset name on both sides so the bundle build and the host app stay aligned.
From The Library Side
On the external bundle build side, presets live in output.externalsPresets and output.externalsPresetDefinitions:
rslib-comp-lib.config.ts
import { defineExternalBundleRslibConfig } from '@lynx-js/lynx-bundle-rslib-config';
export default defineExternalBundleRslibConfig({
output: {
externalsPresets: {
reactlynxPlus: true,
},
externalsPresetDefinitions: {
reactlynxPlus: {
extends: 'reactlynx',
externals: {
'@lynx-js/lynx-ui': ['LynxUI', 'UI'],
},
},
},
},
});
This side decides how imports are mapped to external globals when the bundle is built.
From The Lynx Page Side
On the host app side, presets live in pluginExternalBundle({ externalsPresets, externalsPresetDefinitions }):
lynx.config.ts
import { pluginExternalBundle } from '@lynx-js/external-bundle-rsbuild-plugin';
pluginExternalBundle({
externalsPresets: {
reactlynxPlus: true,
},
externalsPresetDefinitions: {
reactlynxPlus: {
extends: 'reactlynx',
resolveExternals() {
return {
'@lynx-js/lynx-ui': {
libraryName: ['LynxUI', 'UI'],
bundlePath: 'lynx-ui.lynx.bundle',
background: { sectionPath: 'LynxUI' },
mainThread: { sectionPath: 'LynxUI__main-thread' },
async: false,
},
};
},
},
},
});
This side decides where the bundle is loaded from and which section names the runtime should request.
Explicit externals still override mappings provided by presets. Use that when a single app needs a different bundle path or section name.
Use the full object form when you need custom section names, custom exported library names, timeouts, or a dedicated local bundle directory.
The external-bundle example in lynx-examples uses that style:
lynx.config.mjs
pluginExternalBundle({
externalBundleRoot: 'dist-external-bundle',
externalsPresets: {
reactlynx: true,
},
externals: {
'lodash-es': {
bundlePath: 'lodash-es.lynx.bundle',
background: { sectionPath: 'lodash-es' },
mainThread: { sectionPath: 'lodash-es__main-thread' },
async: false,
timeout: 10000,
},
'./components': {
bundlePath: 'comp.lynx.bundle',
background: { sectionPath: 'component' },
mainThread: { sectionPath: 'component__main-thread' },
async: true,
timeout: 5000,
},
},
timeout: 10000,
});
Use this form when:
- one bundle contains multiple business modules
- section names do not match the request key
- bundles are built into
dist-external-bundle
- you want per-bundle timeout or loading behavior
Example
The lynx-examples external-bundle example is available directly in the docs:
API Reference