Skip to content

feat(react): fetchBundle-based lazy bundle loader#2584

Draft
upupming wants to merge 47 commits into
mainfrom
feat/lazy-bundle-with-fetchBundle
Draft

feat(react): fetchBundle-based lazy bundle loader#2584
upupming wants to merge 47 commits into
mainfrom
feat/lazy-bundle-with-fetchBundle

Conversation

@upupming
Copy link
Copy Markdown
Collaborator

@upupming upupming commented May 8, 2026

Summary

Add a lynx.fetchBundle-based lazy bundle loader as an opt-in alternative to lynx.QueryComponent. Enables true async loading and per-import sync/async hints.

Opt in by setting engineVersion: '3.8' (or higher) in pluginReactLynx. Then:

lazy(() => import('./X', { with: { mode: 'sync' } }))   // first-screen blocking
lazy(() => import('./X', { with: { mode: 'async' } }))  // BG fetch + coordinated MT prep

mode is FetchBundle-only — using it under QueryComponent throws in __DEV__.

Output shape

Lazy bundle ships as customSections: main-thread (bytecoded by default; skipped in dev / DEBUG=rspeedy) + background + CSS, plus a manifest of remaining BTS chunks.

Cross-thread coordination

For async mode, BG calls callLepusMethod('rLynxPrepareLazyBundleMTS') inside its own fetchBundle.then. Because the bundle is already in native cache, MT's .then fires synchronously, the C++ Call returns sync, and BG's cb only fires after MT snapshots are registered — so any patch BG sends next lands safely.

Test plan

  • @lynx-js/react runtime — 19/19 lazy-bundle tests
  • @lynx-js/template-webpack-plugin — 344/344
  • @lynx-js/react-rsbuild-plugin — 161/161
  • @lynx-js/react-transform — 73 (vitest) + 22 (cargo)
  • On-device end-to-end (LynxExplorer 3.8+)

Summary by CodeRabbit

  • New Features

    • Added lazy bundle loading using lynx.fetchBundle as an alternative to the existing approach, controlled via engineVersion: '3.8'.
    • Enabled synchronous and asynchronous import modes for lazy components via import('./X', { with: { mode: 'sync' | 'async' } }).
    • Added withLazyBundleMode helper for runtime mode control.
  • Chores

    • Updated @lynx-js/types to 3.10.2-alpha.0 across packages.

Review Change Stack

upupming added 5 commits May 8, 2026 15:17
…ode attr

Recognize `with: { mode: ... }` on dynamic import and rewrite as
`withLazyBundleMode(mode, () => import(...))`. The runtime symbol is
imported from `@lynx-js/react/internal` only when the wrapper is
actually emitted, gated via Lazy::get to avoid spurious imports.
Introduce `withLazyBundleMode(mode, factory)` to temporarily set the
lazy bundle import mode via a Symbol on `lynx`, restoring the prior
value after the factory returns. Wire `__dynamicImport` to read
`mode` from `with` (matching what the SWC plugin forwards) and wrap
component-type loads accordingly. Re-export from `react/internal`
and the lazy proxy so consumers can resolve it.
Introduce a `__LAZY_BUNDLE_FETCHER__` define gated by the
`REACT_LAZY_BUNDLE_FETCHER` env var (default `'FetchBundle'`,
overridable to `'QueryComponent'` for the legacy path) and dispatch
`loadLazyBundle` to one of two implementations at module init.

The FetchBundle implementation uses `lynx.fetchBundle` +
`lynx.loadScript`, with the sync/async behavior driven by the
module-local `lazyBundleMode` set via `withLazyBundleMode`.

Pin `@lynx-js/types` to a vendored 3.10.0 tarball — that release
adds the `fetchBundle` / `loadScript` declarations the new code
type-checks against. Existing tests stub the global to
`'QueryComponent'` so they still exercise the legacy path.
…bundles

Restructure lazy-bundle binary output when the FetchBundle fetcher is
selected (default; fall back via REACT_LAZY_BUNDLE_FETCHER=QueryComponent):

- customSections['main-thread'] ← MTS payload, encoding: 'JsBytecode'
                                  (compiled to QuickJS bytecode by the
                                  lepus encoder; first-screen evaluates
                                  bytecode directly)
- customSections['background']  ← first real BTS chunk (entry)
- customSections['CSS']         ← parsed style ruleList, encoding: 'CSS'
- manifest                       ← remaining BTS chunks (vendor / async),
                                   served via lynx.requireModuleAsync
- lepusCode = undefined          ← MTS moved to customSection
- css.cssMap = {}                ← CSS moved to customSection

The legacy /app-service.js loader stub is dropped — under FetchBundle the
platform evaluates the entry chunk directly via loadScript('background'),
so the stub is dead weight.

React runtime side: lazy-bundle.ts MTS path now also calls
__LoadStyleSheet('CSS', url) + __AdoptStyleSheet + __FlushElementTree
after loadScript so the lazy bundle's styles are adopted at first-screen.

Misc:
- WebEncodePlugin: emit empty {} for missing lepusCode (the web encoder's
  encodeStringMap calls Object.entries which throws on undefined).
- types.d.ts: declare __LoadStyleSheet / __AdoptStyleSheet (since 3.7).
- rstest.config.ts: force REACT_LAZY_BUNDLE_FETCHER=QueryComponent inside
  the test process so existing fixtures (which assert legacy lepusCode +
  manifest shape) keep passing. FetchBundle-specific tests should be
  written separately and override this.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 8, 2026

🦋 Changeset detected

Latest commit: 9ea2105

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@lynx-js/react Minor
@lynx-js/react-rsbuild-plugin Minor
@lynx-js/react-webpack-plugin Minor
@lynx-js/template-webpack-plugin Minor
@lynx-js/react-umd Minor
@lynx-js/react-alias-rsbuild-plugin Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a17c9c82-6caf-4abf-b729-2e3cd821bc86

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR implements a FetchBundle-based lazy-bundle loader with sync/async mode control, replacing the legacy QueryComponent fetcher. It adds runtime loading implementations with first-screen blocking control, build-time output splitting into main-thread/background/CSS sections, a lifecycle handler for main-thread preloading, SWC transform support for mode annotations, comprehensive tests, and example applications demonstrating the feature.

Changes

FetchBundle Lazy-Bundle Implementation

Layer / File(s) Summary
Global types, constants, and lifecycle definitions
packages/react/runtime/src/snapshot/lynx/lazyBundleConstants.ts, packages/react/runtime/src/snapshot/lifecycle/constant.ts, packages/react/runtime/types/types.d.ts, packages/react/types/react.docs.d.ts
New constants for section identifiers (main-thread, background, CSS), timeout values, lifecycle event keys, global __LAZY_BUNDLE_FETCHER__ flag (FetchBundle or QueryComponent), and stylesheet API declarations (__LoadStyleSheet, __AdoptStyleSheet, StyleSheet interface).
Runtime lazy-bundle loading with FetchBundle and mode control
packages/react/runtime/src/snapshot/lynx/lazy-bundle.ts
Core loadLazyBundleWithFetchBundle implementation with main-thread sync path (fetch + timeout wait + response validation + load script + CSS adoption + promise .then override), main-thread async fallback (never-resolving), background sync (reject on error), and background async (callback-driven via prepareLazyBundleMTS). Module-scoped lazyBundleMode state manages temporary mode overrides.
Dynamic import with sync/async mode option and internal exports
packages/react/runtime/src/snapshot/lynx/dynamic-js.ts, packages/react/runtime/src/internal.ts, packages/react/runtime/lazy/internal.js
Extended __dynamicImport to accept optional `with.mode: 'sync'
Lifecycle MTS handler for bundle preloading and main-thread injection
packages/react/runtime/src/snapshot/lynx/prepareLazyBundleMTS.ts, packages/react/runtime/src/lynx.ts
New prepareLazyBundleMTS handler fetches bundles, loads main-thread sections via lynx.loadScript, invokes globalThis.processEvalResult factories for side effects, and adopts stylesheets with per-URL caching and silent error handling. Imported and injected into __MAIN_THREAD__ initialization when __LAZY_BUNDLE_FETCHER__ === 'FetchBundle'.
Build-time fetcher resolution and environment configuration
packages/rspeedy/plugin-react/src/resolveLazyBundleFetcher.ts, packages/rspeedy/plugin-react/test/resolveLazyBundleFetcher.test.ts
New resolveLazyBundleFetcher helper selects FetchBundle vs QueryComponent based on semantic version comparison (engineVersion >= 3.8) with REACT_LAZY_BUNDLE_FETCHER environment override support. Includes meetsMinEngineVersion for numeric component-wise version comparison and comprehensive test coverage for defaults and overrides.
Plugin configuration, type definitions, and DefinePlugin wiring
packages/rspeedy/plugin-react/src/entry.ts, packages/webpack/react-webpack-plugin/src/ReactWebpackPlugin.ts, packages/webpack/react-webpack-plugin/etc/react-webpack-plugin.api.md, packages/webpack/template-webpack-plugin/src/LynxTemplatePlugin.ts, packages/webpack/template-webpack-plugin/src/WebEncodePlugin.ts, packages/webpack/template-webpack-plugin/etc/template-webpack-plugin.api.md
resolveLazyBundleFetcher called from rspeedy entry.ts and injected into both ReactWebpackPlugin (via DefinePlugin as __LAZY_BUNDLE_FETCHER__) and LynxTemplatePlugin. ReactWebpackPlugin wrapper logic branches on lazyBundleFetcher: FetchBundle uses self-invoking IIFE; QueryComponent uses parameterized form. LynxTemplatePlugin conditionally splits async output into custom sections (main-thread, background, CSS) for FetchBundle mode. WebEncodePlugin safely handles undefined lepusCode by defaulting to {}. EncodeOptions and LynxTemplatePluginOptions interfaces updated with new optional fields and encoding metadata.
SWC dynamic-import transform with mode support
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs, packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
Extended SWC transform to extract and validate with.mode alongside with.type. Rewrites calls with mode to use withLazyBundleMode(mode, () => import(...)) wrapper form. Conditionally injects @lynx-js/react/internal import for withLazyBundleMode when mode rewriting is used. Updated snapshots with mode variants.
FetchBundle runtime tests with mode and platform branching
packages/react/runtime/__test__/snapshot/lynx/lazy-bundle-fetchbundle.test.js, packages/react/runtime/__test__/snapshot/lynx/lazy-bundle.test.js
Comprehensive Vitest suite validating main-thread sync (fetchBundle → wait → loadScript → CSS adoption), main-thread async (never-resolving), background sync (reject on error/non-zero response), background async (callback-driven with callback readiness ordering), CSS null-safety, dev mode errors when mode is set but using QueryComponent, and withLazyBundleMode helper restoration. Updated legacy tests to stub __LAZY_BUNDLE_FETCHER__ = 'QueryComponent' for QueryComponent code path validation.
PrepareLazyBundleMTS handler tests
packages/react/runtime/__test__/snapshot/lynx/prepareLazyBundleMTS.test.js
Test suite for prepareLazyBundleMTS happy path (fetchBundle → loadScript → processEvalResult → CSS adoption), per-URL caching (second call skips work), no deduping across URLs, and silent error handling for fetch throws, non-zero response codes, loadScript failures, and absent processEvalResult.
Plugin wrapper and template encoding tests
packages/webpack/react-webpack-plugin/test/lazy-bundle-fetcher.test.ts, packages/webpack/react-webpack-plugin/test/fixtures/lazy-bundle-fetcher/index.jsx, packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/, packages/webpack/template-webpack-plugin/test/lazy-bundle-fetcher.test.ts, packages/webpack/template-webpack-plugin/test/web-encode-plugin-fetchbundle.test.ts
New Vitest suites building rspack bundles with FetchBundle and default (QueryComponent) configs, asserting IIFE vs parameterized wrapper forms and __LAZY_BUNDLE_FETCHER__ literal substitution. Template plugin tests verify customSections vs lepusCode output shape and main-thread JsBytecode encoding (production only, not dev/DEBUG=rspeedy). WebEncodePlugin tests validate undefined lepusCode safety and legacy path flattening. Includes test fixtures and rspack configs for both modes.
Configuration and environment variable updates
packages/webpack/template-webpack-plugin/rstest.config.ts, packages/rspeedy/plugin-react/test/config.test.ts, codecov.yml
Updated rstest config with REACT_LAZY_BUNDLE_FETCHER environment variable set to QueryComponent. Updated config snapshot for default plugin options including lazyBundleFetcher. Expanded codecov ignore patterns for examples and snapshot directories.
Example application configurations and demo components
examples/react-lazy-bundle*/lynx.config.*.js, examples/react-lazy-bundle*/src/{App.tsx,LazyComponent*.{tsx,css}}
Updated configs in both examples with LAZY_BUNDLE_FETCHBUNDLE environment toggle, LAN host detection via os.networkInterfaces(), and conditional engineVersion: '3.8' injection into pluginReactLynx. New LazyComponentSync (yellow styling) and LazyComponentAsync (cyan styling) components. App.tsx conditionally loads and renders based on __LAZY_BUNDLE_FETCHER__ with separate Suspense fallbacks per mode.
Example package.json scripts, dependencies, and changeset
examples/react-lazy-bundle*/package.json, .changeset/lazy-bundle-fetch-bundle.md
Added cross-env dependency and new build:fetchbundle, dev:fetchbundle, preview:fetchbundle npm scripts that set LAZY_BUNDLE_FETCHBUNDLE=1. Updated @lynx-js/types to 3.10.2-alpha.0. Changeset documents FetchBundle loader feature, engineVersion 3.8 opt-in, mode syntax support, and bytecode default behavior.
Peer dependency version ranges and API documentation
packages/webpack/*/package.json, packages/webpack/*/etc/*.api.md
Updated peerDependencies to accept template-webpack-plugin ^0.12.0 and react-webpack-plugin ^0.10.0. Added lazyBundleFetcher option documentation in API reports. Made EncodeOptions lepusCode and manifest optional with optional encoding metadata for custom sections.
Monorepo @lynx-js/types version updates
~40 package.json files in benchmark/, examples/, packages/
Systematic version bump of @lynx-js/types from 3.7.0 to 3.10.2-alpha.0 across entire monorepo to support new lazy-bundle typings.

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • Huxpro
  • HuJean
  • Yradex
  • hzy
  • Sherry-hue
  • colinaaa
  • luhc228
  • gaoachao

🐰 Bundles dancing in the sync-async light,
FetchBundle flows make first-screens bright,
With mode controls and CSS in flight,
Lazy components ready—what a delight! ✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/lazy-bundle-with-fetchBundle

…ce.yaml

`pnpm.overrides` in `package.json` and the `overrides:` block in
`pnpm-workspace.yaml` are mutually exclusive — when both exist, pnpm
honors the `package.json` one and silently ignores the workspace one,
which here pins the cataloged `@rspack/core` version. The clash showed
up as `@rspack/core 1.7.9 vs 1.7.11` type-mismatch errors after
`pnpm install`.

Move the local `@lynx-js/types: file:./vendor/...tgz` override into
`pnpm-workspace.yaml` so all overrides live in one place and the
cataloged `@rspack/core` pin keeps working.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

upupming added 6 commits May 8, 2026 22:01
… >= 3.8

Default __LAZY_BUNDLE_FETCHER__ is now derived from the host's
engineVersion: >= 3.8 picks 'FetchBundle', otherwise 'QueryComponent'.
The REACT_LAZY_BUNDLE_FETCHER env var still forces a specific fetcher,
but forcing 'FetchBundle' on engineVersion < 3.8 now throws a build
error (the platform doesn't expose lynx.fetchBundle on those hosts).

Plumbs engineVersion through pluginReactLynx -> entry.ts -> ReactWebpackPlugin.
CI failures from the previous push:
- code-style-check (api-extractor): the new 'engineVersion' field on
  ReactWebpackPluginOptions wasn't reflected in etc/*.api.md.
- sherif (pnpm dedupe --check): @rspack/core had 2.0.0-beta.X variants
  mixed with the cataloged 1.7.9. The repl build failure was a knock-on
  effect of that resolution drift.

Re-running api-extractor + pnpm dedupe fixes both.
CI's clippy runs with RUSTFLAGS=-D warnings, so the unused 'i' from
'attrs.iter().enumerate()' was rejected. The index isn't read inside
the loop — drop the enumerate.
The local task config dropped the root's '^build' when overriding
'dependsOn' to add 'build:wasm'. As a result web-core's build can race
ahead of its workspace deps' builds — on a fresh CI checkout, when
@lynx-js/web-elements / @lynx-js/web-worker-rpc don't yet have a
'dist/index.js', web-core's rsbuild + rslib produces a partial dist
that downstream consumers (e.g. repl) then fail to bundle ('Module not
found: Can't resolve @lynx-js/web-worker-rpc' / missing
'dist/client/background/index.js').

Adding '^build' restores the workspace-dep ordering. The hash change
also busts the existing poisoned turbo cache.
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 8, 2026

Merging this PR will degrade performance by 26.77%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 79 untouched benchmarks
⏩ 26 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
002-hello-reactLynx-destroyBackground 670.3 µs 915.4 µs -26.77%
008-many-use-state-destroyBackground 9.5 ms 8 ms +19.25%

Comparing feat/lazy-bundle-with-fetchBundle (9ea2105) with main (705a3a3)

Open in CodSpeed

Footnotes

  1. 26 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 8, 2026

React External

#1222 Bundle Size — 693.66KiB (+0.09%).

9ea2105(current) vs 705a3a3 main#1216(baseline)

Bundle metrics  Change 1 change
                 Current
#1222
     Baseline
#1216
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 40.81% 0%
No change  Chunks 0 0
No change  Assets 3 3
No change  Modules 17 17
No change  Duplicate Modules 5 5
No change  Duplicate Code 8.59% 8.59%
No change  Packages 0 0
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#1222
     Baseline
#1216
Regression  Other 693.66KiB (+0.09%) 693.04KiB

Bundle analysis reportBranch feat/lazy-bundle-with-fetchBundl...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 8, 2026

Web Explorer

#9682 Bundle Size — 901.38KiB (0%).

9ea2105(current) vs 705a3a3 main#9676(baseline)

Bundle metrics  Change 1 change
                 Current
#9682
     Baseline
#9676
No change  Initial JS 45.06KiB 45.06KiB
No change  Initial CSS 2.22KiB 2.22KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 9 9
No change  Assets 11 11
Change  Modules 229(+0.44%) 228
No change  Duplicate Modules 11 11
No change  Duplicate Code 27.22% 27.22%
No change  Packages 10 10
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#9682
     Baseline
#9676
No change  JS 497.1KiB 497.1KiB
No change  Other 402.06KiB 402.06KiB
No change  CSS 2.22KiB 2.22KiB

Bundle analysis reportBranch feat/lazy-bundle-with-fetchBundl...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 8, 2026

React MTF Example

#1240 Bundle Size — 207.47KiB (~+0.01%).

9ea2105(current) vs 705a3a3 main#1234(baseline)

Bundle metrics  Change 3 changes
                 Current
#1240
     Baseline
#1234
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 46.38% 0%
No change  Chunks 0 0
No change  Assets 3 3
Change  Modules 193(+0.52%) 192
No change  Duplicate Modules 77 77
Change  Duplicate Code 44.31%(-0.16%) 44.38%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#1240
     Baseline
#1234
No change  IMG 111.23KiB 111.23KiB
Regression  Other 96.24KiB (+0.01%) 96.23KiB

Bundle analysis reportBranch feat/lazy-bundle-with-fetchBundl...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 8, 2026

React Example with Element Template

#375 Bundle Size — 197.79KiB (0%).

9ea2105(current) vs 705a3a3 main#369(baseline)

Bundle metrics  Change 2 changes
                 Current
#375
     Baseline
#369
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 4 4
Change  Modules 79(-1.25%) 80
No change  Duplicate Modules 23 23
Change  Duplicate Code 40.33%(+0.07%) 40.3%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#375
     Baseline
#369
No change  IMG 145.76KiB 145.76KiB
No change  Other 52.03KiB 52.03KiB

Bundle analysis reportBranch feat/lazy-bundle-with-fetchBundl...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 8, 2026

React Example

#8108 Bundle Size — 236.52KiB (~+0.01%).

9ea2105(current) vs 705a3a3 main#8102(baseline)

Bundle metrics  Change 3 changes
                 Current
#8108
     Baseline
#8102
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 38.37% 0%
No change  Chunks 0 0
No change  Assets 4 4
Change  Modules 198(+0.51%) 197
No change  Duplicate Modules 80 80
Change  Duplicate Code 44.8%(-0.16%) 44.87%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#8108
     Baseline
#8102
No change  IMG 145.76KiB 145.76KiB
Regression  Other 90.76KiB (+0.01%) 90.75KiB

Bundle analysis reportBranch feat/lazy-bundle-with-fetchBundl...Project dashboard


Generated by RelativeCIDocumentationReport issue

Comment thread packages/web-platform/web-core/turbo.json
…t options

Picks up `loadScript<T>(sectionName, options?: { bundleName?: string })`
from template-assembler, matching how the FetchBundle path actually calls it.
upupming added a commit that referenced this pull request May 11, 2026
## Summary

`packages/web-platform/web-core`'s turbo `build` task only depended on
its local `build:wasm`, missing `^build`. This caused turbo to start
`web-core`'s TypeScript build before its workspace deps
(`@lynx-js/web-elements`, `@lynx-js/web-worker-rpc`,
`@lynx-js/css-serializer`, ...) had finished building, producing partial
`dist/` output and intermittent CI failures (e.g. `repl` failing to
resolve modules from `web-core/dist`).

Adding `^build` makes turbo wait for upstream workspace builds, matching
the convention used by every other package in the repo.

This was extracted from #2584 where the same fix unblocked Build
(Ubuntu).

## Test plan

- [x] Verified Build (Ubuntu) passes with this change applied on top of
#2584
- [ ] Build (Ubuntu) passes on this PR
- [ ] Build (Windows) passes on this PR

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated build task configuration to improve build process sequencing.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
upupming added 3 commits May 11, 2026 14:15
Hoist `resolveLazyBundleFetcher` into `pluginReactLynx` so the runtime and
the build artifact agree on FetchBundle vs QueryComponent. Both
ReactWebpackPlugin and LynxTemplatePlugin now take the resolved
`lazyBundleFetcher` as a plugin option instead of each computing it (or
defaulting to FetchBundle) on its own.

Without this, a project on the default `targetSdkVersion` (3.2) would
ship a customSections-based lazy bundle that the QueryComponent runtime
path does not understand, and `react-lazy-bundle` crashed at load time.
…undle

The FetchBundle runtime evaluates `customSections['main-thread']` directly,
so the wrapper has to execute itself and bind `globDynamicComponentEntry`
locally. Switch to a self-invoked IIFE with the literal `__Card__` baked in
when `lazyBundleFetcher === 'FetchBundle'`. The QueryComponent path keeps
the existing `(function (globDynamicComponentEntry) { ... })` shape since
its caller still passes the entry name in.
…ples

Both lazy-bundle examples now have `dev:fetchbundle`, `build:fetchbundle`,
`preview:fetchbundle` scripts that flip the resolver to FetchBundle by
bumping engineVersion to 3.8 (gated on `LAZY_BUNDLE_FETCHBUNDLE=1` env).
Lazy imports are switched to `with: { mode: 'sync' }` so the demos
exercise the sync first-screen path. The runtime also now logs the raw
response on FetchBundle load failure to make field debugging easier.
@upupming upupming force-pushed the feat/lazy-bundle-with-fetchBundle branch from fd6bb6f to 2519670 Compare May 11, 2026 10:04
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (1)
packages/webpack/template-webpack-plugin/src/WebEncodePlugin.ts (1)

98-104: 💤 Low value

Non-null assertion on root when type allows undefined.

EncodeOptions.lepusCode.root is declared as string | undefined. The root! assertion will produce lepusCode.root = undefined at runtime when lepusCode is provided but root is absent (e.g., an upstream hook that supplies only lepusChunk), and the downstream encoder may not be resilient to that. Either guard with a conditional spread or treat lepusCode with no root the same as the missing-lepusCode case.

♻️ Suggested defensive shape
-            lepusCode: encodeOptions.lepusCode
-              ? {
-                // flatten the lepusCode to a single object
-                ...encodeOptions.lepusCode.lepusChunk,
-                root: encodeOptions.lepusCode.root!,
-              }
-              : {},
+            lepusCode: encodeOptions.lepusCode
+              ? {
+                ...encodeOptions.lepusCode.lepusChunk,
+                ...(encodeOptions.lepusCode.root !== undefined
+                  ? { root: encodeOptions.lepusCode.root }
+                  : {}),
+              }
+              : {},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/webpack/template-webpack-plugin/src/WebEncodePlugin.ts` around lines
98 - 104, The code uses a non-null assertion on EncodeOptions.lepusCode.root
(encodeOptions.lepusCode.root!) which can produce an undefined root at runtime;
update the lepusCode construction in WebEncodePlugin (the block that spreads
encodeOptions.lepusCode.lepusChunk into lepusCode) to avoid the `!` by only
including root when it's defined (e.g., conditionally spread or add root:
encodeOptions.lepusCode.root only if not undefined), or treat a missing
lepusCode.root the same as the absent lepusCode case and return an empty object
when root is absent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/react-lazy-bundle/lynx.config.js`:
- Around line 10-22: detectLanHost() is being called at module top-level which
causes errors during build; change the code to compute assetPrefix lazily and
allow an explicit override: read LYNX_LAZY_BUNDLE_HOST first and use it if set,
otherwise call detectLanHost() only when needed (e.g., inside dev/preview
startup logic) so builds that don't need LAN resolution won't run the scan; also
robustly parse and validate the port (use a helper like parseInt with a fallback
default 54173, reject empty strings/NaN and clamp to valid port range 1–65535)
and construct assetPrefix only after host and port are validated.

In `@packages/react/runtime/src/snapshot/lynx/lazy-bundle.ts`:
- Around line 165-194: The MT sync path currently calls
__LoadStyleSheet(SECTION_CSS, response.url) and __AdoptStyleSheet(styleSheet)
without protection, so any throw there escapes instead of returning the
never-resolving Promise like other failures; wrap the CSS load/adopt steps in a
try/catch around the calls to __LoadStyleSheet and __AdoptStyleSheet (after
lynx.loadScript/response handling) and on any error return new Promise(() => {})
to match the existing failure behavior used for lynx.fetchBundle and
lynx.loadScript in loadLazyBundle.

In `@packages/react/runtime/src/snapshot/lynx/prepareLazyBundleMTS.ts`:
- Around line 8-47: The current prepareLazyBundleMTS caches the URL before any
work completes, preventing retries on fetch/load failures; remove the early
cache.add(url) and instead call cache.add(url) only after the bundle has been
successfully loaded and applied (i.e., after lynx.loadScript succeeds and after
__AdoptStyleSheet has been called for the CSS), leaving all catch/early-return
paths without caching so failures remain retryable; update references in
prepareLazyBundleMTS around lynx.fetchBundle, lynx.loadScript,
processEvalResult, __LoadStyleSheet and __AdoptStyleSheet accordingly.

In `@packages/rspeedy/plugin-react/src/resolveLazyBundleFetcher.ts`:
- Around line 17-24: The error message constructed for the
REACT_LAZY_BUNDLE_FETCHER check references the wrong config key
("targetSdkVersion"); update the string to mention engineVersion instead. Locate
where FETCH_BUNDLE_MIN_ENGINE_VERSION and REACT_LAZY_BUNDLE_FETCHER are used and
change the phrases on lines that currently say "requires targetSdkVersion" and
"Either bump 'targetSdkVersion' to" so they refer to "engineVersion" (or
"'engineVersion'") and instruct users to bump/unset engineVersion accordingly;
keep the rest of the message (including engineVersion ? `'${engineVersion}'` :
'<unset>') unchanged.

In `@packages/webpack/react-refresh-webpack-plugin/package.json`:
- Line 52: The peer dependency entry "@lynx-js/react-webpack-plugin": "^0.3.0 ||
^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0 || ^0.8.0 || ^0.9.0 || ^0.10.0" references
a non-existent 0.10.0; remove the "|| ^0.10.0" segment from that dependency
string in package.json (or alternatively, if you intend to publish 0.10.0 now,
bump the peer package to include a real 0.10.0 release) so the peerDependencies
list only contains valid released versions.

In `@packages/webpack/react-webpack-plugin/test/lazy-bundle-fetcher.test.ts`:
- Around line 67-73: The Promise created around compiler.run may return early on
error paths without calling compiler.close(), leaking resources; update the
compiler.run callback handling in the test so compiler.close() is always invoked
before resolving or rejecting the Promise (for example call compiler.close(...)
in both error and success branches or move resolve/reject into a try/finally
that calls compiler.close()), referencing the compiler.run callback and
compiler.close to ensure close executes on every callback path.

In `@packages/webpack/template-webpack-plugin/src/LynxTemplatePlugin.ts`:
- Around line 1024-1062: In buildLazyBundleFetchBundleSections: don’t pick the
background entry by the first Object.entries(manifest) item—identify the real BG
entry using explicit metadata (e.g., asset/chunk flags or chunk-group markers
from assetsInfoByGroups/backgroundThread or fallback to the last asset) and use
that asset to set entryChunk and SECTION_BACKGROUND instead of the current
positional logic that sets entryChunk from manifest iteration; and replace the
single-first-css logic (cssAssets[0] + SECTION_CSS) with merging all cssAssets
through cssChunksToMap (or mapping each chunk and concatenating their ruleList
results) so every CSS chunk contributes to the SECTION_CSS ruleList rather than
dropping additional cssAssets.

---

Nitpick comments:
In `@packages/webpack/template-webpack-plugin/src/WebEncodePlugin.ts`:
- Around line 98-104: The code uses a non-null assertion on
EncodeOptions.lepusCode.root (encodeOptions.lepusCode.root!) which can produce
an undefined root at runtime; update the lepusCode construction in
WebEncodePlugin (the block that spreads encodeOptions.lepusCode.lepusChunk into
lepusCode) to avoid the `!` by only including root when it's defined (e.g.,
conditionally spread or add root: encodeOptions.lepusCode.root only if not
undefined), or treat a missing lepusCode.root the same as the absent lepusCode
case and return an empty object when root is absent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1392ece8-db3e-44bf-814f-63da26124e88

📥 Commits

Reviewing files that changed from the base of the PR and between 33b124f and 82cbb45.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (54)
  • .changeset/lazy-bundle-fetch-bundle.md
  • examples/react-lazy-bundle-standalone/lynx.config.consumer.js
  • examples/react-lazy-bundle-standalone/lynx.config.producer.js
  • examples/react-lazy-bundle-standalone/package.json
  • examples/react-lazy-bundle-standalone/src/App.tsx
  • examples/react-lazy-bundle-standalone/src/LazyComponentAsync.css
  • examples/react-lazy-bundle-standalone/src/LazyComponentAsync.tsx
  • examples/react-lazy-bundle-standalone/src/LazyComponentSync.css
  • examples/react-lazy-bundle-standalone/src/LazyComponentSync.tsx
  • examples/react-lazy-bundle-standalone/src/entry-url.ts
  • examples/react-lazy-bundle/lynx.config.js
  • examples/react-lazy-bundle/package.json
  • examples/react-lazy-bundle/src/App.tsx
  • examples/react-lazy-bundle/src/LazyComponentAsync.css
  • examples/react-lazy-bundle/src/LazyComponentAsync.tsx
  • examples/react-lazy-bundle/src/LazyComponentSync.css
  • examples/react-lazy-bundle/src/LazyComponentSync.tsx
  • packages/react/runtime/__test__/snapshot/lynx/lazy-bundle-fetchbundle.test.js
  • packages/react/runtime/__test__/snapshot/lynx/lazy-bundle.test.js
  • packages/react/runtime/__test__/snapshot/lynx/prepareLazyBundleMTS.test.js
  • packages/react/runtime/lazy/internal.js
  • packages/react/runtime/src/internal.ts
  • packages/react/runtime/src/lynx.ts
  • packages/react/runtime/src/snapshot/lifecycle/constant.ts
  • packages/react/runtime/src/snapshot/lynx/dynamic-js.ts
  • packages/react/runtime/src/snapshot/lynx/lazy-bundle.ts
  • packages/react/runtime/src/snapshot/lynx/lazyBundleConstants.ts
  • packages/react/runtime/src/snapshot/lynx/prepareLazyBundleMTS.ts
  • packages/react/runtime/types/types.d.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/types/react.docs.d.ts
  • packages/rspeedy/plugin-react/src/entry.ts
  • packages/rspeedy/plugin-react/src/resolveLazyBundleFetcher.ts
  • packages/rspeedy/plugin-react/test/config.test.ts
  • packages/rspeedy/plugin-react/test/resolveLazyBundleFetcher.test.ts
  • packages/webpack/css-extract-webpack-plugin/package.json
  • packages/webpack/react-refresh-webpack-plugin/package.json
  • packages/webpack/react-webpack-plugin/etc/react-webpack-plugin.api.md
  • packages/webpack/react-webpack-plugin/package.json
  • packages/webpack/react-webpack-plugin/src/ReactWebpackPlugin.ts
  • packages/webpack/react-webpack-plugin/test/fixtures/lazy-bundle-fetcher/index.jsx
  • packages/webpack/react-webpack-plugin/test/lazy-bundle-fetcher.test.ts
  • packages/webpack/template-webpack-plugin/etc/template-webpack-plugin.api.md
  • packages/webpack/template-webpack-plugin/rstest.config.ts
  • packages/webpack/template-webpack-plugin/src/LynxTemplatePlugin.ts
  • packages/webpack/template-webpack-plugin/src/WebEncodePlugin.ts
  • packages/webpack/template-webpack-plugin/test/fixtures/lazy-bundle-fetcher/entry.js
  • packages/webpack/template-webpack-plugin/test/fixtures/lazy-bundle-fetcher/foo.bts.js
  • packages/webpack/template-webpack-plugin/test/fixtures/lazy-bundle-fetcher/foo.mts.js
  • packages/webpack/template-webpack-plugin/test/lazy-bundle-fetcher.test.ts
  • packages/webpack/template-webpack-plugin/test/web-encode-plugin-fetchbundle.test.ts
  • pnpm-workspace.yaml
  • vendor/lynx-js-types-3.10.0.tgz

Comment thread examples/react-lazy-bundle/lynx.config.js
Comment thread packages/react/runtime/src/snapshot/lynx/lazy-bundle.ts
Comment thread packages/react/runtime/src/snapshot/lynx/prepareLazyBundleMTS.ts
Comment thread packages/rspeedy/plugin-react/src/resolveLazyBundleFetcher.ts
Comment thread packages/webpack/react-refresh-webpack-plugin/package.json
Comment thread packages/webpack/react-webpack-plugin/test/lazy-bundle-fetcher.test.ts Outdated
Comment thread packages/webpack/template-webpack-plugin/src/LynxTemplatePlugin.ts
upupming added 4 commits May 11, 2026 23:47
- resolveLazyBundleFetcher: error message says \`engineVersion\` (the
  actual config knob), not \`targetSdkVersion\`
- lazy-bundle.ts MT sync: wrap CSS load + adopt in try/catch so any
  stylesheet failure resolves into the never-resolving promise like
  every other failure mode in the same branch
- react-webpack-plugin test: route compiler.close() through finally so
  it runs even if the run callback rejects
Example apps are demonstration projects without unit tests, so they
should not count toward project / patch coverage. This brings the
ignore list in line with packages/genui/** which is treated the same
way.
`__swc_snapshots__` and `__snapshots__` directories hold generated
test outputs (vitest/cargo snapshots), not source code that should
contribute to coverage.
@upupming upupming marked this pull request as ready for review May 12, 2026 02:46
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

…work

The two pure shape tests (FetchBundle customSections / QueryComponent
legacy lepusCode) belong with the rest of the package's case-based
tests under \`test/cases/\` — they assert on the on-disk \`tasm.json\`
shape and don't need env mutation.

The 4 bytecode-gating tests stay standalone in
\`lazy-bundle-fetcher.test.ts\` because they flip
\`process.env.DEBUG\` per test, and \`cases.test.ts\` runs all cases
in one process.

Drive-by: standalone test now writes to a per-test \`mkdtemp\` output
dir instead of the package's shared \`dist/\`, and the
\`web-encode-plugin\` test uses bracket access on the parsed JSON to
appease tsc's \`noPropertyAccessFromIndexSignature\`.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
packages/webpack/template-webpack-plugin/test/lazy-bundle-fetcher.test.ts (2)

106-116: 💤 Low value

Handle errors from compiler.close.

Line 113 ignores potential errors from compiler.close(). While rare, close errors could indicate resource-cleanup failures that might affect subsequent tests.

🛡️ Proposed error handling
     compiler.run((err, stats) => {
       if (err) return reject(err);
       if (!stats) return reject(new Error('webpack returned empty stats'));
       resolve(stats);
-      compiler.close(() => void 0);
+      compiler.close((closeErr) => {
+        if (closeErr) console.error('webpack close error:', closeErr);
+      });
     });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/webpack/template-webpack-plugin/test/lazy-bundle-fetcher.test.ts`
around lines 106 - 116, The test helper runWebpack currently ignores errors from
compiler.close; update runWebpack (the compiler.run callback and its use of
compiler.close) so that you only resolve the Promise after compiler.close's
callback has run and check its error argument—if close yields an error, reject
the Promise (or at minimum propagate/log the error) instead of silently
swallowing it; this requires moving the resolve(stats) call into the
compiler.close callback and handling close's (err) parameter in runWebpack.

48-54: ⚡ Quick win

Consider cleaning up temporary directories.

Each buildConfig call creates a new temp directory via mkdtempSync, but the test suite never removes them. Frequent test runs could accumulate many directories in tmpdir().

♻️ Suggested cleanup approach

Add a cleanup mechanism in the test suite:

+const createdDirs: string[] = [];
+
 function buildConfig(
   capturePlugin: (compiler: webpack.Compiler) => void,
   mode: 'development' | 'production',
 ): webpack.Configuration {
   const dist = mkdtempSync(join(tmpdir(), 'tmpl-fetchbundle-'));
+  createdDirs.push(dist);
   return {

Then in the outer describe block:

afterEach(() => {
  // ... existing DEBUG restore ...
  for (const dir of createdDirs) {
    rmSync(dir, { recursive: true, force: true });
  }
  createdDirs.length = 0;
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/webpack/template-webpack-plugin/test/lazy-bundle-fetcher.test.ts`
around lines 48 - 54, buildConfig is creating temp dirs via mkdtempSync that are
never removed; track created dirs and remove them in test teardown. Modify
buildConfig to push each created dist path into a shared array (e.g.,
createdDirs) and add an afterEach hook in the test file that iterates
createdDirs and calls rmSync(dir, { recursive: true, force: true }) then clears
the array; ensure you import/require rmSync and that DEBUG restore logic in
afterEach remains intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/webpack/template-webpack-plugin/test/lazy-bundle-fetcher.test.ts`:
- Around line 106-116: The test helper runWebpack currently ignores errors from
compiler.close; update runWebpack (the compiler.run callback and its use of
compiler.close) so that you only resolve the Promise after compiler.close's
callback has run and check its error argument—if close yields an error, reject
the Promise (or at minimum propagate/log the error) instead of silently
swallowing it; this requires moving the resolve(stats) call into the
compiler.close callback and handling close's (err) parameter in runWebpack.
- Around line 48-54: buildConfig is creating temp dirs via mkdtempSync that are
never removed; track created dirs and remove them in test teardown. Modify
buildConfig to push each created dist path into a shared array (e.g.,
createdDirs) and add an afterEach hook in the test file that iterates
createdDirs and calls rmSync(dir, { recursive: true, force: true }) then clears
the array; ensure you import/require rmSync and that DEBUG restore logic in
afterEach remains intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7941f470-3bc8-47f5-ab06-7c2fb30f8bb8

📥 Commits

Reviewing files that changed from the base of the PR and between c126bbd and f6bc1e3.

📒 Files selected for processing (10)
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/fetchbundle/foo.bts.js
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/fetchbundle/foo.mts.js
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/fetchbundle/index.js
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/fetchbundle/rspack.config.js
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/querycomponent/foo.bts.js
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/querycomponent/foo.mts.js
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/querycomponent/index.js
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/querycomponent/rspack.config.js
  • packages/webpack/template-webpack-plugin/test/lazy-bundle-fetcher.test.ts
  • packages/webpack/template-webpack-plugin/test/web-encode-plugin-fetchbundle.test.ts
✅ Files skipped from review due to trivial changes (4)
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/fetchbundle/index.js
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/fetchbundle/foo.mts.js
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/querycomponent/foo.bts.js
  • packages/webpack/template-webpack-plugin/test/cases/lazy-bundle-fetcher/querycomponent/rspack.config.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/webpack/template-webpack-plugin/test/web-encode-plugin-fetchbundle.test.ts

upupming added 3 commits May 12, 2026 17:28
Drop the vendored \`@lynx-js/types-3.10.0.tgz\` override now that
\`@lynx-js/types@3.10.2-alpha.0\` ships the FetchBundle / loadScript
declarations. Override pin moves to the alpha; \`vendor/\` removed.
Drop duplicate `@rsbuild/core@2.0.0-beta.3` indirect deps that
sherif flagged after the main merge.
Drop the workspace override; the alpha is now referenced directly
from each consumer's package.json so resolution behaves like any
other dependency.
@upupming upupming marked this pull request as draft May 12, 2026 11:03
@upupming
Copy link
Copy Markdown
Collaborator Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: db3c74cf11

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
upupming added 3 commits May 12, 2026 19:13
\`use once_cell::sync::Lazy\` resolved transitively through swc_core's
deps, but cargo guarantees nothing about reaching transitive crates by
their bare name. Declare \`once_cell\` explicitly to match the sibling
swc plugins and lock the resolution.

Spotted by Codex review.
Now that `once_cell` is declared in Cargo.toml, the indirect
`swc_core::ecma::atoms::once_cell` re-export trick is no longer
needed. Match `swc_plugin_snapshot`'s simpler import style.
The @lynx-js/types bump pulled some packages back to
`@rsbuild/core@2.0.0-beta.3`; dedupe collapses them to the
overridden 1.7.5 again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants