@lynx-js/external-bundle-rsbuild-plugin 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/lib/index.d.ts +23 -0
- package/lib/index.js +47 -25
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @lynx-js/external-bundle-rsbuild-plugin
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- The `reactlynx` externals preset accepts `{ async: true }`, mounting ReactLynx as an awaited promise so async runtimes can load it via `fetchBundle().then` (the sync array form reads `React.memo` etc. off a pending promise and gets `undefined`). Externals presets resolve per environment (`environmentName` is available in the preset context): `lynx` / `lynx-*` environments use `react.lynx.bundle`, other environments (e.g. `web`) use the web-encoded `@lynx-js/react-umd/{dev,prod}-web` `react.web.bundle` — `async` only controls the mount form. ([#2934](https://github.com/lynx-family/lynx-stack/pull/2934))
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`34318ea`](https://github.com/lynx-family/lynx-stack/commit/34318ea3432b6484a383707458ed9c4ee19e2097)]:
|
|
12
|
+
- @lynx-js/externals-loading-webpack-plugin@0.2.1
|
|
13
|
+
|
|
3
14
|
## 0.3.0
|
|
4
15
|
|
|
5
16
|
### Minor Changes
|
package/lib/index.d.ts
CHANGED
|
@@ -28,6 +28,19 @@ export interface ReactLynxExternalsPresetOptions {
|
|
|
28
28
|
* @defaultValue `'@lynx-js/react-umd'`
|
|
29
29
|
*/
|
|
30
30
|
reactUmdPackageName?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Load the ReactLynx runtime bundle asynchronously, for the web target.
|
|
33
|
+
*
|
|
34
|
+
* The web runtime (`@lynx-js/web-core`) can only fetch external bundles
|
|
35
|
+
* asynchronously (`fetchBundle().then`), so ReactLynx must be mounted as a
|
|
36
|
+
* promise that consuming modules await before reading a subpath (otherwise
|
|
37
|
+
* `React.memo` etc. are read off a pending promise and are `undefined`).
|
|
38
|
+
* Enabling this also resolves the web-encoded `@lynx-js/react-umd/{dev,prod}-web`
|
|
39
|
+
* bundle and defaults `bundlePath` to `react.web.bundle`.
|
|
40
|
+
*
|
|
41
|
+
* @defaultValue `false`
|
|
42
|
+
*/
|
|
43
|
+
async?: boolean;
|
|
31
44
|
/**
|
|
32
45
|
* Override the runtime bundle URL directly.
|
|
33
46
|
*
|
|
@@ -65,6 +78,16 @@ export interface ExternalsPresetContext {
|
|
|
65
78
|
* The current Rsbuild project root path.
|
|
66
79
|
*/
|
|
67
80
|
rootPath: string;
|
|
81
|
+
/**
|
|
82
|
+
* The Rsbuild environment being resolved (e.g. `'lynx'`, `'web'`).
|
|
83
|
+
*
|
|
84
|
+
* @remarks
|
|
85
|
+
*
|
|
86
|
+
* Presets use this to pick environment-specific artifacts — for example the
|
|
87
|
+
* built-in `reactlynx` preset resolves the web-encoded `react.web.bundle`
|
|
88
|
+
* for the `web` environment and `react.lynx.bundle` otherwise.
|
|
89
|
+
*/
|
|
90
|
+
environmentName?: string;
|
|
68
91
|
}
|
|
69
92
|
/**
|
|
70
93
|
* Definition for a named externals preset.
|
package/lib/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import { ExternalsLoadingPlugin } from '@lynx-js/externals-loading-webpack-plugi
|
|
|
13
13
|
const require = createRequire(import.meta.url);
|
|
14
14
|
const DEFAULT_REACT_UMD_PACKAGE_NAME = '@lynx-js/react-umd';
|
|
15
15
|
const REACT_LYNX_BUNDLE_FILE_NAME = 'react.lynx.bundle';
|
|
16
|
+
const REACT_LYNX_WEB_BUNDLE_FILE_NAME = 'react.web.bundle';
|
|
16
17
|
const reactLynxExternalTemplate = {
|
|
17
18
|
'react': {
|
|
18
19
|
libraryName: ['ReactLynx', 'React'],
|
|
@@ -125,28 +126,39 @@ export function normalizeBundlePath(bundlePath) {
|
|
|
125
126
|
function createBuiltInExternalsPresetDefinitions() {
|
|
126
127
|
return {
|
|
127
128
|
reactlynx: {
|
|
128
|
-
resolveExternals(value) {
|
|
129
|
-
return createReactLynxExternals(normalizeReactLynxPreset(value));
|
|
129
|
+
resolveExternals(value, context) {
|
|
130
|
+
return createReactLynxExternals(normalizeReactLynxPreset(value), isWebEnvironment(context));
|
|
130
131
|
},
|
|
131
132
|
resolveManagedAssets(value, context) {
|
|
132
133
|
const preset = normalizeReactLynxPreset(value);
|
|
133
134
|
if (!preset || preset.url) {
|
|
134
135
|
return new Map();
|
|
135
136
|
}
|
|
137
|
+
const isWeb = isWebEnvironment(context);
|
|
136
138
|
return new Map([
|
|
137
139
|
[
|
|
138
|
-
getDefaultReactLynxBundlePath(preset),
|
|
139
|
-
getReactLynxBundlePath(context.rootPath, preset.reactUmdPackageName ?? DEFAULT_REACT_UMD_PACKAGE_NAME),
|
|
140
|
+
getDefaultReactLynxBundlePath(preset, isWeb),
|
|
141
|
+
getReactLynxBundlePath(context.rootPath, preset.reactUmdPackageName ?? DEFAULT_REACT_UMD_PACKAGE_NAME, isWeb),
|
|
140
142
|
],
|
|
141
143
|
]);
|
|
142
144
|
},
|
|
143
145
|
},
|
|
144
146
|
};
|
|
145
147
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
// The bundle encoding follows the target environment: `lynx` / `lynx-*`
|
|
149
|
+
// environments decode `tasm` bundles (mirroring rspeedy's `isLynx`
|
|
150
|
+
// convention), every other environment (e.g. `web`) decodes web-encoded
|
|
151
|
+
// bundles. `async` only controls how the external is mounted.
|
|
152
|
+
function isWebEnvironment(context) {
|
|
153
|
+
const name = context.environmentName;
|
|
154
|
+
if (name === undefined) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
return name !== 'lynx' && !name.startsWith('lynx-');
|
|
158
|
+
}
|
|
159
|
+
function getReactLynxBundlePath(rootPath, reactUmdPackageName, isWeb) {
|
|
160
|
+
const variant = process.env['NODE_ENV'] === 'production' ? 'prod' : 'dev';
|
|
161
|
+
const reactUmdExport = `${reactUmdPackageName}/${variant}${isWeb ? '-web' : ''}`;
|
|
150
162
|
try {
|
|
151
163
|
return require.resolve(reactUmdExport, { paths: [rootPath] });
|
|
152
164
|
}
|
|
@@ -238,14 +250,15 @@ function resolvePresetExternals(externalsPresets, presetDefinitions, context) {
|
|
|
238
250
|
}
|
|
239
251
|
return { externals, managedAssets };
|
|
240
252
|
}
|
|
241
|
-
function createReactLynxExternals(preset) {
|
|
253
|
+
function createReactLynxExternals(preset, isWeb) {
|
|
242
254
|
const bundleReference = preset?.url
|
|
243
255
|
? { url: preset.url }
|
|
244
|
-
: { bundlePath: getDefaultReactLynxBundlePath(preset) };
|
|
256
|
+
: { bundlePath: getDefaultReactLynxBundlePath(preset, isWeb) };
|
|
245
257
|
return Object.fromEntries(Object.entries(reactLynxExternalTemplate).map(([request, external]) => [
|
|
246
258
|
request,
|
|
247
259
|
{
|
|
248
260
|
...external,
|
|
261
|
+
...(preset?.async === undefined ? {} : { async: preset.async }),
|
|
249
262
|
...bundleReference,
|
|
250
263
|
},
|
|
251
264
|
]));
|
|
@@ -278,8 +291,13 @@ class EmitManagedBundleAssetsPlugin {
|
|
|
278
291
|
});
|
|
279
292
|
}
|
|
280
293
|
}
|
|
281
|
-
function getDefaultReactLynxBundlePath(preset) {
|
|
282
|
-
|
|
294
|
+
function getDefaultReactLynxBundlePath(preset, isWeb) {
|
|
295
|
+
if (preset?.bundlePath) {
|
|
296
|
+
return normalizeBundlePath(preset.bundlePath);
|
|
297
|
+
}
|
|
298
|
+
return isWeb
|
|
299
|
+
? REACT_LYNX_WEB_BUNDLE_FILE_NAME
|
|
300
|
+
: REACT_LYNX_BUNDLE_FILE_NAME;
|
|
283
301
|
}
|
|
284
302
|
function joinUrlPath(base, bundlePath) {
|
|
285
303
|
const normalizedBase = base ?? '/';
|
|
@@ -312,13 +330,6 @@ function getManagedBundleAssets(options, presetManagedAssets, api) {
|
|
|
312
330
|
}
|
|
313
331
|
return assets;
|
|
314
332
|
}
|
|
315
|
-
function getLocalBundleAssets(options, presetManagedAssets, api, serverBase) {
|
|
316
|
-
const assets = new Map();
|
|
317
|
-
for (const [bundlePath, sourcePath] of getManagedBundleAssets(options, presetManagedAssets, api)) {
|
|
318
|
-
assets.set(joinUrlPath(serverBase, bundlePath), sourcePath);
|
|
319
|
-
}
|
|
320
|
-
return assets;
|
|
321
|
-
}
|
|
322
333
|
function resolvePluginExternals(externals) {
|
|
323
334
|
if (!externals) {
|
|
324
335
|
return {};
|
|
@@ -386,12 +397,16 @@ export function pluginExternalBundle(options) {
|
|
|
386
397
|
name: 'lynx:external-bundle',
|
|
387
398
|
setup(api) {
|
|
388
399
|
const presetDefinitions = resolvePresetDefinitions(options.externalsPresetDefinitions);
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
400
|
+
// Presets resolve per environment (in `modifyRspackConfig`, where the
|
|
401
|
+
// environment name is known); this map collects every environment's
|
|
402
|
+
// local bundle assets for the dev-server middleware, which reads it at
|
|
403
|
+
// request time.
|
|
404
|
+
const localBundleAssets = new Map();
|
|
405
|
+
let serverBase;
|
|
392
406
|
api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => {
|
|
393
|
-
|
|
394
|
-
if (
|
|
407
|
+
serverBase = config.server?.base;
|
|
408
|
+
if (options.externals === undefined
|
|
409
|
+
&& options.externalsPresets === undefined) {
|
|
395
410
|
return config;
|
|
396
411
|
}
|
|
397
412
|
return mergeRsbuildConfig(config, {
|
|
@@ -423,17 +438,24 @@ export function pluginExternalBundle(options) {
|
|
|
423
438
|
},
|
|
424
439
|
});
|
|
425
440
|
});
|
|
426
|
-
api.modifyRspackConfig((config) => {
|
|
441
|
+
api.modifyRspackConfig((config, { environment }) => {
|
|
427
442
|
const LAYERS = api.useExposed(Symbol.for('LAYERS'));
|
|
428
443
|
if (!LAYERS) {
|
|
429
444
|
throw new Error('external-bundle-rsbuild-plugin requires exposed `LAYERS`. Please install a DSL plugin, for example `pluginReactLynx` for ReactLynx.');
|
|
430
445
|
}
|
|
446
|
+
const presetResolution = resolvePresetExternals(options.externalsPresets, presetDefinitions, {
|
|
447
|
+
rootPath: api.context.rootPath,
|
|
448
|
+
environmentName: environment.name,
|
|
449
|
+
});
|
|
431
450
|
const explicitExternals = resolvePluginExternals(options.externals);
|
|
432
451
|
const externals = {
|
|
433
452
|
...presetResolution.externals,
|
|
434
453
|
...explicitExternals,
|
|
435
454
|
};
|
|
436
455
|
const managedBundleAssets = getManagedBundleAssets(options, presetResolution.managedAssets, api);
|
|
456
|
+
for (const [bundlePath, sourcePath] of managedBundleAssets) {
|
|
457
|
+
localBundleAssets.set(joinUrlPath(serverBase, bundlePath), sourcePath);
|
|
458
|
+
}
|
|
437
459
|
config.plugins = config.plugins || [];
|
|
438
460
|
if (managedBundleAssets.size > 0) {
|
|
439
461
|
config.plugins.push(new EmitManagedBundleAssetsPlugin(managedBundleAssets));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynx-js/external-bundle-rsbuild-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "An rsbuild plugin for loading lynx external bundles.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rsbuild",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"README.md"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@lynx-js/externals-loading-webpack-plugin": "0.2.
|
|
37
|
+
"@lynx-js/externals-loading-webpack-plugin": "0.2.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@microsoft/api-extractor": "7.58.2",
|
|
41
|
-
"@rsbuild/core": "2.
|
|
42
|
-
"@lynx-js/react-umd": "0.
|
|
41
|
+
"@rsbuild/core": "2.1.4",
|
|
42
|
+
"@lynx-js/react-umd": "0.123.0"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=18"
|