Skip to content

feat(react/transform): auto define lynx.loadLazyBundle#1956

Merged
HuJean merged 3 commits intomainfrom
p/hujing/lazy-bundle
Dec 8, 2025
Merged

feat(react/transform): auto define lynx.loadLazyBundle#1956
HuJean merged 3 commits intomainfrom
p/hujing/lazy-bundle

Conversation

@HuJean
Copy link
Copy Markdown
Collaborator

@HuJean HuJean commented Nov 25, 2025

Auto define lynx.loadLazyBundle when using import(/* relative path */).

close #1954

Summary by CodeRabbit

  • New Features

    • Auto-defines lynx.loadLazyBundle when using relative dynamic imports to simplify lazy-bundle usage.
  • Examples & Documentation

    • Added a React lazy-bundle example project with config, sample app, and utility modules demonstrating dynamic imports.
  • Tests

    • Added and updated tests and snapshots covering dynamic import transformation and lazy-bundle loading behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).
  • Changeset added, and when a BREAKING CHANGE occurs, it needs to be clearly marked (or not required).

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Nov 25, 2025

🦋 Changeset detected

Latest commit: 5fd6201

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

This PR includes changesets to release 1 package
Name Type
@lynx-js/react Patch

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 Nov 25, 2025

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

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

📝 Walkthrough

Walkthrough

Refactors React runtime to import lazy from preact/compat, removes local lazy wrapper, and updates the SWC dynamic-import transform to optionally inject Lynx lazy-bundle imports; adds tests, vitest configs, a new example project, and a changeset documenting the patch.

Changes

Cohort / File(s) Summary
Changeset
\.changeset/four-rice-guess.md
Adds a patch changeset for @lynx-js/react documenting automatic definition of lynx.loadLazyBundle for relative dynamic imports.
Runtime lazy export refactor
packages/react/runtime/src/index.ts
Removes local lazy wrapper and loadLazyBundle wiring; imports and re-exports lazy directly from preact/compat.
SWC plugin core logic
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs, .../napi.rs
Adds inject_lazy_bundle: Option<bool> config, internal has_inner_lazy_bundle: bool state, create_import_decl helper, and conditional prepending of lazy import declarations; updates Default/init and conversions.
Type & bindings
packages/react/transform/index.d.ts, packages/react/transform/swc-plugin-reactlynx/index.d.ts
Adds optional injectLazyBundle?: boolean to DynamicImportVisitorConfig type declarations.
N-API & config propagation
packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs
Propagates inject_lazy_bundle through N-API bindings and conversion helpers; default set to Some(true).
Tests & snapshots
packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/*.js, packages/react/transform/__test__/fixture.spec.js
Adds/updates snapshots and unit tests for lazy/import handling and inline import behavior; adjusts expectations for injected imports and removed variants.
Vitest / plugin test configs
packages/react/runtime/vitest.config.ts, packages/react/testing-library/src/vitest.config.js
Adds dynamicImport / injectLazyBundle flags and runtimePkg/layer options to transform snapshots and plugin configs.
Webpack plugin tests
packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx, packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx, .../foo2.js
Asserts lynx.loadLazyBundle is defined at runtime; refactors test to await dynamic imports and adds foo2.js helper.
Example project
examples/react-lazy-bundle/*
Adds a full example project: lynx.config.js, package.json, tsconfig.json, styles and source files (src/App.tsx, src/index.tsx, src/rspeedy-env.d.ts, src/utils/*.ts, src/App.css).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review hotspots:
    • swc_plugin_dynamic_import/lib.rs — transformation correctness, import insertion order, and inner-bundle detection.
    • napi.rs and type propagation — ensure config marshaling and defaults behave across FFI boundary.
    • Test snapshots and webpack/vitest test cases — confirm runtime assertion and snapshot updates match transformed output.

Possibly related PRs

Suggested reviewers

  • gaoachao
  • colinaaa
  • hzy

Poem

🐰 A bundle hops in, soft and spry,

lynx.loadLazyBundle now draws nigh.
No wrapper fuss, imports align,
Dynamic hops — the code's just fine! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: auto-defining lynx.loadLazyBundle when dynamic imports are used, which matches the PR's core objective.
Linked Issues check ✅ Passed The PR implements automatic injection of lynx.loadLazyBundle for dynamic imports with relative paths, directly addressing #1954's requirement to prevent runtime errors when lynx.loadLazyBundle is undefined.
Out of Scope Changes check ✅ Passed All changes are aligned with fixing #1954: SWC plugin enhancements enable auto-injection, runtime/index.ts removes manual wrapping, vitest configs enable/disable the feature appropriately, and test files verify the functionality.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@HuJean HuJean changed the title feat(react/transform): auto import lazy runtime for lynx.loadLazyBund… feat(react/transform): auto import lazy runtime Nov 25, 2025
@codecov
Copy link
Copy Markdown

codecov bot commented Nov 25, 2025

Codecov Report

❌ Patch coverage is 70.68966% with 17 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...wc_snapshots__/lib.rs/should_import_lazy_import.js 0.00% 9 Missing ⚠️
...wc_snapshots__/lib.rs/should_import_lazy_bundle.js 0.00% 4 Missing ⚠️
...transform/crates/swc_plugin_dynamic_import/napi.rs 0.00% 3 Missing ⚠️
.../transform/crates/swc_plugin_dynamic_import/lib.rs 97.61% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

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: 0

🧹 Nitpick comments (3)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (1)

45-45: Consider a more descriptive field name.

The field has_dynamic_import specifically tracks relative path dynamic imports (not all dynamic imports). A more descriptive name like has_local_dynamic_import or has_relative_dynamic_import would make the intent clearer, as external URL imports are also "dynamic imports" but don't set this flag.

 pub struct DynamicImportVisitor<C>
 where
   C: Comments,
 {
   opts: DynamicImportVisitorConfig,
-  has_dynamic_import: bool,
+  has_local_dynamic_import: bool,
   named_imports: HashSet<Ident>,
   comments: Option<C>,
 }
packages/rspeedy/plugin-react-alias/src/index.ts (1)

127-138: Alias support for experimental/lazy/lynx is wired correctly; consider centralizing entry names

Adding 'experimental/lazy/lynx' to transformedEntries correctly ensures @lynx-js/react/experimental/lazy/lynx$ is aliased alongside the other transform‑generated imports.

To avoid future drift between react‑transform and this alias plugin, you might consider centralizing these entry names (e.g., a shared constants module) rather than maintaining the list here and in the transform separately.

packages/react/package.json (1)

31-34: New ./experimental/lazy/lynx export and types mapping look consistent; ensure release metadata is updated

The new ./experimental/lazy/lynx export and its typesVersions entry both point to ./runtime/lazy/lynx.{js,d.ts}, which matches the new runtime/type files and keeps the JS/types surfaces aligned.

Since this adds a new public subpath for @lynx-js/react, make sure there’s a corresponding changeset entry for @lynx-js/react using the exact package name, so release notes capture this API addition (as per existing changeset guidelines in this repo).

Also applies to: 122-124

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4695100 and 2d8e372.

📒 Files selected for processing (14)
  • .changeset/four-rice-guess.md (1 hunks)
  • packages/react/package.json (2 hunks)
  • packages/react/runtime/lazy/lynx.d.ts (1 hunks)
  • packages/react/runtime/lazy/lynx.js (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (6 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js (1 hunks)
  • packages/rspeedy/plugin-react-alias/src/index.ts (1 hunks)
  • packages/rspeedy/plugin-react-alias/test/index.test.ts (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (30)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/template-webpack-plugin/src/LynxCacheEventsSetupListRuntimeModule.ts:21-25
Timestamp: 2025-08-19T12:49:05.875Z
Learning: In the Lynx cache events system, there are two separate runtime modules with distinct responsibilities: `LynxCacheEventsSetupListRuntimeModule` is only responsible for initializing the setup list with the setup functions, while `LynxCacheEventsRuntimeModule` guarantees the initialization of `loaded` and `cachedActions` properties. The modules have a dependency relationship where `lynxCacheEventsSetupList` is required by `lynxCacheEvents`.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/runtime/lazy/lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • .changeset/four-rice-guess.md
  • packages/rspeedy/plugin-react-alias/test/index.test.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/lazy/lynx.d.ts
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/runtime/lazy/lynx.js
  • packages/react/package.json
  • .changeset/four-rice-guess.md
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/runtime/lazy/lynx.d.ts
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/runtime/lazy/lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • .changeset/four-rice-guess.md
  • packages/rspeedy/plugin-react-alias/test/index.test.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/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/lazy/lynx.d.ts
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/package.json
  • packages/react/runtime/lazy/lynx.d.ts
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/runtime/lazy/lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • .changeset/four-rice-guess.md
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/lazy/lynx.d.ts
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/package.json
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/rspeedy/plugin-react-alias/test/index.test.ts
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/rspeedy/plugin-react-alias/test/index.test.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/runtime/lazy/lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/lazy/lynx.d.ts
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/runtime/lazy/lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • .changeset/four-rice-guess.md
  • packages/rspeedy/plugin-react-alias/test/index.test.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/lazy/lynx.d.ts
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/runtime/lazy/lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • .changeset/four-rice-guess.md
  • 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/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/lazy/lynx.d.ts
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-07-18T04:27:18.291Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • packages/rspeedy/plugin-react-alias/test/index.test.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/lazy/lynx.d.ts
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • packages/react/runtime/lazy/lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/runtime/lazy/lynx.js
  • .changeset/four-rice-guess.md
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-19T12:49:05.875Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/template-webpack-plugin/src/LynxCacheEventsSetupListRuntimeModule.ts:21-25
Timestamp: 2025-08-19T12:49:05.875Z
Learning: In the Lynx cache events system, there are two separate runtime modules with distinct responsibilities: `LynxCacheEventsSetupListRuntimeModule` is only responsible for initializing the setup list with the setup functions, while `LynxCacheEventsRuntimeModule` guarantees the initialization of `loaded` and `cachedActions` properties. The modules have a dependency relationship where `lynxCacheEventsSetupList` is required by `lynxCacheEvents`.

Applied to files:

  • packages/react/runtime/lazy/lynx.js
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/react/package.json
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • packages/react/package.json
  • .changeset/four-rice-guess.md
  • packages/react/runtime/lazy/lynx.d.ts
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-11T06:00:04.376Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:59-61
Timestamp: 2025-08-11T06:00:04.376Z
Learning: In the lynx-family/lynx-stack repository, the `testingLibraryPlugin` in `packages/react/testing-library/src/plugins/vitest.ts` intentionally uses `process.exit` when jsdom installation fails, maintaining consistency with the previous implementation from `packages/react/testing-library/src/vitest.config.js`. This behavior should not be changed to use `this.error` despite being a Vite plugin best practice.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/rspeedy/plugin-react-alias/test/index.test.ts
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • packages/rspeedy/plugin-react-alias/test/index.test.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/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • .changeset/four-rice-guess.md
  • 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/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
📚 Learning: 2025-10-11T06:16:12.517Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1820
File: packages/web-platform/web-tests/tests/react.spec.ts:834-856
Timestamp: 2025-10-11T06:16:12.517Z
Learning: In packages/web-platform/web-tests/tests/react.spec.ts, the tests `basic-bindmouse` and `basic-mts-bindtouchstart` are NOT duplicates despite having similar test structures. They test different event types: `basic-bindmouse` validates mouse events (mousedown, mouseup, mousemove) with mouse-specific properties (button, buttons, x, y, pageX, pageY, clientX, clientY), while `basic-mts-bindtouchstart` validates touch events (touchstart) with touch arrays (touches, targetTouches, changedTouches). The similar test structure is coincidental and follows testing conventions.

Applied to files:

  • packages/rspeedy/plugin-react-alias/test/index.test.ts
📚 Learning: 2025-08-13T09:20:00.936Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1502
File: packages/react/testing-library/types/entry.d.ts:71-71
Timestamp: 2025-08-13T09:20:00.936Z
Learning: In lynx-js/react testing library, wrapper components must have children as a required prop because they are always called with `h(WrapperComponent, null, innerElement)` where innerElement is passed as children. The type `React.JSXElementConstructor<{ children: React.ReactNode }>` correctly requires children to be mandatory.

Applied to files:

  • packages/rspeedy/plugin-react-alias/test/index.test.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-09-10T11:42:36.855Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1714
File: packages/react/transform/Cargo.toml:19-19
Timestamp: 2025-09-10T11:42:36.855Z
Learning: In packages/react/transform/Cargo.toml, the crate uses serde derive macros (#[derive(Serialize, Deserialize)]) in multiple files including src/esbuild.rs and src/swc_plugin_extract_str/mod.rs, so the "derive" feature is required when migrating to workspace dependencies.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • 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/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
📚 Learning: 2025-08-21T07:21:51.621Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1562
File: packages/react/transform/src/swc_plugin_snapshot/jsx_helpers.rs:261-283
Timestamp: 2025-08-21T07:21:51.621Z
Learning: In packages/react/transform/src/swc_plugin_snapshot/jsx_helpers.rs, the team prefers to keep the original unreachable! logic for JSXSpreadChild in jsx_is_children_full_dynamic function rather than implementing defensive error handling.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
🧬 Code graph analysis (1)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)
packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (1)
  • new (67-71)
packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)
  • DynamicImportVisitorConfig (166-171)
🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~6-~6: Use a hyphen to join words.
Context: ... patch "@lynx-js/react": patch --- Auto import `@lynx-js/react/experimental/lazy...

(QB_NEW_EN_HYPHEN)

🔇 Additional comments (13)
packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js (1)

1-2: LGTM!

The snapshot correctly reflects the new lazy import injection behavior. The @lynx-js/react/experimental/lazy/lynx import is prepended when relative path dynamic imports are detected (e.g., ./index.js), while @lynx-js/react/experimental/lazy/import is added for external URL imports that use __dynamicImport.

packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js (1)

1-4: LGTM!

The snapshot correctly demonstrates the isolated case: when only relative path dynamic imports exist (without external URLs), only the @lynx-js/react/experimental/lazy/lynx import is injected. The webpackChunkName comment is properly added.

packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1)

1-9: LGTM!

The snapshot correctly demonstrates the isolated case: when only external URL dynamic imports exist (without relative paths), only the @lynx-js/react/experimental/lazy/import import is injected, and __dynamicImport is used for the external URL.

.changeset/four-rice-guess.md (1)

1-6: LGTM!

The changeset correctly documents the new feature with appropriate patch version bumps for both affected packages. The package names follow the repository conventions (using exact scoped names from package.json).

packages/react/runtime/lazy/lynx.js (1)

1-2: LGTM!

The implementation correctly exposes loadLazyBundle on the global lynx object. This aligns with the codebase pattern where the Lynx Engine provides the lynx global at runtime.

packages/react/runtime/src/index.ts (1)

18-21: LGTM!

Clean refactoring that directly re-exports lazy from preact/compat. The lynx.loadLazyBundle setup responsibility is now properly separated into @lynx-js/react/experimental/lazy/lynx, which is auto-imported by the SWC plugin when needed.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (3)

114-131: LGTM!

The create_lazy_import_decl helper cleanly generates the import declarations. The string replacement replace("/internal", "") correctly transforms @lynx-js/react/internal to @lynx-js/react for the experimental lazy paths.


336-384: LGTM!

Good test coverage for the new lazy import behavior:

  • should_import_lazy_import: external URL only → lazy/import injected
  • should_import_lazy_lynx: relative path only → lazy/lynx injected
  • should_not_import_lazy: template literal → no lazy imports (correctly ignored as context imports)

267-277: The review comment is based on a misunderstanding of the intended design.

The conditional logic is correct and working as intended. The plugin uses different lazy runtimes for different import types:

  • Relative path imports (e.g., import("./index.js")) → has_dynamic_import=true → injects only lazy/lynx
  • External URL imports (e.g., import("https://...")) → named_imports={__dynamicImport} → injects only lazy/import

The snapshots confirm this behavior is expected: each import type receives the appropriate lazy runtime dependency it needs. There is no missing dependency issue or bug here. The lazy runtime dependencies are correctly satisfied in both scenarios.

Likely an incorrect or invalid review comment.

packages/rspeedy/plugin-react-alias/test/index.test.ts (1)

71-76: New lazy Lynx alias assertion is consistent with plugin aliasing

The added expectation for @lynx-js/react/experimental/lazy/lynx$ correctly matches the alias key the plugin sets and points to the expected runtime/lazy/lynx.js path, in line with the existing experimental/lazy/import assertion.

packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1)

28-28: Confirm lynx.loadLazyBundle is available in all environments this test runs in

You assert lynx.loadLazyBundle before branching on __BACKGROUND__, while the other expectations use lynx[...] only in background and globalThis[...] otherwise. Please double‑check that lynx (and lynx.loadLazyBundle) is indeed defined in all relevant environments; if not, you may need to mirror the conditional pattern used below.

packages/react/runtime/lazy/lynx.d.ts (1)

1-1: Side‑effect‑only declaration file looks appropriate

Using export {}; to declare the module without value exports fits a runtime that’s only meant to be imported for side effects (e.g., installing lynx.loadLazyBundle) and not to provide typed imports.

packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1)

3-5: Dynamic import('./foo.js') usage aligns with lazy‑bundle test intent

Using a top‑level import('./foo.js').then(...) is a straightforward way to exercise relative import() for this webpack case, so the lazy‑bundle machinery can be validated without changing test assertions.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Nov 25, 2025

CodSpeed Performance Report

Merging #1956 will not alter performance

Comparing p/hujing/lazy-bundle (5fd6201) with main (6400f87)1

Summary

✅ 63 untouched
⏩ 3 skipped2

Footnotes

  1. No successful run was found on main (8cdb69d) during the generation of this report, so 6400f87 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 3 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 Nov 25, 2025

React Example

#6388 Bundle Size — 236.9KiB (0%).

5fd6201(current) vs 6400f87 main#6360(baseline)

Bundle metrics  Change 1 change
                 Current
#6388
     Baseline
#6360
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
No change  Modules 162 162
No change  Duplicate Modules 65 65
Change  Duplicate Code 46.74%(-0.02%) 46.75%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#6388
     Baseline
#6360
No change  IMG 145.76KiB 145.76KiB
No change  Other 91.14KiB 91.14KiB

Bundle analysis reportBranch p/hujing/lazy-bundleProject dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci bot commented Nov 25, 2025

Web Explorer

#6548 Bundle Size — 372.73KiB (0%).

5fd6201(current) vs 6400f87 main#6520(baseline)

Bundle metrics  Change 1 change
                 Current
#6548
     Baseline
#6520
No change  Initial JS 146.31KiB 146.31KiB
No change  Initial CSS 32.4KiB 32.4KiB
Change  Cache Invalidation 0% 11.74%
No change  Chunks 8 8
No change  Assets 8 8
Change  Modules 229(-0.43%) 230
No change  Duplicate Modules 16 16
No change  Duplicate Code 2.97% 2.97%
No change  Packages 4 4
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#6548
     Baseline
#6520
No change  JS 243.35KiB 243.35KiB
No change  Other 96.98KiB 96.98KiB
No change  CSS 32.4KiB 32.4KiB

Bundle analysis reportBranch p/hujing/lazy-bundleProject dashboard


Generated by RelativeCIDocumentationReport issue

@HuJean HuJean force-pushed the p/hujing/lazy-bundle branch 3 times, most recently from d3d6324 to fbcd88d Compare November 25, 2025 05:57
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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1)

22-28: The assertion for lynx.loadLazyBundle is incorrect for external URL imports.

Based on the webpack plugin's transform logic, external URL imports (like https://www/a.js) only inject the "import" lazy module to provide React APIs. The "lynx" lazy module—which defines lynx.loadLazyBundle—is only injected for relative/local imports.

The test checks for lynx.loadLazyBundle on line 28, but this property will not be defined when using external URLs. Either use a relative import path to test the "lynx" lazy module, or remove the lynx.loadLazyBundle assertion and keep only the React API symbol checks.

🧹 Nitpick comments (2)
.changeset/four-rice-guess.md (1)

1-6: Changeset packages and description look correct

Package names match scoped package.json names and patch bumps are appropriate for this bugfix-level behavior change. The one-line description is clear and specific to the new auto-import behavior. If you care about wording nits, you could change “Auto import” to “Auto-import”, but that’s optional.

Based on learnings, this matches the repo’s changeset conventions.

packages/react/runtime/lazy/lynx.js (1)

1-2: Runtime wiring is correct; consider guarding the lynx global

The import and assignment correctly expose loadLazyBundle on lynx. This assumes a global lynx is always present where this module runs; if there are environments (e.g., Node tests/SSR) where lynx might be absent, you could optionally guard the write to avoid a ReferenceError, e.g.:

-import { loadLazyBundle } from '@lynx-js/react/internal';
-lynx.loadLazyBundle = loadLazyBundle;
+import { loadLazyBundle } from '@lynx-js/react/internal';
+if (typeof lynx !== 'undefined') {
+  lynx.loadLazyBundle = loadLazyBundle;
+}

If this file only ever executes under the Lynx engine where lynx is guaranteed, the current version is fine.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d3d6324 and fbcd88d.

📒 Files selected for processing (17)
  • .changeset/four-rice-guess.md (1 hunks)
  • packages/react/package.json (2 hunks)
  • packages/react/runtime/lazy/lynx.d.ts (1 hunks)
  • packages/react/runtime/lazy/lynx.js (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/runtime/vitest.config.ts (1 hunks)
  • packages/react/transform/__test__/fixture.spec.js (3 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (6 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js (1 hunks)
  • packages/rspeedy/plugin-react-alias/src/index.ts (1 hunks)
  • packages/rspeedy/plugin-react-alias/test/index.test.ts (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/rspeedy/plugin-react-alias/test/index.test.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/runtime/lazy/lynx.d.ts
  • packages/react/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_import.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_transform_import_call.js
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (30)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/template-webpack-plugin/src/LynxCacheEventsSetupListRuntimeModule.ts:21-25
Timestamp: 2025-08-19T12:49:05.875Z
Learning: In the Lynx cache events system, there are two separate runtime modules with distinct responsibilities: `LynxCacheEventsSetupListRuntimeModule` is only responsible for initializing the setup list with the setup functions, while `LynxCacheEventsRuntimeModule` guarantees the initialization of `loaded` and `cachedActions` properties. The modules have a dependency relationship where `lynxCacheEventsSetupList` is required by `lynxCacheEvents`.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/src/index.ts
  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/runtime/vitest.config.ts
  • packages/react/runtime/lazy/lynx.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/transform/__test__/fixture.spec.js
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/runtime/lazy/lynx.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/src/index.ts
  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/runtime/vitest.config.ts
  • packages/react/runtime/lazy/lynx.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/src/index.ts
  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/runtime/vitest.config.ts
  • packages/react/runtime/lazy/lynx.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/runtime/vitest.config.ts
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/src/index.ts
  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/runtime/vitest.config.ts
  • packages/react/runtime/lazy/lynx.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/runtime/vitest.config.ts
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/runtime/lazy/lynx.js
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/src/index.ts
  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/runtime/lazy/lynx.js
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/src/index.ts
  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/runtime/vitest.config.ts
  • packages/react/runtime/lazy/lynx.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-13T09:20:00.936Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1502
File: packages/react/testing-library/types/entry.d.ts:71-71
Timestamp: 2025-08-13T09:20:00.936Z
Learning: In lynx-js/react testing library, wrapper components must have children as a required prop because they are always called with `h(WrapperComponent, null, innerElement)` where innerElement is passed as children. The type `React.JSXElementConstructor<{ children: React.ReactNode }>` correctly requires children to be mandatory.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
  • packages/react/transform/__test__/fixture.spec.js
📚 Learning: 2025-08-11T06:00:04.376Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:59-61
Timestamp: 2025-08-11T06:00:04.376Z
Learning: In the lynx-family/lynx-stack repository, the `testingLibraryPlugin` in `packages/react/testing-library/src/plugins/vitest.ts` intentionally uses `process.exit` when jsdom installation fails, maintaining consistency with the previous implementation from `packages/react/testing-library/src/vitest.config.js`. This behavior should not be changed to use `this.error` despite being a Vite plugin best practice.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/react/runtime/src/index.ts
  • packages/react/transform/__test__/fixture.spec.js
📚 Learning: 2025-07-18T04:27:18.291Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.

Applied to files:

  • packages/react/runtime/src/index.ts
📚 Learning: 2025-09-23T08:54:39.966Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
📚 Learning: 2025-08-18T08:46:20.001Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1547
File: packages/rspeedy/core/src/config/loadConfig.ts:11-11
Timestamp: 2025-08-18T08:46:20.001Z
Learning: `#register` and similar imports starting with "#" are Node.js subpath imports defined in the "imports" field of package.json, not TypeScript path mapping aliases. These are natively supported by both Node.js and TypeScript without requiring additional tsconfig.json configuration like "moduleResolution" or "resolvePackageJsonImports" settings.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
📚 Learning: 2025-09-10T11:42:36.855Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1714
File: packages/react/transform/Cargo.toml:19-19
Timestamp: 2025-09-10T11:42:36.855Z
Learning: In packages/react/transform/Cargo.toml, the crate uses serde derive macros (#[derive(Serialize, Deserialize)]) in multiple files including src/esbuild.rs and src/swc_plugin_extract_str/mod.rs, so the "derive" feature is required when migrating to workspace dependencies.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/runtime/vitest.config.ts
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • packages/react/runtime/lazy/lynx.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • packages/react/runtime/vitest.config.ts
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-28T08:46:43.177Z
Learnt from: f0rdream
Repo: lynx-family/lynx-stack PR: 1835
File: packages/react/worklet-runtime/src/workletRuntime.ts:52-55
Timestamp: 2025-09-28T08:46:43.177Z
Learning: The legacy worklet path with `_lepusWorkletHash` in `packages/react/worklet-runtime/src/workletRuntime.ts` is preserved for compatibility with MTS (Mini-app Threading Service) that doesn't support Initial Frame Rendering. This path will not be touched in current implementations.

Applied to files:

  • packages/react/runtime/vitest.config.ts
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • .changeset/four-rice-guess.md
🧬 Code graph analysis (1)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)
packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (1)
  • new (67-71)
packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)
  • DynamicImportVisitorConfig (166-171)
🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~6-~6: Use a hyphen to join words.
Context: ... patch "@lynx-js/react": patch --- Auto import `@lynx-js/react/experimental/lazy...

(QB_NEW_EN_HYPHEN)

🔇 Additional comments (7)
packages/react/transform/__test__/fixture.spec.js (1)

909-1003: Dynamic import “badcase” snapshot correctly exercises lazy runtime auto-import

The added await import("./index.js"); input, together with the updated snapshot (new import "@lynx-js/react/experimental/lazy/lynx";, preserved experimental/lazy/import, and the webpackChunkName comment on the relative import) cleanly verifies the new auto-import behavior, and the shifted error location (:6:8:) stays consistent with the modified source template. No issues from the test side.

packages/react/runtime/vitest.config.ts (1)

64-64: LGTM!

The new alias for the experimental lazy runtime is correctly configured and follows the existing pattern. The ordering is appropriate since more specific paths should precede less specific ones.

packages/react/runtime/src/index.ts (1)

18-18: Clean refactor - direct re-export of lazy from preact/compat.

The Lynx-specific loadLazyBundle wiring is now correctly separated into @lynx-js/react/experimental/lazy/lynx, which gets auto-imported by the SWC transform when dynamic imports are detected.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (3)

114-131: Well-structured helper for lazy import generation.

The path manipulation using .replace("/internal", "") correctly transforms the default runtime package from @lynx-js/react/internal to @lynx-js/react/experimental/lazy/{name}. The empty specifiers correctly generate a side-effect-only import.


267-277: Correct conditional lazy import injection.

The logic correctly differentiates between:

  • External URL imports (named_imports not empty) → adds "import" lazy module
  • Relative/local dynamic imports (has_dynamic_import true) → adds "lynx" lazy module

Both can coexist when a file has both import types.


336-384: Good test coverage for the new lazy import scenarios.

The tests appropriately cover:

  • External URL imports requiring "import" lazy module
  • Relative path imports requiring "lynx" lazy module
  • Template literal imports that should not inject lazy modules
packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js (1)

1-4: Snapshot correctly reflects the lazy lynx import injection.

The auto-generated snapshot shows the expected behavior: relative path dynamic imports trigger the injection of @lynx-js/react/experimental/lazy/lynx and the webpackChunkName comment is properly generated.

@HuJean HuJean force-pushed the p/hujing/lazy-bundle branch from fbcd88d to f91c760 Compare November 28, 2025 08:05
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: 0

🧹 Nitpick comments (1)
.changeset/four-rice-guess.md (1)

6-6: Optional: Consider minor grammar improvement.

The description is clear, but per English grammar conventions, compound modifiers before nouns should be hyphenated: "Auto-import" or "Automatically import".

-Auto import `@lynx-js/react/experimental/lazy/lynx` when using `import(/* relative path */)` to define lynx.loadLazyBundle.
+Auto-import `@lynx-js/react/experimental/lazy/lynx` when using `import(/* relative path */)` to define lynx.loadLazyBundle.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fbcd88d and f91c760.

📒 Files selected for processing (17)
  • .changeset/four-rice-guess.md (1 hunks)
  • packages/react/package.json (2 hunks)
  • packages/react/runtime/lazy/lynx.d.ts (1 hunks)
  • packages/react/runtime/lazy/lynx.js (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/runtime/vitest.config.ts (1 hunks)
  • packages/react/transform/__test__/fixture.spec.js (3 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (6 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js (1 hunks)
  • packages/rspeedy/plugin-react-alias/src/index.ts (1 hunks)
  • packages/rspeedy/plugin-react-alias/test/index.test.ts (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/react/runtime/vitest.config.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_transform_import_call.js
  • packages/rspeedy/plugin-react-alias/test/index.test.ts
  • packages/react/runtime/lazy/lynx.d.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_import.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/rspeedy/plugin-react-alias/src/index.ts
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (30)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/template-webpack-plugin/src/LynxCacheEventsSetupListRuntimeModule.ts:21-25
Timestamp: 2025-08-19T12:49:05.875Z
Learning: In the Lynx cache events system, there are two separate runtime modules with distinct responsibilities: `LynxCacheEventsSetupListRuntimeModule` is only responsible for initializing the setup list with the setup functions, while `LynxCacheEventsRuntimeModule` guarantees the initialization of `loaded` and `cachedActions` properties. The modules have a dependency relationship where `lynxCacheEventsSetupList` is required by `lynxCacheEvents`.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/react/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
📚 Learning: 2025-09-23T08:54:39.966Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/react/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/react/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/react/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/react/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/runtime/lazy/lynx.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-18T08:46:20.001Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1547
File: packages/rspeedy/core/src/config/loadConfig.ts:11-11
Timestamp: 2025-08-18T08:46:20.001Z
Learning: `#register` and similar imports starting with "#" are Node.js subpath imports defined in the "imports" field of package.json, not TypeScript path mapping aliases. These are natively supported by both Node.js and TypeScript without requiring additional tsconfig.json configuration like "moduleResolution" or "resolvePackageJsonImports" settings.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/react/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-13T09:20:00.936Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1502
File: packages/react/testing-library/types/entry.d.ts:71-71
Timestamp: 2025-08-13T09:20:00.936Z
Learning: In lynx-js/react testing library, wrapper components must have children as a required prop because they are always called with `h(WrapperComponent, null, innerElement)` where innerElement is passed as children. The type `React.JSXElementConstructor<{ children: React.ReactNode }>` correctly requires children to be mandatory.

Applied to files:

  • packages/react/transform/__test__/fixture.spec.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-11T06:00:04.376Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:59-61
Timestamp: 2025-08-11T06:00:04.376Z
Learning: In the lynx-family/lynx-stack repository, the `testingLibraryPlugin` in `packages/react/testing-library/src/plugins/vitest.ts` intentionally uses `process.exit` when jsdom installation fails, maintaining consistency with the previous implementation from `packages/react/testing-library/src/vitest.config.js`. This behavior should not be changed to use `this.error` despite being a Vite plugin best practice.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • packages/react/runtime/lazy/lynx.js
  • packages/react/package.json
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-19T12:49:05.875Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/template-webpack-plugin/src/LynxCacheEventsSetupListRuntimeModule.ts:21-25
Timestamp: 2025-08-19T12:49:05.875Z
Learning: In the Lynx cache events system, there are two separate runtime modules with distinct responsibilities: `LynxCacheEventsSetupListRuntimeModule` is only responsible for initializing the setup list with the setup functions, while `LynxCacheEventsRuntimeModule` guarantees the initialization of `loaded` and `cachedActions` properties. The modules have a dependency relationship where `lynxCacheEventsSetupList` is required by `lynxCacheEvents`.

Applied to files:

  • packages/react/runtime/lazy/lynx.js
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/react/package.json
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • packages/react/package.json
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • packages/react/package.json
  • .changeset/four-rice-guess.md
📚 Learning: 2025-10-10T08:22:12.051Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1837
File: packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts:266-266
Timestamp: 2025-10-10T08:22:12.051Z
Learning: In packages/web-platform/web-mainthread-apis, the handleUpdatedData function returned from prepareMainThreadAPIs is internal-only, used to serve web-core. It does not require public documentation, type exports, or SSR support.

Applied to files:

  • packages/react/package.json
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • packages/react/package.json
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js
📚 Learning: 2025-09-10T11:42:36.855Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1714
File: packages/react/transform/Cargo.toml:19-19
Timestamp: 2025-09-10T11:42:36.855Z
Learning: In packages/react/transform/Cargo.toml, the crate uses serde derive macros (#[derive(Serialize, Deserialize)]) in multiple files including src/esbuild.rs and src/swc_plugin_extract_str/mod.rs, so the "derive" feature is required when migrating to workspace dependencies.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-07-18T04:27:18.291Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.

Applied to files:

  • packages/react/runtime/src/index.ts
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~6-~6: Use a hyphen to join words.
Context: ... patch "@lynx-js/react": patch --- Auto import `@lynx-js/react/experimental/lazy...

(QB_NEW_EN_HYPHEN)

🔇 Additional comments (11)
packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1)

28-28: LGTM! Test assertion correctly verifies the new runtime behavior.

The assertion confirms that lynx.loadLazyBundle is available after the experimental lazy/lynx module is auto-imported, which aligns with the PR objectives.

packages/react/runtime/lazy/lynx.js (1)

1-2: LGTM! Side-effect module correctly exposes loadLazyBundle.

This module intentionally mutates the global lynx object to make loadLazyBundle available when auto-imported by the transform plugin. The side-effect nature is appropriate for this use case.

packages/react/runtime/src/index.ts (1)

18-18: LGTM! Simplifies runtime by importing lazy directly from preact/compat.

The removal of the local lazy wrapper is appropriate since the loadLazyBundle wiring is now handled separately in the dedicated experimental/lazy/lynx module. This separation improves modularity.

packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js (1)

1-4: LGTM! Snapshot correctly reflects the expected transformation.

This auto-generated snapshot shows that relative-path dynamic imports trigger the auto-import of @lynx-js/react/experimental/lazy/lynx, which exposes lynx.loadLazyBundle for the lazy bundle handling.

packages/react/package.json (1)

31-34: LGTM! New export path appropriately exposes the experimental lazy/lynx runtime.

The export path is necessary because this module has side effects (assigns lynx.loadLazyBundle) that need to be triggered via import. The structure is consistent with the existing ./experimental/lazy/import export.

packages/react/transform/__test__/fixture.spec.js (1)

917-917: LGTM! Test correctly validates the auto-import behavior.

The test demonstrates that relative-path dynamic imports trigger auto-import of both:

  1. @lynx-js/react/experimental/lazy/lynx (for lynx.loadLazyBundle)
  2. @lynx-js/react/experimental/lazy/import (for external lazy handling)

The comprehensive test coverage is provided by the Rust implementation tests (should_import_lazy_import, should_import_lazy_lynx, should_not_import_lazy).

Also applies to: 942-943, 949-949

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (5)

45-45: LGTM! Field correctly tracks whether relative-path dynamic imports are present.

The has_inner_lazy_bundle flag appropriately distinguishes between:

  • Inner lazy bundles (relative paths that webpack bundles together)
  • External lazy resources (URLs/dynamic paths handled by __dynamicImport)

The naming is precise and the flag is used correctly to conditionally emit the lazy/lynx import.

Also applies to: 67-67


114-131: LGTM! Helper function cleanly generates lazy import declarations.

The create_lazy_import_decl function appropriately:

  • Generates import declarations for {runtime_pkg}/experimental/lazy/{name}
  • Strips /internal from the runtime package path
  • Creates evaluation-phase imports with no specifiers (side-effect imports)

The comment clarifies the distinction between lazy/import (external standalone bundles) and lazy/lynx (auto-generated bundles).


220-220: LGTM! Correctly sets flag for relative-path dynamic imports.

The flag is set only when a string-literal, non-external, relative-path dynamic import is detected (line 196-210 validates these conditions). This ensures the lazy/lynx import is only added when needed for webpack-bundled lazy modules.


267-277: LGTM! Import prepending logic is correct.

The order is appropriate:

  1. Prepends lazy/import when named imports exist (external resources)
  2. Prepends lazy/lynx when inner lazy bundles are detected (relative imports)

Since prepend_stmt adds to the beginning, the final order will be lazy/lynx then lazy/import, which is correct.


336-384: LGTM! Comprehensive test coverage for lazy import scenarios.

The new tests appropriately cover:

  • should_import_lazy_import: Only external URL imports (lazy/import only)
  • should_import_lazy_lynx: Only relative-path imports (lazy/lynx only)
  • should_not_import_lazy: Template literal imports (no lazy imports)

This addresses the previous review concern about test case coverage.

@HuJean HuJean enabled auto-merge (squash) November 28, 2025 08:20
@HuJean HuJean force-pushed the p/hujing/lazy-bundle branch from 7a4b124 to 9698a0d Compare December 1, 2025 02:57
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: 0

♻️ Duplicate comments (2)
packages/react/runtime/lazy/lynx.js (1)

1-2: Side-effect import correctly wires the lazy runtime.

This module is auto-imported by the SWC transform when dynamic imports are detected, ensuring lynx.loadLazyBundle is available before any lazy bundle loading occurs. The implementation is minimal and follows the established pattern for exposing runtime functions on the lynx global.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (1)

45-45: Consider the naming suggestion from a previous review.

A past review comment suggested renaming has_inner_lazy_bundle to has_lazy_bundle. The current naming distinguishes "inner" (bundled with main bundle) from "external" (standalone) lazy bundles, which aligns with the comments at lines 114-115. Either naming works; consider whether the distinction is valuable for readers.

🧹 Nitpick comments (3)
packages/rspeedy/plugin-react-alias/src/index.ts (1)

152-158: Alias added correctly, but uses a different resolution pattern.

This alias uses path.join directly rather than the resolve() helper used for other transformedEntries. This is likely intentional since lazy/lynx.js is a new file that may not be configured in the package's exports map yet.

If the runtime package's package.json exports are later updated to include this entry, consider consolidating this into transformedEntries for consistency.

.changeset/four-rice-guess.md (1)

1-6: Changeset correctly documents the patch release.

Package names match the exact scoped names from package.json. The description clearly explains the new auto-import behavior and the version requirement.

Minor grammar nit: Consider "Auto-import" (hyphenated) for consistency.

-Auto import `@lynx-js/react/experimental/lazy/lynx` when using `import(/* relative path */)` to define lynx.loadLazyBundle. This requires `@lynx-js/react-rsbuild-plugin` v0.11.5 to work.
+Auto-import `@lynx-js/react/experimental/lazy/lynx` when using `import(/* relative path */)` to define lynx.loadLazyBundle. This requires `@lynx-js/react-rsbuild-plugin` v0.11.5 to work.
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (1)

124-126: String replacement may cause unintended behavior with custom runtime packages.

The .replace("/internal", "") will replace the first occurrence of /internal in the string, which could be problematic if a custom runtime_pkg contains /internal elsewhere in the path.

For example, if runtime_pkg is @my-org/internal-react/internal, the result would be:

  • Input: @my-org/internal-react/internal/experimental/lazy/lynx
  • Output: @my-org-react/internal/experimental/lazy/lynx (incorrect)

Consider using strip_suffix or trim_end_matches if the intent is to only remove a trailing /internal:

-      value: format!("{runtime_pkg}/experimental/lazy/{name}")
-        .replace("/internal", "")
-        .into(),
+      value: {
+        let base = runtime_pkg.strip_suffix("/internal").unwrap_or(runtime_pkg);
+        format!("{base}/experimental/lazy/{name}").into()
+      },
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a4b124 and 9698a0d.

📒 Files selected for processing (16)
  • .changeset/four-rice-guess.md (1 hunks)
  • packages/react/runtime/lazy/lynx.d.ts (1 hunks)
  • packages/react/runtime/lazy/lynx.js (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/runtime/vitest.config.ts (1 hunks)
  • packages/react/transform/__test__/fixture.spec.js (3 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (6 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js (1 hunks)
  • packages/rspeedy/plugin-react-alias/src/index.ts (1 hunks)
  • packages/rspeedy/plugin-react-alias/test/index.test.ts (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
🚧 Files skipped from review as they are similar to previous changes (9)
  • packages/rspeedy/plugin-react-alias/test/index.test.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/transform/test/fixture.spec.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_lynx.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js
  • packages/react/runtime/src/index.ts
  • packages/react/runtime/lazy/lynx.d.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_transform_import_call.js
  • packages/react/runtime/vitest.config.ts
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (25)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/rspeedy/plugin-react-alias/src/index.ts
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/rspeedy/plugin-react-alias/src/index.ts
📚 Learning: 2025-08-11T06:00:04.376Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:59-61
Timestamp: 2025-08-11T06:00:04.376Z
Learning: In the lynx-family/lynx-stack repository, the `testingLibraryPlugin` in `packages/react/testing-library/src/plugins/vitest.ts` intentionally uses `process.exit` when jsdom installation fails, maintaining consistency with the previous implementation from `packages/react/testing-library/src/vitest.config.js`. This behavior should not be changed to use `this.error` despite being a Vite plugin best practice.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/rspeedy/plugin-react-alias/src/index.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • packages/rspeedy/plugin-react-alias/src/index.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/lazy/lynx.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • packages/react/runtime/lazy/lynx.js
  • packages/rspeedy/plugin-react-alias/src/index.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/runtime/lazy/lynx.js
  • packages/rspeedy/plugin-react-alias/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • .changeset/four-rice-guess.md
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • packages/rspeedy/plugin-react-alias/src/index.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-10T11:42:36.855Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1714
File: packages/react/transform/Cargo.toml:19-19
Timestamp: 2025-09-10T11:42:36.855Z
Learning: In packages/react/transform/Cargo.toml, the crate uses serde derive macros (#[derive(Serialize, Deserialize)]) in multiple files including src/esbuild.rs and src/swc_plugin_extract_str/mod.rs, so the "derive" feature is required when migrating to workspace dependencies.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
🧬 Code graph analysis (1)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)
packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (1)
  • new (67-71)
packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)
  • DynamicImportVisitorConfig (166-171)
🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~6-~6: Use a hyphen to join words.
Context: ... patch "@lynx-js/react": patch --- Auto import `@lynx-js/react/experimental/lazy...

(QB_NEW_EN_HYPHEN)

🔇 Additional comments (5)
packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1)

1-9: Snapshot correctly captures the expected transform behavior.

The snapshot shows the SWC plugin now auto-imports @lynx-js/react/experimental/lazy/import alongside the __dynamicImport helper when processing dynamic imports. This aligns with the PR's objective to ensure lazy runtime availability.

Based on learnings, this is an auto-generated snapshot file and any issues should be addressed in the transform logic, not the snapshot itself.

packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1)

22-28: Test correctly validates the auto-import behavior.

The assertion at line 28 directly validates the fix for issue #1954, ensuring lynx.loadLazyBundle is defined when code uses dynamic imports. Based on learnings, webpack properties are injected at compile time, so this assertion doesn't need to wait for the dynamic import to complete.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (3)

196-220: LGTM!

The flag has_inner_lazy_bundle is correctly set when a string literal dynamic import is detected (excluding explicitly external URLs). This ensures the @lynx-js/react/experimental/lazy/lynx runtime is auto-imported for internal lazy bundles as intended by the PR objective.


267-277: LGTM!

The prepend logic correctly handles two scenarios:

  1. External dynamic imports (non-string-literal or external URLs) → adds experimental/lazy/import runtime
  2. Internal lazy bundles (relative path string literals) → adds experimental/lazy/lynx runtime

The use of separate conditionals allows both imports to be added when both conditions are met.


323-384: LGTM!

The new tests provide good coverage for the three main scenarios:

  1. should_import_lazy_import - external URL with component type assertion triggers __dynamicImport and lazy/import
  2. should_import_lazy_lynx - relative path import triggers lazy/lynx auto-import
  3. should_not_import_lazy - template literal imports are ignored (webpack context imports)

These tests align well with the PR objectives of auto-importing the lazy runtime based on import patterns.

@HuJean HuJean force-pushed the p/hujing/lazy-bundle branch from 9698a0d to 7675333 Compare December 1, 2025 09:11
@HuJean HuJean changed the title feat(react/transform): auto import lazy runtime feat(react/transform): auto define lynx.loadLazyBundle Dec 1, 2025
@HuJean HuJean force-pushed the p/hujing/lazy-bundle branch 3 times, most recently from bdc8ce7 to ee46fb1 Compare December 1, 2025 09:19
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: 1

🧹 Nitpick comments (3)
packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1)

2-6: Test now correctly targets plain dynamic imports

The async test with two awaited relative import() calls exercises the intended scenario (dynamic imports without lazy wrapper) and then checks lynx.loadLazyBundle is defined, which matches the linked bug’s intent. As a minor optional tweak, you could run the imports in parallel for slightly faster tests:

await Promise.all([import('./foo.js'), import('./foo2.js')]);

But the current version is perfectly fine functionally.

examples/react-lazy-bundle/lynx.config.js (1)

1-25: Verify pluginQRCode schema return type

The overall rsbuild config looks good, but the custom QR schema:

schema(url) {
  return `${url}?fullscreen=true`;
}

differs from the plugin’s documented default of returning an object like { http: url }. If registerConsoleShortcuts (downstream of pluginQRCode) expects that object shape, this change may break QR payloads. You might instead want:

schema(url) {
  return { http: `${url}?fullscreen=true` };
}

Please double‑check the plugin’s expected schema shape.

examples/react-lazy-bundle/src/App.tsx (1)

1-61: Component logic is solid; consider renaming inner res for clarity

The dynamic imports in useEffect nicely exercise relative string‑literal imports and the onTap handler cleanly toggles alterLogo; overall behavior looks correct for this example.

Minor readability nit: in

void import('./utils/dynamic.js').then((res) => {
  console.info('dynamic import dynamic');
  void res.dynamicAdd(1, 2).then(res => {
    console.info('dynamic add', res);
  });
});

the inner res shadows the outer one. Renaming the inner parameter (e.g. to sum or result) would avoid confusion:

void res.dynamicAdd(1, 2).then(result => {
  console.info('dynamic add', result);
});
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9698a0d and bdc8ce7.

⛔ Files ignored due to path filters (4)
  • examples/react-lazy-bundle/src/assets/arrow.png is excluded by !**/*.png
  • examples/react-lazy-bundle/src/assets/lynx-logo.png is excluded by !**/*.png
  • examples/react-lazy-bundle/src/assets/react-logo.png is excluded by !**/*.png
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (21)
  • .changeset/four-rice-guess.md (1 hunks)
  • examples/react-lazy-bundle/lynx.config.js (1 hunks)
  • examples/react-lazy-bundle/package.json (1 hunks)
  • examples/react-lazy-bundle/src/App.css (1 hunks)
  • examples/react-lazy-bundle/src/App.tsx (1 hunks)
  • examples/react-lazy-bundle/src/index.tsx (1 hunks)
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/add.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/dynamic.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/minus.ts (1 hunks)
  • examples/react-lazy-bundle/tsconfig.json (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/transform/__test__/fixture.spec.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (6 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_lynx.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
✅ Files skipped from review due to trivial changes (1)
  • examples/react-lazy-bundle/package.json
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_transform_import_call.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/test/fixture.spec.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/runtime/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_lynx.js
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (26)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.
📚 Learning: 2025-07-18T04:27:18.291Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.

Applied to files:

  • examples/react-lazy-bundle/src/index.tsx
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • examples/react-lazy-bundle/src/index.tsx
  • .changeset/four-rice-guess.md
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • examples/react-lazy-bundle/lynx.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • examples/react-lazy-bundle/src/index.tsx
  • examples/react-lazy-bundle/src/App.tsx
  • .changeset/four-rice-guess.md
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/lynx.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • examples/react-lazy-bundle/lynx.config.js
  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • .changeset/four-rice-guess.md
  • examples/react-lazy-bundle/lynx.config.js
  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • examples/react-lazy-bundle/lynx.config.js
  • examples/react-lazy-bundle/tsconfig.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/lynx.config.js
  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • examples/react-lazy-bundle/lynx.config.js
  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • examples/react-lazy-bundle/lynx.config.js
  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
📚 Learning: 2025-11-03T08:47:17.714Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1911
File: packages/web-platform/web-tests/tests/react/basic-element-list-estimated-main-axis-size-px/index.jsx:14-24
Timestamp: 2025-11-03T08:47:17.714Z
Learning: In the autoScroll method for XList components in the lynx-family/lynx-stack repository, the `rate` parameter supports plain strings like `'100'` in addition to numbers and strings with unit suffixes (`${number}px`, `${number}rpx`, `${number}ppx`), even though the TypeScript type definition may appear more restrictive.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-09-18T08:12:56.802Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1770
File: packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts:316-318
Timestamp: 2025-09-18T08:12:56.802Z
Learning: In packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts, the current implementation uses cardStyleElement.textContent += for lazy component styles. While this could theoretically invalidate rule indices by reparsing the stylesheet, Sherry-hue indicated that UIDs don't repeat for the same element, making this approach acceptable for now. A future optimization to use separate style elements per entry was discussed but deferred to a separate PR to keep the current lazy bundle PR focused.

Applied to files:

  • examples/react-lazy-bundle/src/App.css
🧬 Code graph analysis (3)
examples/react-lazy-bundle/src/utils/dynamic.ts (1)
examples/react-lazy-bundle/src/utils/add.ts (1)
  • add (1-3)
examples/react-lazy-bundle/src/index.tsx (1)
examples/react-lazy-bundle/src/App.tsx (1)
  • App (8-61)
examples/react-lazy-bundle/lynx.config.js (1)
packages/rspeedy/plugin-qrcode/src/index.ts (1)
  • pluginQRCode (91-155)
🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~5-~5: Use a hyphen to join words.
Context: --- "@lynx-js/react": patch --- Auto define lynx.loadLazyBundle when using `i...

(QB_NEW_EN_HYPHEN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (9)
examples/react-lazy-bundle/src/rspeedy-env.d.ts (1)

1-1: LGTM!

The triple-slash reference follows the established pattern for Rspeedy templates. The @lynx-js/rspeedy dependency is correctly listed in devDependencies, so the type reference to @lynx-js/rspeedy/client is valid.

packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1)

1-9: Snapshot output looks consistent with the intended dynamic‑import transform

The side‑effect import of @lynx-js/react/experimental/lazy/import and the explicit __dynamicImport call inside an async IIFE are both valid and aligned with the expected runtime wiring; there are no correctness issues here.

packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1)

1-3: Simple helper module looks good

foo2 is a clear, side‑effect‑free helper that fits the test case needs; no changes suggested.

examples/react-lazy-bundle/src/utils/minus.ts (1)

1-3: Utility implementation is correct

minus does exactly what its name suggests with clear types and no edge‑case issues for this example.

examples/react-lazy-bundle/src/utils/add.ts (1)

1-3: Add helper looks good

Straightforward, typed add helper; matches how it’s used elsewhere.

examples/react-lazy-bundle/tsconfig.json (1)

1-19: TS config is consistent for an example app

The JSX/runtime settings and noEmit + allowJs/checkJs combo make sense for a purely type‑checked example, and the includes/references look coherent assuming those referenced tsconfig files exist and are composite projects.

If you haven’t already, quickly run pnpm ts:check (or the equivalent) from the repo root to confirm the new project reference chain doesn’t introduce any circular or missing‑project errors.

examples/react-lazy-bundle/src/utils/dynamic.ts (1)

1-4: Dynamic wrapper around add is appropriate

dynamicAdd cleanly demonstrates a relative string‑literal dynamic import and delegates to add, which is exactly the pattern this PR is targeting.

If this is meant to exercise the SWC transform, ensure there’s a corresponding test that snapshots or asserts the transformed import for ./add.js.

examples/react-lazy-bundle/src/index.tsx (1)

1-17: Entry setup and dynamic import look good

The entry correctly wires root.render(<App />) and uses a top‑level void import('./utils/minus.js') to exercise relative dynamic imports; the minimal webpack HMR hook is also fine for this example.

Consider adding or updating a transform test that covers this exact import('./utils/minus.js') shape so regressions in the lazy‑bundle injection are caught automatically.

examples/react-lazy-bundle/src/App.css (1)

1-119: Styling matches the component structure and is syntactically sound

The CSS classes line up with the elements in App.tsx, animations and layout properties are well‑formed, and there are no apparent issues that would block this example from rendering correctly.

@HuJean HuJean disabled auto-merge December 1, 2025 10:02
@HuJean HuJean enabled auto-merge (squash) December 1, 2025 10:02
hzy
hzy previously approved these changes Dec 2, 2025
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: 0

♻️ Duplicate comments (2)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (1)

219-219: Naming aligned with internal lazy bundle semantics.

The field has_inner_lazy_bundle correctly distinguishes relative-path imports (which create inner lazy bundles) from external URL imports (handled via __dynamicImport in the else branch). The naming accurately reflects the specific behavior being tracked.

.changeset/four-rice-guess.md (1)

5-5: Minor grammar fix needed: hyphenate "Auto-define".

As per static analysis, use a hyphen to join the compound modifier.

-Auto define lynx.loadLazyBundle when using `import(/* relative path */)`.
+Auto-define lynx.loadLazyBundle when using `import(/* relative path */)`.
🧹 Nitpick comments (2)
examples/react-lazy-bundle/lynx.config.js (1)

17-24: Consider documenting the purpose of the empty web environment.

The web: {} environment is defined but empty. If this example primarily targets the Lynx environment, consider adding a brief comment explaining why the web environment is included (e.g., for potential dual-target builds or future expansion).

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (1)

266-278: Consider a more robust path transformation approach.

The string replacement .replace("/internal", "") on line 269 is fragile and could produce unexpected results if runtime_pkg contains "/internal" in an unexpected position (e.g., a custom package path like @company/internal-react/internal).

Consider using a more explicit approach:

-        create_import_decl(
-          &format!("{}/experimental/lazy/import", self.opts.runtime_pkg).replace("/internal", ""),
-        ),
+        create_import_decl(
+          &self.opts.runtime_pkg
+            .strip_suffix("/internal")
+            .map(|pkg| format!("{}/experimental/lazy/import", pkg))
+            .unwrap_or_else(|| format!("{}/experimental/lazy/import", self.opts.runtime_pkg)),
+        ),
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bdc8ce7 and 72115af.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (25)
  • .changeset/four-rice-guess.md (1 hunks)
  • examples/react-lazy-bundle/lynx.config.js (1 hunks)
  • examples/react-lazy-bundle/package.json (1 hunks)
  • examples/react-lazy-bundle/src/App.css (1 hunks)
  • examples/react-lazy-bundle/src/App.tsx (1 hunks)
  • examples/react-lazy-bundle/src/index.tsx (1 hunks)
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/add.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/dynamic.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/minus.ts (1 hunks)
  • examples/react-lazy-bundle/tsconfig.json (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/runtime/vitest.config.ts (1 hunks)
  • packages/react/transform/__test__/fixture.spec.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (8 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/index.d.ts (1 hunks)
  • packages/react/transform/rspack-napi/src/index.ts (1 hunks)
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
🚧 Files skipped from review as they are similar to previous changes (14)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/src/utils/dynamic.ts
  • examples/react-lazy-bundle/src/index.tsx
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • examples/react-lazy-bundle/src/App.tsx
  • examples/react-lazy-bundle/src/utils/minus.ts
  • packages/react/transform/test/fixture.spec.js
  • examples/react-lazy-bundle/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_import.js
  • examples/react-lazy-bundle/src/utils/add.ts
  • examples/react-lazy-bundle/src/App.css
  • examples/react-lazy-bundle/tsconfig.json
  • packages/react/runtime/src/index.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (25)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/react/transform/index.d.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/react/transform/index.d.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/rspack-napi/src/index.ts
  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • examples/react-lazy-bundle/lynx.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/react/transform/index.d.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/rspack-napi/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • examples/react-lazy-bundle/lynx.config.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/vitest.config.ts
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-11T06:00:04.376Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:59-61
Timestamp: 2025-08-11T06:00:04.376Z
Learning: In the lynx-family/lynx-stack repository, the `testingLibraryPlugin` in `packages/react/testing-library/src/plugins/vitest.ts` intentionally uses `process.exit` when jsdom installation fails, maintaining consistency with the previous implementation from `packages/react/testing-library/src/vitest.config.js`. This behavior should not be changed to use `this.error` despite being a Vite plugin best practice.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/vitest.config.ts
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-23T08:54:39.966Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/rspack-napi/src/index.ts
  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • examples/react-lazy-bundle/lynx.config.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/rspack-napi/src/index.ts
  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • examples/react-lazy-bundle/lynx.config.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • packages/react/transform/rspack-napi/src/index.ts
  • examples/react-lazy-bundle/lynx.config.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/transform/rspack-napi/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • examples/react-lazy-bundle/lynx.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-09-10T11:42:36.855Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1714
File: packages/react/transform/Cargo.toml:19-19
Timestamp: 2025-09-10T11:42:36.855Z
Learning: In packages/react/transform/Cargo.toml, the crate uses serde derive macros (#[derive(Serialize, Deserialize)]) in multiple files including src/esbuild.rs and src/swc_plugin_extract_str/mod.rs, so the "derive" feature is required when migrating to workspace dependencies.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • examples/react-lazy-bundle/lynx.config.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
🧬 Code graph analysis (1)
examples/react-lazy-bundle/lynx.config.js (1)
packages/rspeedy/plugin-qrcode/src/index.ts (1)
  • pluginQRCode (91-155)
🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~5-~5: Use a hyphen to join words.
Context: --- "@lynx-js/react": patch --- Auto define lynx.loadLazyBundle when using `i...

(QB_NEW_EN_HYPHEN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (10)
examples/react-lazy-bundle/lynx.config.js (1)

1-25: LGTM! Clean example configuration for demonstrating lazy bundle functionality.

The configuration correctly integrates the React Lynx plugin, QR code generation, and conditional performance profiling. The structure follows RSBuild/Rspeedy conventions and provides a solid foundation for the lazy bundle example.

packages/react/runtime/vitest.config.ts (1)

39-39: Change dynamicImport: false to dynamicImport: true or document the intentional exclusion.

Runtime tests extensively use dynamic imports (await import(...)) across multiple test files, including lazy-bundle.test.js which directly tests loadLazyBundle with dynamic imports. Setting dynamicImport: false prevents the new lazy bundle auto-injection feature from being applied to these test files, creating a gap in test coverage for the PR's primary objective. Either enable the transform to validate the feature works in tests, or add a comment explaining why this intentional opt-out is necessary.

⛔ Skipped due to learnings
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:59-61
Timestamp: 2025-08-11T06:00:04.376Z
Learning: In the lynx-family/lynx-stack repository, the `testingLibraryPlugin` in `packages/react/testing-library/src/plugins/vitest.ts` intentionally uses `process.exit` when jsdom installation fails, maintaining consistency with the previous implementation from `packages/react/testing-library/src/vitest.config.js`. This behavior should not be changed to use `this.error` despite being a Vite plugin best practice.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.
packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1)

22-28: LGTM!

The test correctly validates that lynx.loadLazyBundle is defined after a dynamic import attempt. Based on learnings, webpack properties are injected at compile/build time, so the assertion doesn't need to wait for the dynamic import to complete.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)

117-130: LGTM!

The helper function create_import_decl correctly creates a side-effect-only import declaration with the appropriate SWC AST structure. Good extraction of repeated logic.


338-386: Good test coverage for lazy bundle injection scenarios.

The tests properly cover:

  • should_import_lazy_import: external URL with inject_lazy_bundle default (true)
  • should_import_lazy_bundle: relative path import triggering inner lazy bundle
  • should_not_import_lazy: template literal imports (context imports) correctly excluded
packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)

166-173: LGTM!

The injectLazyBundle field correctly mirrors the Rust configuration (inject_lazy_bundle) and follows TypeScript naming conventions. Properly marked as @internal.

packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (1)

29-36: Verify intentional hardcoding of inject_lazy_bundle.

The N-API struct DynamicImportVisitorConfig (lines 13-18) doesn't expose inject_lazy_bundle, so it's hardcoded to true during conversion. This means N-API consumers cannot disable lazy bundle injection.

If this is intentional (always enable for N-API consumers), consider adding a brief comment explaining why. If configurability is needed, the field should be added to the N-API struct.

packages/react/transform/rspack-napi/src/index.ts (1)

78-82: LGTM! Default enables lazy bundle auto-injection.

The new injectLazyBundle: true default aligns with the PR objective to automatically define lynx.loadLazyBundle when dynamic imports are used. This prevents the runtime error mentioned in issue #1954.

packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js (1)

2-4: LGTM! Standard dynamic import pattern.

The async IIFE with dynamic import correctly demonstrates the use case that triggers lazy bundle injection. The webpackChunkName comment provides helpful metadata for webpack's code splitting.

packages/react/transform/index.d.ts (1)

427-428: LGTM! Type definition is correct.

The injectLazyBundle: boolean field is properly typed and documented as @internal, consistent with the other internal configuration fields in DynamicImportVisitorConfig.

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: 1

♻️ Duplicate comments (2)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (1)

216-216: Consider renaming for clarity.

The field name has_inner_lazy_bundle was previously flagged. Since this tracks whether any relative-path dynamic import was found (triggering lazy bundle injection), a name like has_lazy_bundle or needs_lazy_bundle_import might be clearer.

.changeset/four-rice-guess.md (1)

5-5: Hyphenate compound modifier: use "Auto-define" instead of "Auto define".

As previously noted, the compound modifier should be hyphenated for grammatical correctness.

-Auto define lynx.loadLazyBundle when using `import(/* relative path */)`.
+Auto-define lynx.loadLazyBundle when using `import(/* relative path */)`.
🧹 Nitpick comments (4)
examples/react-lazy-bundle/src/index.tsx (1)

7-9: Consider adding error handling for the dynamic import.

While this works for a demo, adding .catch() would make the example more robust and demonstrate proper error handling for lazy bundle loading.

Apply this diff to add error handling:

 void import('./utils/minus.js').then((res) => {
   console.info('dynamic import minus', res.minus(1, 2));
+}).catch((err) => {
+  console.error('Failed to load minus module:', err);
 });
examples/react-lazy-bundle/src/utils/dynamic.ts (1)

1-4: Consider caching the dynamic import to improve performance.

The function performs a dynamic import on every call. While JavaScript engines may cache module loads, explicitly caching the import promise would be more efficient and demonstrate best practices for lazy loading.

Apply this diff to cache the import:

+let addModulePromise: Promise<typeof import('./add.js')> | null = null;
+
 export async function dynamicAdd(a: number, b: number) {
-  const { add } = await import('./add.js');
+  if (!addModulePromise) {
+    addModulePromise = import('./add.js');
+  }
+  const { add } = await addModulePromise;
   return add(a, b);
 }
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (1)

263-268: String manipulation for path construction is fragile.

The .replace("/internal", "") approach assumes runtime_pkg always contains /internal suffix. If the config ever changes or someone provides a custom runtime_pkg without that suffix, the path construction will be incorrect.

Consider making this more explicit:

-        create_import_decl(
-          &format!("{}/experimental/lazy/import", self.opts.runtime_pkg).replace("/internal", ""),
-        ),
+        create_import_decl("@lynx-js/react/experimental/lazy/import"),

Alternatively, if the base package needs to be configurable, consider adding a separate config field for the base package name.

packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js (1)

1-1: Data-URL side-effect import wiring lynx.loadLazyBundle looks correct; please verify URL/encoding and generation path

The new top-level import ensures lynx.loadLazyBundle is assigned before any dynamic imports run in this module, which matches the PR goal of avoiding lynx.loadLazyBundle is not a function at runtime.

Two things to double‑check:

  1. The data:text/javascript;charset=utf-8,... specifier currently embeds raw JS (import { loadLazyBundle } ...;lynx.loadLazyBundle = loadLazyBundle;) without URL-encoding. Some loaders/runtimes (especially browser/Node URL parsers) can be strict about data: URLs being valid URLs, which may require percent‑encoding spaces and certain punctuation. Please confirm this exact specifier works across the bundlers/runtimes you support; if not, consider having the transform encode the body (e.g., via encodeURIComponent or equivalent) rather than changing the snapshot by hand.

  2. Since files under tests/__swc_snapshots__/ are auto-generated, ensure this change is the result of the updated swc_plugin_dynamic_import transform logic, not a manual edit to the snapshot. Based on learnings, snapshot files should only reflect generator changes, not be the primary place to implement logic.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 72115af and b13040f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (23)
  • .changeset/four-rice-guess.md (1 hunks)
  • examples/react-lazy-bundle/lynx.config.js (1 hunks)
  • examples/react-lazy-bundle/package.json (1 hunks)
  • examples/react-lazy-bundle/src/App.css (1 hunks)
  • examples/react-lazy-bundle/src/App.tsx (1 hunks)
  • examples/react-lazy-bundle/src/index.tsx (1 hunks)
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/add.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/dynamic.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/minus.ts (1 hunks)
  • examples/react-lazy-bundle/tsconfig.json (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/runtime/vitest.config.ts (1 hunks)
  • packages/react/transform/__test__/fixture.spec.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (6 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js (1 hunks)
  • packages/react/transform/rspack-napi/src/index.ts (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
🚧 Files skipped from review as they are similar to previous changes (10)
  • examples/react-lazy-bundle/src/App.tsx
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • packages/react/runtime/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_bundle.js
  • examples/react-lazy-bundle/src/App.css
  • examples/react-lazy-bundle/tsconfig.json
  • packages/react/transform/test/fixture.spec.js
  • examples/react-lazy-bundle/src/utils/add.ts
  • examples/react-lazy-bundle/lynx.config.js
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (26)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:52-72
Timestamp: 2025-08-13T11:36:12.075Z
Learning: The lynx-stack project requires Node.js >=22 as specified in package.json engines, so Node.js compatibility fallbacks for features introduced before v22 are unnecessary.
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • examples/react-lazy-bundle/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • examples/react-lazy-bundle/package.json
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • examples/react-lazy-bundle/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-11T06:00:04.376Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:59-61
Timestamp: 2025-08-11T06:00:04.376Z
Learning: In the lynx-family/lynx-stack repository, the `testingLibraryPlugin` in `packages/react/testing-library/src/plugins/vitest.ts` intentionally uses `process.exit` when jsdom installation fails, maintaining consistency with the previous implementation from `packages/react/testing-library/src/vitest.config.js`. This behavior should not be changed to use `this.error` despite being a Vite plugin best practice.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • examples/react-lazy-bundle/src/index.tsx
  • examples/react-lazy-bundle/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • examples/react-lazy-bundle/src/utils/dynamic.ts
  • .changeset/four-rice-guess.md
  • packages/react/transform/rspack-napi/src/index.ts
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • examples/react-lazy-bundle/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • .changeset/four-rice-guess.md
  • packages/react/transform/rspack-napi/src/index.ts
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-07-18T04:27:18.291Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.

Applied to files:

  • examples/react-lazy-bundle/src/index.tsx
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • examples/react-lazy-bundle/src/index.tsx
  • examples/react-lazy-bundle/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • .changeset/four-rice-guess.md
  • packages/react/transform/rspack-napi/src/index.ts
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • examples/react-lazy-bundle/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • .changeset/four-rice-guess.md
  • packages/react/transform/rspack-napi/src/index.ts
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • examples/react-lazy-bundle/package.json
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • examples/react-lazy-bundle/package.json
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • examples/react-lazy-bundle/package.json
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • examples/react-lazy-bundle/package.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-23T08:54:39.966Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/rspack-napi/src/index.ts
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-09-10T11:42:36.855Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1714
File: packages/react/transform/Cargo.toml:19-19
Timestamp: 2025-09-10T11:42:36.855Z
Learning: In packages/react/transform/Cargo.toml, the crate uses serde derive macros (#[derive(Serialize, Deserialize)]) in multiple files including src/esbuild.rs and src/swc_plugin_extract_str/mod.rs, so the "derive" feature is required when migrating to workspace dependencies.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
🧬 Code graph analysis (3)
examples/react-lazy-bundle/src/index.tsx (1)
examples/react-lazy-bundle/src/App.tsx (1)
  • App (5-30)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)
packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (1)
  • new (67-71)
packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)
  • DynamicImportVisitorConfig (166-171)
examples/react-lazy-bundle/src/utils/dynamic.ts (1)
examples/react-lazy-bundle/src/utils/add.ts (1)
  • add (1-3)
🪛 GitHub Check: code-style-check
packages/react/transform/rspack-napi/src/index.ts

[failure] 81-81:
Type 'boolean | DynamicImportVisitorConfig | { runtimePkg: string; layer: string; injectLazyBundle: true; }' is not assignable to type 'boolean | DynamicImportVisitorConfig'.

🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~5-~5: Use a hyphen to join words.
Context: --- "@lynx-js/react": patch --- Auto define lynx.loadLazyBundle when using `i...

(QB_NEW_EN_HYPHEN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (10)
examples/react-lazy-bundle/package.json (1)

1-22: Package structure follows monorepo conventions; verify supporting example files and version strategy.

The configuration correctly uses workspace:* for local packages and marks itself as private. However, a few items warrant verification:

  1. Supporting files: Ensure all necessary example assets are included in the PR (lynx.config.js, App.tsx, utility files demonstrating lazy bundle usage, etc.).
  2. Preact-devtools version: Line 15 pins an experimental build (^5.0.1-cf9aef5). Confirm this is intentional for this example.
  3. Types version: Line 19 pins @lynx-js/types@3.4.11 without a caret. Verify this aligns with version pinning strategy used in other example packages.
  4. Metadata fields: Confirm that omitting description, author, and license fields is the convention for example packages in this monorepo.
packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1)

1-3: LGTM! Test fixture is appropriate.

This test fixture is correctly implemented for validating the lazy bundle loading functionality. The simple function returning a constant value is suitable for testing dynamic imports and verifying that lynx.loadLazyBundle is properly defined.

examples/react-lazy-bundle/src/utils/minus.ts (1)

1-3: LGTM! Clean example utility.

The function is correctly implemented and serves its purpose as a test case for lazy bundle loading.

examples/react-lazy-bundle/src/index.tsx (2)

1-5: LGTM! Proper setup imports.

The imports correctly set up the development environment and bring in necessary components.


11-17: LGTM! Standard render and HMR setup.

The rendering logic and hot module replacement configuration are correctly implemented.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)

334-361: Test coverage looks good.

The new tests (should_import_lazy_import, should_import_lazy_bundle, should_not_import_lazy) cover the key scenarios:

  • External URL imports that need __dynamicImport wrapper
  • Relative path imports that trigger lazy bundle injection
  • Template literal imports that should be ignored

270-275: Data URL import approach is correct and guaranteed to work.

The data URL effectively injects lynx.loadLazyBundle during module evaluation. The lynx global is guaranteed to exist because webpack's runtime-wrapper-webpack-plugin injects lynx = lynx || {}; as part of the module wrapper initialization. The unencoded data URL is safe for this use case since the content contains only ASCII characters with no special characters requiring encoding.

packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1)

1-9: Snapshot correctly reflects external URL handling.

The transformed output shows:

  1. The experimental lazy import is prepended
  2. The __dynamicImport helper is imported from internal
  3. External URL (https://) is wrapped with __dynamicImport instead of native import()

This aligns with the transform logic where external URLs use the __dynamicImport wrapper path.

packages/react/runtime/vitest.config.ts (1)

39-39: Disabling dynamic import transform for runtime tests is appropriate.

Setting dynamicImport: false prevents the new lazy bundle injection from affecting runtime unit tests, which should test runtime behavior in isolation rather than transform behavior.

packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1)

22-28: Test correctly validates the bug fix.

The test structure is appropriate:

  1. Attempts a dynamic import (which triggers the transform to inject loadLazyBundle)
  2. Catches and ignores the expected network error
  3. Verifies lynx.loadLazyBundle is defined

Based on learnings, webpack properties are injected at compile time, so the assertion correctly runs synchronously after the import attempt.

@HuJean HuJean force-pushed the p/hujing/lazy-bundle branch from b13040f to 8c5b505 Compare December 2, 2025 07:49
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: 0

♻️ Duplicate comments (1)
.changeset/four-rice-guess.md (1)

5-5: Hyphenate “Auto-define” in the changeset description.

Change the leading phrase to use a hyphen for correct compound wording:

-Auto define lynx.loadLazyBundle when using `import(/* relative path */)`.
+Auto-define lynx.loadLazyBundle when using `import(/* relative path */)`.
🧹 Nitpick comments (4)
examples/react-lazy-bundle/src/utils/dynamic.ts (1)

1-4: Dynamic import helper is correct; consider adding explicit return type

The lazy import and delegation to add(a, b) look good and match the relative-path dynamic import requirement. You might optionally add an explicit return type for clarity:

-export async function dynamicAdd(a: number, b: number) {
+export async function dynamicAdd(a: number, b: number): Promise<number> {

This makes the intent of returning a Promise<number> obvious at call sites, but is not strictly required.

examples/react-lazy-bundle/lynx.config.js (1)

1-25: Confirm QR code schema return type (string vs { http: url }).

pluginQRCode’s default schema maps the URL to an object like { http: url }, while this example overrides it to return a plain string:

schema(url) {
  return `${url}?fullscreen=true`;
}

If registerConsoleShortcuts / the QR plugin expect the original object shape, consider:

schema(url) {
  return { http: `${url}?fullscreen=true` };
}

Otherwise, please double‑check the types to ensure this override is valid and doesn’t break QR code generation.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)

40-48: Scope of has_inner_lazy_bundle and lazy-bundle injection.

has_inner_lazy_bundle is set for any non‑external string‑literal dynamic import:

  • It fires for import("./index.js") and import("./index.js", { with: { type: "component" } }) (good, matches the issue intent).
  • It also fires for bare specifiers like import("some-pkg") and other non‑URL string literals, which will also cause the data‑URL lazy‑bundle import to be prepended.

If the goal is only to auto‑define lynx.loadLazyBundle for “internal”/relative paths, you might want to narrow this condition, e.g. to prefixes like "./" / "../" (or however “relative” is defined in your bundlers). If it’s intentional to cover all non‑URL string specifiers, this is fine, but might be worth a short comment to avoid surprises for future readers.

Also applies to: 63-70, 168-193, 216-217, 232-276


114-127: Check prepend_stmt insertion order for the three injected imports.

Given how prepend_stmt works, calling it in this order:

  1. runtime named import (__dynamicImport),
  2. lazy runtime import via create_import_decl("{runtimePkg}/experimental/lazy/import"),
  3. data‑URL import that assigns lynx.loadLazyBundle,

likely results in the final module order being:

  1. data‑URL import,
  2. lazy/import side‑effect import,
  3. runtime named import.

If any of these need to run in a specific order (e.g., lazy/import expecting lynx.loadLazyBundle to be assigned only after its own side‑effects), it may be safer to assert/adjust the order explicitly (or add a brief comment documenting that this order is intentional and tested across bundlers).

Also applies to: 263-275

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b13040f and 8c5b505.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (22)
  • .changeset/four-rice-guess.md (1 hunks)
  • examples/react-lazy-bundle/lynx.config.js (1 hunks)
  • examples/react-lazy-bundle/package.json (1 hunks)
  • examples/react-lazy-bundle/src/App.css (1 hunks)
  • examples/react-lazy-bundle/src/App.tsx (1 hunks)
  • examples/react-lazy-bundle/src/index.tsx (1 hunks)
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/add.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/dynamic.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/minus.ts (1 hunks)
  • examples/react-lazy-bundle/tsconfig.json (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/runtime/vitest.config.ts (1 hunks)
  • packages/react/transform/__test__/fixture.spec.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (6 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
✅ Files skipped from review due to trivial changes (1)
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
🚧 Files skipped from review as they are similar to previous changes (13)
  • examples/react-lazy-bundle/src/index.tsx
  • examples/react-lazy-bundle/src/App.tsx
  • packages/react/runtime/vitest.config.ts
  • examples/react-lazy-bundle/src/App.css
  • examples/react-lazy-bundle/src/utils/minus.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_bundle.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_transform_import_call.js
  • examples/react-lazy-bundle/tsconfig.json
  • packages/react/transform/test/fixture.spec.js
  • examples/react-lazy-bundle/src/utils/add.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_import.js
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (25)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • .changeset/four-rice-guess.md
  • examples/react-lazy-bundle/package.json
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/react/runtime/src/index.ts
  • examples/react-lazy-bundle/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • .changeset/four-rice-guess.md
  • examples/react-lazy-bundle/package.json
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/react/runtime/src/index.ts
  • examples/react-lazy-bundle/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • examples/react-lazy-bundle/lynx.config.js
  • examples/react-lazy-bundle/src/utils/dynamic.ts
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/react/runtime/src/index.ts
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/react/runtime/src/index.ts
  • examples/react-lazy-bundle/package.json
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/react/runtime/src/index.ts
  • examples/react-lazy-bundle/package.json
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-18T04:27:18.291Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.

Applied to files:

  • packages/react/runtime/src/index.ts
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/react/runtime/src/index.ts
  • examples/react-lazy-bundle/package.json
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/runtime/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-08-13T09:20:00.936Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1502
File: packages/react/testing-library/types/entry.d.ts:71-71
Timestamp: 2025-08-13T09:20:00.936Z
Learning: In lynx-js/react testing library, wrapper components must have children as a required prop because they are always called with `h(WrapperComponent, null, innerElement)` where innerElement is passed as children. The type `React.JSXElementConstructor<{ children: React.ReactNode }>` correctly requires children to be mandatory.

Applied to files:

  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • examples/react-lazy-bundle/package.json
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • examples/react-lazy-bundle/package.json
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • examples/react-lazy-bundle/package.json
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • examples/react-lazy-bundle/package.json
  • examples/react-lazy-bundle/lynx.config.js
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-09-10T11:42:36.855Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1714
File: packages/react/transform/Cargo.toml:19-19
Timestamp: 2025-09-10T11:42:36.855Z
Learning: In packages/react/transform/Cargo.toml, the crate uses serde derive macros (#[derive(Serialize, Deserialize)]) in multiple files including src/esbuild.rs and src/swc_plugin_extract_str/mod.rs, so the "derive" feature is required when migrating to workspace dependencies.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
🧬 Code graph analysis (3)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)
packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (1)
  • new (67-71)
packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)
  • DynamicImportVisitorConfig (166-171)
examples/react-lazy-bundle/lynx.config.js (1)
packages/rspeedy/plugin-qrcode/src/index.ts (1)
  • pluginQRCode (91-155)
examples/react-lazy-bundle/src/utils/dynamic.ts (1)
examples/react-lazy-bundle/src/utils/add.ts (1)
  • add (1-3)
🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~5-~5: Use a hyphen to join words.
Context: --- "@lynx-js/react": patch --- Auto define lynx.loadLazyBundle when using `i...

(QB_NEW_EN_HYPHEN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / clippy
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (4)
packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1)

1-3: foo2 test helper looks fine.

Simple named export returning a constant is clear and matches typical test fixture patterns; no issues.

examples/react-lazy-bundle/package.json (1)

1-22: Example package.json looks consistent.

Workspace wiring, scripts (rspeedy build/dev, vitest --typecheck.only), and dependencies/devDependencies all look reasonable for an internal example package.

packages/react/runtime/src/index.ts (1)

5-21: Importing lazy directly from preact/compat is appropriate.

Pulling lazy from preact/compat and re‑exporting it (both via the default export object and named exports) keeps the public API intact while removing the custom wrapper; this aligns with offloading lynx.loadLazyBundle wiring to the transform/runtime side.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (1)

334-382: New tests nicely cover the lazy-import and lazy-bundle cases.

The added tests (should_import_lazy_import, should_import_lazy_bundle, should_not_import_lazy) exercise:

  • external URL + { with: { type: "component" } },
  • plain relative import,
  • template literal import ignored by the transform,

which gives good regression coverage for both the new injection paths and the “no-op” case.

@HuJean HuJean force-pushed the p/hujing/lazy-bundle branch from 8c5b505 to 5cb8f8c Compare December 2, 2025 08:12
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: 0

♻️ Duplicate comments (1)
.changeset/four-rice-guess.md (1)

1-5: Minor wording: hyphenate “Auto‑define”

Consider changing the description to:

Auto-define lynx.loadLazyBundle when using `import(/* relative path */)`.

to match standard compound‑verb hyphenation.

🧹 Nitpick comments (1)
examples/react-lazy-bundle/src/utils/dynamic.ts (1)

1-4: Consider adding explicit return type annotation.

The function correctly demonstrates lazy loading via dynamic import with a relative path, which aligns with the PR's objective to auto-define lynx.loadLazyBundle. The implementation is clean and correct.

For improved clarity in example code, consider adding an explicit return type annotation:

-export async function dynamicAdd(a: number, b: number) {
+export async function dynamicAdd(a: number, b: number): Promise<number> {
   const { add } = await import('./add.js');
   return add(a, b);
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c5b505 and 5cb8f8c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (23)
  • .changeset/four-rice-guess.md (1 hunks)
  • examples/react-lazy-bundle/lynx.config.js (1 hunks)
  • examples/react-lazy-bundle/package.json (1 hunks)
  • examples/react-lazy-bundle/src/App.css (1 hunks)
  • examples/react-lazy-bundle/src/App.tsx (1 hunks)
  • examples/react-lazy-bundle/src/index.tsx (1 hunks)
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/add.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/dynamic.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/minus.ts (1 hunks)
  • examples/react-lazy-bundle/tsconfig.json (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/runtime/vitest.config.ts (1 hunks)
  • packages/react/testing-library/src/vitest.config.js (1 hunks)
  • packages/react/transform/__test__/fixture.spec.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (6 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_transform_import_call.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
🚧 Files skipped from review as they are similar to previous changes (13)
  • examples/react-lazy-bundle/src/App.tsx
  • examples/react-lazy-bundle/src/utils/add.ts
  • examples/react-lazy-bundle/src/index.tsx
  • examples/react-lazy-bundle/lynx.config.js
  • packages/react/runtime/vitest.config.ts
  • packages/react/runtime/src/index.ts
  • examples/react-lazy-bundle/src/utils/minus.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_transform_import_call.js
  • packages/react/transform/test/fixture.spec.js
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • examples/react-lazy-bundle/tsconfig.json
  • examples/react-lazy-bundle/src/App.css
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (26)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1770
File: packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts:316-318
Timestamp: 2025-09-18T08:12:56.802Z
Learning: In packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts, the current implementation uses cardStyleElement.textContent += for lazy component styles. While this could theoretically invalidate rule indices by reparsing the stylesheet, Sherry-hue indicated that UIDs don't repeat for the same element, making this approach acceptable for now. A future optimization to use separate style elements per entry was discussed but deferred to a separate PR to keep the current lazy bundle PR focused.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/package.json
  • packages/react/testing-library/src/vitest.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • examples/react-lazy-bundle/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/package.json
  • packages/react/testing-library/src/vitest.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/package.json
  • packages/react/testing-library/src/vitest.config.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/testing-library/src/vitest.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/package.json
  • packages/react/testing-library/src/vitest.config.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-11T06:00:04.376Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:59-61
Timestamp: 2025-08-11T06:00:04.376Z
Learning: In the lynx-family/lynx-stack repository, the `testingLibraryPlugin` in `packages/react/testing-library/src/plugins/vitest.ts` intentionally uses `process.exit` when jsdom installation fails, maintaining consistency with the previous implementation from `packages/react/testing-library/src/vitest.config.js`. This behavior should not be changed to use `this.error` despite being a Vite plugin best practice.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/package.json
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
  • .changeset/four-rice-guess.md
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/testing-library/src/vitest.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
📚 Learning: 2025-09-10T11:42:36.855Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1714
File: packages/react/transform/Cargo.toml:19-19
Timestamp: 2025-09-10T11:42:36.855Z
Learning: In packages/react/transform/Cargo.toml, the crate uses serde derive macros (#[derive(Serialize, Deserialize)]) in multiple files including src/esbuild.rs and src/swc_plugin_extract_str/mod.rs, so the "derive" feature is required when migrating to workspace dependencies.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • packages/react/testing-library/src/vitest.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • examples/react-lazy-bundle/package.json
  • .changeset/four-rice-guess.md
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • examples/react-lazy-bundle/package.json
  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • examples/react-lazy-bundle/package.json
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • examples/react-lazy-bundle/package.json
  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • examples/react-lazy-bundle/package.json
📚 Learning: 2025-09-23T08:54:39.966Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.

Applied to files:

  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
🧬 Code graph analysis (2)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)
packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (1)
  • new (67-71)
packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)
  • DynamicImportVisitorConfig (166-171)
examples/react-lazy-bundle/src/utils/dynamic.ts (1)
examples/react-lazy-bundle/src/utils/add.ts (1)
  • add (1-3)
🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~5-~5: Use a hyphen to join words.
Context: --- "@lynx-js/react": patch --- Auto define lynx.loadLazyBundle when using `i...

(QB_NEW_EN_HYPHEN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (10)
examples/react-lazy-bundle/package.json (1)

1-21: ✓ Package metadata and configuration look good.

The package.json is well-structured for the new lazy-bundle example:

  • Name, scoping, and privacy settings follow monorepo conventions
  • Build tooling (rspeedy, plugins) is consistent with other React examples
  • Dependencies are minimal and focused: only @lynx-js/react with workspace reference
  • DevDependencies are appropriate for a Lynx/React example project

Note: The package correctly avoids explicitly depending on lazy-bundle runtime, which aligns with the PR objective of auto-defining lynx.loadLazyBundle via the SWC transform.

Please verify that the example source code (under examples/react-lazy-bundle/src) correctly demonstrates dynamic imports with relative paths (e.g., import("./Component")) and that these imports resolve correctly after the SWC transform is applied.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (4)

40-48: Internal flag wiring for lazy bundle import looks sound

has_inner_lazy_bundle is correctly introduced and initialized, and the struct’s default still flows through DynamicImportVisitor::new, so there’s no risk of an uninitialized or stale flag between runs. This keeps the new behavior fully internal to the visitor.

Also applies to: 59-70


114-127: Helper create_import_decl keeps import construction consistent

Extracting the side‑effect import creation into create_import_decl avoids duplicating the ImportDecl boilerplate and ensures both the experimental/lazy/import and data‑URL imports share identical flags (ImportPhase::Evaluation, type_only, with). No issues here.


185-217: Lazy‑bundle auto‑definition behavior matches the issue goals

For non‑external string‑literal import() calls (e.g. import('./index.js')), you:

  • Reject invalid option objects as before.
  • Attach the webpackChunkName comment.
  • Set has_inner_lazy_bundle = true, which later prepends the data‑URL import that defines lynx.loadLazyBundle.

External URLs (https://, http://, //) continue to go through __dynamicImport plus experimental/lazy/import without triggering the inner lazy‑bundle import, which keeps the “relative / non‑external” case special as described in the issue.

Combined modules that mix local and external dynamic imports will get both imports (lazy/import + data‑URL) once, which is acceptable.

Looks correct and well‑scoped.

Also applies to: 270-275


321-382: New dynamic‑import tests cover key branches

The added tests exercise:

  • External URL with { with: { type: "component" } }should_import_lazy_import.
  • Relative path string literal → should_import_lazy_bundle.
  • Template literal context import → should_not_import_lazy.

That gives good coverage of the new behavior and the intentional “ignore template imports” path. No additional cases seem strictly necessary for this PR.

packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1)

22-29: Good assertion to lock in lazy runtime availability

The extra expect(lynx.loadLazyBundle).not.toBeUndefined(); after the dynamic import (with errors swallowed) is a solid regression test that the lazy runtime is wired even when the external URL fails to load.

packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1)

1-9: Snapshot matches new dynamic‑import transform

This snapshot correctly reflects the transform: side‑effect import of @lynx-js/react/experimental/lazy/import plus a named import of __dynamicImport from the internal runtime, then delegating the import("https://…", { with: { type: "component" } }) call to __dynamicImport. No manual edits needed; future changes should continue to flow from the transform logic.

packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js (1)

1-4: Snapshot correctly captures inner lazy‑bundle wiring

The generated code—data‑URL import that assigns lynx.loadLazyBundle, followed by the annotated import("./index.js")—is exactly what the new has_inner_lazy_bundle path is supposed to emit. This looks consistent with the transform; no further changes needed.

packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1)

2-7: Updated test appropriately targets relative dynamic imports

Switching to an async test that await import('./foo.js') and await import('./foo2.js') before asserting lynx.loadLazyBundle is defined directly validates the new behavior for local code‑split bundles. This is a clear regression test for the original bug.

packages/react/testing-library/src/vitest.config.js (1)

224-250: This setting is intentional and correct. dynamicImport: false disables the dynamic‑import transform in the test environment, which is appropriate since tests should not apply transforms that require special runtime support. This is consistent with the internal runtime test config and maintains a clear separation between test (transform disabled) and production (transform enabled) behavior.

@HuJean HuJean force-pushed the p/hujing/lazy-bundle branch from 5cb8f8c to 3afd3e9 Compare December 2, 2025 09:58
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: 0

♻️ Duplicate comments (1)
.changeset/four-rice-guess.md (1)

5-5: Hyphenate “Auto define” in the changeset summary.

Use the compound modifier form for clarity and consistency with prior feedback.

-Auto define lynx.loadLazyBundle when using `import(/* relative path */)`.
+Auto-define lynx.loadLazyBundle when using `import(/* relative path */)`.
🧹 Nitpick comments (1)
examples/react-lazy-bundle/src/App.tsx (1)

11-15: Consider renaming the inner res parameter for clarity

In the nested res.dynamicAdd(1, 2).then(res => { ... }), the inner res shadows the outer module namespace, which can be mildly confusing when reading. Renaming the inner one (e.g. to value or result) would improve readability without behavior changes.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cb8f8c and 3afd3e9.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (27)
  • .changeset/four-rice-guess.md (1 hunks)
  • examples/react-lazy-bundle/lynx.config.js (1 hunks)
  • examples/react-lazy-bundle/package.json (1 hunks)
  • examples/react-lazy-bundle/src/App.css (1 hunks)
  • examples/react-lazy-bundle/src/App.tsx (1 hunks)
  • examples/react-lazy-bundle/src/index.tsx (1 hunks)
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/add.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/dynamic.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/minus.ts (1 hunks)
  • examples/react-lazy-bundle/tsconfig.json (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/runtime/vitest.config.ts (1 hunks)
  • packages/react/testing-library/src/vitest.config.js (1 hunks)
  • packages/react/transform/__test__/fixture.spec.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (8 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (3 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/index.d.ts (1 hunks)
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts (1 hunks)
  • packages/webpack/css-extract-webpack-plugin/test/diagnostic/error/sass/expected/rspack.txt (1 hunks)
  • packages/webpack/css-extract-webpack-plugin/test/diagnostic/error/sass/expected/webpack.txt (4 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
✅ Files skipped from review due to trivial changes (1)
  • packages/webpack/css-extract-webpack-plugin/test/diagnostic/error/sass/expected/rspack.txt
🚧 Files skipped from review as they are similar to previous changes (12)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_import.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js
  • examples/react-lazy-bundle/package.json
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/lynx.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/test/fixture.spec.js
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • examples/react-lazy-bundle/src/utils/dynamic.ts
  • examples/react-lazy-bundle/tsconfig.json
  • examples/react-lazy-bundle/src/index.tsx
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (29)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • examples/react-lazy-bundle/src/App.tsx
  • .changeset/four-rice-guess.md
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • examples/react-lazy-bundle/src/App.tsx
  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • .changeset/four-rice-guess.md
  • packages/react/runtime/src/index.ts
  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • examples/react-lazy-bundle/src/App.tsx
  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • .changeset/four-rice-guess.md
  • packages/react/runtime/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • .changeset/four-rice-guess.md
  • packages/react/runtime/src/index.ts
  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-08-11T06:00:04.376Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:59-61
Timestamp: 2025-08-11T06:00:04.376Z
Learning: In the lynx-family/lynx-stack repository, the `testingLibraryPlugin` in `packages/react/testing-library/src/plugins/vitest.ts` intentionally uses `process.exit` when jsdom installation fails, maintaining consistency with the previous implementation from `packages/react/testing-library/src/vitest.config.js`. This behavior should not be changed to use `this.error` despite being a Vite plugin best practice.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/runtime/vitest.config.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/testing-library/src/vitest.config.js
  • packages/webpack/css-extract-webpack-plugin/test/diagnostic/error/sass/expected/webpack.txt
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • packages/react/runtime/src/index.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/webpack/css-extract-webpack-plugin/test/diagnostic/error/sass/expected/webpack.txt
📚 Learning: 2025-09-29T06:43:40.182Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-09-29T06:43:40.182Z
Learning: Applies to .changeset/*.md : For contributions, generate and commit a Changeset describing your changes

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/react/runtime/src/index.ts
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-18T04:27:18.291Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.

Applied to files:

  • packages/react/runtime/src/index.ts
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/react/runtime/src/index.ts
  • packages/react/testing-library/src/vitest.config.js
  • packages/react/transform/index.d.ts
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • packages/react/runtime/src/index.ts
📚 Learning: 2025-08-13T09:20:00.936Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1502
File: packages/react/testing-library/types/entry.d.ts:71-71
Timestamp: 2025-08-13T09:20:00.936Z
Learning: In lynx-js/react testing library, wrapper components must have children as a required prop because they are always called with `h(WrapperComponent, null, innerElement)` where innerElement is passed as children. The type `React.JSXElementConstructor<{ children: React.ReactNode }>` correctly requires children to be mandatory.

Applied to files:

  • packages/react/runtime/src/index.ts
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs
📚 Learning: 2025-09-10T11:42:36.855Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1714
File: packages/react/transform/Cargo.toml:19-19
Timestamp: 2025-09-10T11:42:36.855Z
Learning: In packages/react/transform/Cargo.toml, the crate uses serde derive macros (#[derive(Serialize, Deserialize)]) in multiple files including src/esbuild.rs and src/swc_plugin_extract_str/mod.rs, so the "derive" feature is required when migrating to workspace dependencies.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/react/testing-library/src/vitest.config.js
📚 Learning: 2025-09-18T08:12:56.802Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1770
File: packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts:316-318
Timestamp: 2025-09-18T08:12:56.802Z
Learning: In packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts, the current implementation uses cardStyleElement.textContent += for lazy component styles. While this could theoretically invalidate rule indices by reparsing the stylesheet, Sherry-hue indicated that UIDs don't repeat for the same element, making this approach acceptable for now. A future optimization to use separate style elements per entry was discussed but deferred to a separate PR to keep the current lazy bundle PR focused.

Applied to files:

  • examples/react-lazy-bundle/src/App.css
📚 Learning: 2025-09-23T08:54:39.966Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.

Applied to files:

  • packages/webpack/css-extract-webpack-plugin/test/diagnostic/error/sass/expected/webpack.txt
📚 Learning: 2025-09-23T08:53:56.927Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/src/loader.ts:244-251
Timestamp: 2025-09-23T08:53:56.927Z
Learning: In webpack CSS extraction plugins, when storing per-module dependencies in a compiler-scoped map like cssModuleId2Deps, the map should not be reset at compilation start because in incremental compilation (watch mode/HMR), only changed files pass through the loader. Unchanged modules need their dependency information to persist between compilations so the plugin can access all modules' dependencies when generating CSS output.

Applied to files:

  • packages/webpack/css-extract-webpack-plugin/test/diagnostic/error/sass/expected/webpack.txt
🧬 Code graph analysis (4)
examples/react-lazy-bundle/src/App.tsx (1)
packages/react/transform/src/wasm.js (1)
  • view (24-28)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)
packages/react/transform/index.d.ts (1)
  • DynamicImportVisitorConfig (422-429)
packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (2)
  • default (23-29)
  • default (63-65)
packages/react/testing-library/src/vitest.config.js (1)
packages/react/testing-library/loaders/jsx-loader.js (1)
  • runtimePkgName (9-9)
packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (3)
packages/react/transform/index.d.ts (1)
  • DynamicImportVisitorConfig (422-429)
packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)
  • DynamicImportVisitorConfig (166-173)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)
  • default (34-40)
  • default (57-59)
🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~5-~5: Use a hyphen to join words.
Context: --- "@lynx-js/react": patch --- Auto define lynx.loadLazyBundle when using `i...

(QB_NEW_EN_HYPHEN)

🔇 Additional comments (12)
packages/webpack/css-extract-webpack-plugin/test/diagnostic/error/sass/expected/webpack.txt (1)

8-8: Verify that manual edits to expected output files are appropriate.

This file appears to be an expected test output used for diagnostic comparison. According to learnings from prior reviews, similar auto-generated test outputs should not be manually edited; instead, the source fixtures should be updated and outputs regenerated.

Additionally, the connection between these path changes (absolute <ROOT> → relative ../../../../../../../) and the PR objective (auto-define lynx.loadLazyBundle for dynamic imports) is unclear. This file is for CSS extraction plugin diagnostics, not dynamic import handling.

Please clarify:

  1. Is this an auto-generated expected output file, or is it manually maintained?
  2. What is the relationship between these path changes and the lazy bundle feature described in the PR objectives?
  3. If manually maintained, what prompted the change from absolute to relative paths?

Also applies to: 18-18, 36-36, 49-49

examples/react-lazy-bundle/src/utils/minus.ts (1)

1-3: LGTM!

The utility function is correct and appropriate for demonstrating lazy bundle loading with dynamic imports.

examples/react-lazy-bundle/src/utils/add.ts (1)

1-3: Utility function implementation looks correct

Typed signature and implementation are straightforward and correct for the intended demo usage.

examples/react-lazy-bundle/src/App.tsx (1)

5-17: Dynamic import usage aligns with lazy-bundle objectives

The useEffect hook’s fire-and-forget dynamic imports with relative .js paths (for ./utils/add.js and ./utils/dynamic.js) cleanly exercise the lazy-bundle transform without extra runtime wiring, which fits the repo’s preference for minimal runtime checks in demo code. Based on learnings, this style is consistent with the stack’s compile-time–first approach.

examples/react-lazy-bundle/src/App.css (1)

1-34: Styles match component structure and are consistent

CSS classes and the global text rule line up with the JSX structure in App.tsx; looks good for the example use case.

packages/react/runtime/vitest.config.ts (1)

27-48: Disabling dynamic-import transform for runtime tests looks appropriate.

Setting dynamicImport: false here keeps the runtime Vitest setup free from dynamic-import side effects while the transform itself is covered in its own test suite.

packages/react/runtime/src/index.ts (1)

7-84: Using preact/compat’s lazy directly is consistent and safe.

Importing lazy from preact/compat and exposing it via both default and named exports keeps the runtime surface aligned with Preact, while lazy-bundle wiring is now handled by the dynamic-import transform.

packages/react/transform/index.d.ts (1)

422-429: injectLazyBundle flag is correctly surfaced in the public TS config.

The optional injectLazyBundle?: boolean on DynamicImportVisitorConfig matches the Rust inject_lazy_bundle: Option<bool> and preserves default-on behavior (None treated as enabled), which is what you want for existing callers.

Please double-check other call sites of dynamicImport in this repo to ensure any explicit config objects that should disable auto lazy-bundle injection now set injectLazyBundle: false explicitly.

packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)

166-173: Dynamic-import typings stay consistent across transform entry points.

Adding injectLazyBundle?: boolean here keeps the SWC plugin typings in sync with packages/react/transform/index.d.ts and the Rust config, so consumers of this d.ts see the same internal flag shape everywhere.

If any tooling generates these d.ts files, please ensure the generator is also updated so injectLazyBundle doesn’t get dropped on the next regen.

packages/react/testing-library/src/vitest.config.js (1)

224-254: Explicit dynamicImport config for testing-library is coherent.

Routing dynamic-import through the transform with

dynamicImport: {
  injectLazyBundle: false,
  layer: 'test',
  runtimePkg: `${runtimePkgName}/internal`,
}

keeps __dynamicImport wired to the correct runtime while intentionally disabling the auto lynx.loadLazyBundle data-URI import in this Vitest environment, which makes sense for a generic testing helper.

packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (1)

13-50: NAPI config cleanly propagates the new inject_lazy_bundle flag.

The added inject_lazy_bundle: Option<bool> field, its Default of Some(true), and the updated From conversions keep the NAPI-facing config in sync with the core Rust config while preserving default-on behavior for auto lazy-bundle injection.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (1)

22-41: Dynamic-import visitor correctly wires auto lynx.loadLazyBundle injection with an escape hatch.

Implementation details look solid:

  • Config & state:

    • DynamicImportVisitorConfig gains inject_lazy_bundle: Option<bool> with a default of Some(true).
    • The visitor tracks has_inner_lazy_bundle separately from named_imports, which lets you distinguish “inner lazy bundle present” (string-literal, non-URL import) from “needs runtime __dynamicImport helper.”
  • Call-site handling:

    • For import("./foo") (string literal, non-explicitly-external), you:
      • validate the options object shape if present,
      • inject the webpackChunkName comment,
      • set self.has_inner_lazy_bundle = true without rewriting the call, letting the bundler handle chunking.
    • For other imports (URLs, expressions, etc.), you still rewrite to __dynamicImport and populate named_imports as before.
  • Module-level imports:

    • When named_imports is non-empty, you prepend:
      • import { __dynamicImport } from runtime_pkg;
      • import "<runtime_pkg>/experimental/lazy/import" (with /internal stripped), ensuring the lazy runtime is present whenever __dynamicImport is used.
    • Independently, when inject_lazy_bundle is enabled (Some(true) or None) and has_inner_lazy_bundle is true, you prepend the data-URI import that pulls loadLazyBundle from @lynx-js/react/internal and assigns lynx.loadLazyBundle. This directly addresses the “lynx.loadLazyBundle is not a function” bug for relative-path dynamic imports.
  • Defaults & tests:

    • Treating None as enabled in the match on inject_lazy_bundle ensures older configs automatically gain the fix.
    • The updated and added tests (should_transform_import_call, should_import_lazy_import, should_import_lazy_bundle, should_not_import_lazy) cover both the “off” switch and the new injection behaviors.

Overall, the logic matches the PR objectives and remains backward-compatible, with inject_lazy_bundle providing a clear opt-out when needed.

Also applies to: 43-72, 117-131, 188-283, 297-391

@HuJean HuJean force-pushed the p/hujing/lazy-bundle branch from 3afd3e9 to c37c6fb Compare December 2, 2025 11:05
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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1)

24-24: Use a relative path import to test the lazy loading feature consistently.

This test should use a relative path import (e.g., import('./module.js')) instead of the absolute URL import('https://www/a.js') to align with the PR objectives for detecting and injecting lazy runtime for relative path dynamic imports. The load-lazy-bundle test case already properly validates this behavior with relative paths like import('./foo.js').

♻️ Duplicate comments (1)
.changeset/four-rice-guess.md (1)

5-5: Hyphenate compound modifier: use "Auto-define" instead of "Auto define".

The compound verb phrase should be hyphenated for correct grammar.

Apply this diff:

-Auto define lynx.loadLazyBundle when using `import(/* relative path */)`.
+Auto-define lynx.loadLazyBundle when using `import(/* relative path */)`.

Based on coding guidelines and static analysis hints.

🧹 Nitpick comments (3)
examples/react-lazy-bundle/src/index.tsx (1)

7-9: Good demonstration of the dynamic import feature, but consider adding error handling.

This dynamic import correctly demonstrates the PR's core feature—automatic injection of lynx.loadLazyBundle for relative path imports. The top-level execution is appropriate for an example.

However, since this is an example that developers may reference, consider adding error handling to demonstrate best practices:

-void import('./utils/minus.js').then((res) => {
-  console.info('dynamic import minus', res.minus(1, 2));
-});
+void import('./utils/minus.js')
+  .then((res) => {
+    console.info('dynamic import minus', res.minus(1, 2));
+  })
+  .catch((err) => {
+    console.error('Failed to load minus module:', err);
+  });
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (2)

268-271: Consider more robust path manipulation.

The .replace("/internal", "") assumes runtime_pkg ends with "/internal". While this works with the current default, a more robust approach would verify the assumption or use a configurable base path.

Consider this safer alternative:

let base_pkg = self.opts.runtime_pkg
  .strip_suffix("/internal")
  .unwrap_or(&self.opts.runtime_pkg);
create_import_decl(&format!("{}/experimental/lazy/import", base_pkg))

273-277: Simplify boolean pattern matching.

The match expression for inject_lazy_bundle can be simplified using unwrap_or.

Apply this diff:

-    if match self.opts.inject_lazy_bundle {
-      Some(true) => true,
-      Some(false) => false,
-      None => true,
-    } && self.has_inner_lazy_bundle
+    if self.opts.inject_lazy_bundle.unwrap_or(true) && self.has_inner_lazy_bundle
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3afd3e9 and c37c6fb.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (25)
  • .changeset/four-rice-guess.md (1 hunks)
  • examples/react-lazy-bundle/lynx.config.js (1 hunks)
  • examples/react-lazy-bundle/package.json (1 hunks)
  • examples/react-lazy-bundle/src/App.css (1 hunks)
  • examples/react-lazy-bundle/src/App.tsx (1 hunks)
  • examples/react-lazy-bundle/src/index.tsx (1 hunks)
  • examples/react-lazy-bundle/src/rspeedy-env.d.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/add.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/dynamic.ts (1 hunks)
  • examples/react-lazy-bundle/src/utils/minus.ts (1 hunks)
  • examples/react-lazy-bundle/tsconfig.json (1 hunks)
  • packages/react/runtime/src/index.ts (1 hunks)
  • packages/react/runtime/vitest.config.ts (1 hunks)
  • packages/react/testing-library/src/vitest.config.js (1 hunks)
  • packages/react/transform/__test__/fixture.spec.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (8 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (3 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_bundle.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1 hunks)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_not_import_lazy.js (0 hunks)
  • packages/react/transform/index.d.ts (1 hunks)
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js (1 hunks)
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_not_import_lazy.js
🚧 Files skipped from review as they are similar to previous changes (16)
  • examples/react-lazy-bundle/src/App.tsx
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/foo2.js
  • packages/react/runtime/vitest.config.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/load-lazy-bundle/index.jsx
  • examples/react-lazy-bundle/src/utils/dynamic.ts
  • packages/react/transform/index.d.ts
  • examples/react-lazy-bundle/package.json
  • examples/react-lazy-bundle/src/utils/add.ts
  • examples/react-lazy-bundle/lynx.config.js
  • examples/react-lazy-bundle/src/utils/minus.ts
  • examples/react-lazy-bundle/src/App.css
  • packages/react/runtime/src/index.ts
  • packages/react/testing-library/src/vitest.config.js
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/swc_snapshots/lib.rs/should_import_lazy_bundle.js
  • packages/react/transform/test/fixture.spec.js
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/four-rice-guess.md
🧠 Learnings (29)
📓 Common learnings
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • .changeset/four-rice-guess.md
  • examples/react-lazy-bundle/tsconfig.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • .changeset/four-rice-guess.md
  • examples/react-lazy-bundle/tsconfig.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • .changeset/four-rice-guess.md
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • examples/react-lazy-bundle/src/index.tsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-11-03T08:47:17.714Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1911
File: packages/web-platform/web-tests/tests/react/basic-element-list-estimated-main-axis-size-px/index.jsx:14-24
Timestamp: 2025-11-03T08:47:17.714Z
Learning: In the autoScroll method for XList components in the lynx-family/lynx-stack repository, the `rate` parameter supports plain strings like `'100'` in addition to numbers and strings with unit suffixes (`${number}px`, `${number}rpx`, `${number}ppx`), even though the TypeScript type definition may appear more restrictive.

Applied to files:

  • examples/react-lazy-bundle/src/rspeedy-env.d.ts
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • .changeset/four-rice-guess.md
  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-09-29T06:43:40.182Z
Learnt from: CR
Repo: lynx-family/lynx-stack PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-09-29T06:43:40.182Z
Learning: Applies to .changeset/*.md : For contributions, generate and commit a Changeset describing your changes

Applied to files:

  • .changeset/four-rice-guess.md
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
  • examples/react-lazy-bundle/src/index.tsx
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • .changeset/four-rice-guess.md
  • examples/react-lazy-bundle/tsconfig.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • .changeset/four-rice-guess.md
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-11-05T03:26:52.546Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1916
File: packages/react/transform/crates/swc_plugin_snapshot/lib.rs:9-9
Timestamp: 2025-11-05T03:26:52.546Z
Learning: In the lynx-stack repository's swc_core v47 upgrade (PR #1916), the import `use swc_core::atoms as swc_atoms;` is required in files that use the `quote!` macro (e.g., packages/react/transform/crates/swc_plugin_snapshot/lib.rs, swc_plugin_list/lib.rs, swc_plugin_worklet/gen_stmt.rs) even though swc_atoms may not appear explicitly in the source code. This is because the quote! macro generates code that internally references swc_atoms. Removing this import causes compiler error: "failed to resolve: use of unresolved module or unlinked crate `swc_atoms`".

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • examples/react-lazy-bundle/tsconfig.json
  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-08-18T08:46:20.001Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1547
File: packages/rspeedy/core/src/config/loadConfig.ts:11-11
Timestamp: 2025-08-18T08:46:20.001Z
Learning: `#register` and similar imports starting with "#" are Node.js subpath imports defined in the "imports" field of package.json, not TypeScript path mapping aliases. These are natively supported by both Node.js and TypeScript without requiring additional tsconfig.json configuration like "moduleResolution" or "resolvePackageJsonImports" settings.

Applied to files:

  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • examples/react-lazy-bundle/tsconfig.json
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In packages/react/transform/src/swc_plugin_compat/mod.rs, the `add_pure_comment` function at lines 478-482 is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs. These are two distinct code paths that should be treated differently.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
📚 Learning: 2025-09-18T04:43:54.426Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1771
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_component_with_static_sibling.js:2-2
Timestamp: 2025-09-18T04:43:54.426Z
Learning: In the lynx-family/lynx-stack repository, the `add_pure_comment` function in packages/react/transform/src/swc_plugin_compat/mod.rs (around lines 478-482) is specifically for `wrapWithLynxComponent` calls, not `createSnapshot` calls. The PURE comment injection for `createSnapshot` is handled separately in swc_plugin_snapshot/mod.rs.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-09-10T11:42:36.855Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1714
File: packages/react/transform/Cargo.toml:19-19
Timestamp: 2025-09-10T11:42:36.855Z
Learning: In packages/react/transform/Cargo.toml, the crate uses serde derive macros (#[derive(Serialize, Deserialize)]) in multiple files including src/esbuild.rs and src/swc_plugin_extract_str/mod.rs, so the "derive" feature is required when migrating to workspace dependencies.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs
📚 Learning: 2025-08-11T06:00:04.376Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1305
File: packages/react/testing-library/src/plugins/vitest.ts:59-61
Timestamp: 2025-08-11T06:00:04.376Z
Learning: In the lynx-family/lynx-stack repository, the `testingLibraryPlugin` in `packages/react/testing-library/src/plugins/vitest.ts` intentionally uses `process.exit` when jsdom installation fails, maintaining consistency with the previous implementation from `packages/react/testing-library/src/vitest.config.js`. This behavior should not be changed to use `this.error` despite being a Vite plugin best practice.

Applied to files:

  • packages/webpack/react-webpack-plugin/test/cases/code-splitting/lazy-imports/index.jsx
📚 Learning: 2025-07-18T04:27:18.291Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1238
File: packages/react/runtime/src/debug/component-stack.ts:70-90
Timestamp: 2025-07-18T04:27:18.291Z
Learning: The component-stack.ts file in packages/react/runtime/src/debug/component-stack.ts is a direct fork from https://github.com/preactjs/preact/blob/main/debug/src/component-stack.js. The team prefers to keep it aligned with the upstream Preact version and may contribute improvements back to Preact in the future.

Applied to files:

  • examples/react-lazy-bundle/src/index.tsx
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js
🧬 Code graph analysis (2)
packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (3)
packages/react/transform/index.d.ts (1)
  • DynamicImportVisitorConfig (422-429)
packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)
  • DynamicImportVisitorConfig (166-173)
packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (2)
  • default (23-29)
  • default (63-65)
examples/react-lazy-bundle/src/index.tsx (1)
examples/react-lazy-bundle/src/App.tsx (1)
  • App (5-30)
🪛 LanguageTool
.changeset/four-rice-guess.md

[grammar] ~5-~5: Use a hyphen to join words.
Context: --- "@lynx-js/react": patch --- Auto define lynx.loadLazyBundle when using `i...

(QB_NEW_EN_HYPHEN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / clippy
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (13)
examples/react-lazy-bundle/src/rspeedy-env.d.ts (1)

1-1: LGTM! Follows the established Rspeedy pattern.

The triple-slash reference directive correctly includes type declarations from @lynx-js/rspeedy/client, which is the standard pattern for Rspeedy-based projects in this repository.

Based on learnings, Rspeedy templates use lynx-js/rspeedy/client types via rspeedy-env.d.ts instead of vite/client types.

examples/react-lazy-bundle/src/index.tsx (3)

1-3: LGTM!

The imports correctly set up debugging tools and the React runtime for the example application.


11-13: LGTM!

The root rendering logic is correct and follows the standard Lynx React pattern.


15-17: LGTM!

The HMR setup follows the standard webpack hot module replacement pattern, enabling a better development experience.

packages/react/transform/crates/swc_plugin_dynamic_import/napi.rs (3)

18-19: LGTM! Field addition follows existing pattern.

The inject_lazy_bundle field is properly declared with Option type and @internal documentation, consistent with other internal fields in the struct.


27-27: LGTM! Default enables auto-injection.

Setting inject_lazy_bundle to Some(true) by default aligns with the PR objective to automatically define lynx.loadLazyBundle when using dynamic imports with relative paths.


37-37: LGTM! Field properly propagated.

The inject_lazy_bundle field is correctly propagated through both From trait implementations, maintaining consistency between DynamicImportVisitorConfig and CoreConfig.

Also applies to: 47-47

packages/react/transform/crates/swc_plugin_dynamic_import/tests/__swc_snapshots__/lib.rs/should_import_lazy_import.js (1)

1-9: Auto-generated snapshot looks correct.

This snapshot demonstrates the expected transform output: importing the lazy/import module, importing __dynamicImport, and calling it with an external URL and component type.

packages/react/transform/crates/swc_plugin_dynamic_import/lib.rs (5)

29-30: LGTM! Config field added consistently.

The inject_lazy_bundle field is properly added to DynamicImportVisitorConfig with a sensible default of Some(true), enabling auto-injection by default.

Also applies to: 38-38


48-48: LGTM! State tracking added for inner lazy bundles.

The has_inner_lazy_bundle field correctly tracks when relative-path imports requiring lazy bundle loading are detected, initialized to false and set to true at line 219 when appropriate.

Also applies to: 70-70


117-130: LGTM! Helper function reduces duplication.

The create_import_decl helper properly constructs side-effect import declarations, eliminating code duplication for lazy import generation.


306-306: LGTM! Tests cover key scenarios.

The test suite properly covers:

  • Disabling lazy bundle injection with inject_lazy_bundle: Some(false)
  • External URL imports requiring lazy/import
  • Relative path imports requiring lazy bundle injection
  • Template literal imports (no lazy handling)

Also applies to: 343-391


279-282: The data URL approach is established and the concerns are addressed by Lynx's architecture.

The global lynx object is guaranteed to exist via shimming (lynx = lynx || {} in RuntimeWrapperWebpackPlugin), loadLazyBundle is properly exported from @lynx-js/react/internal, and webpack bundlers support this data: URL pattern as evidenced by existing test snapshots. This approach is not unconventional in this codebase—it's an established pattern already used in generated code and tested consistently. Similar to how __-prefixed functions are injected globally by the Lynx Engine, the lynx object is shimmed at bundle initialization to ensure it's always available.

Copy link
Copy Markdown
Collaborator

@upupming upupming left a comment

Choose a reason for hiding this comment

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

LGTM! Just one question~

@HuJean HuJean merged commit a01fa58 into main Dec 8, 2025
81 of 85 checks passed
@HuJean HuJean deleted the p/hujing/lazy-bundle branch December 8, 2025 09:59
@colinaaa colinaaa mentioned this pull request Dec 9, 2025
3 tasks
colinaaa added a commit that referenced this pull request Dec 9, 2025
<!--
  Thank you for submitting a pull request!

We appreciate the time and effort you have invested in making these
changes. Please ensure that you provide enough information to allow
others to review your pull request.

Upon submission, your pull request will be automatically assigned with
reviewers.

If you want to learn more about contributing to this project, please
visit:
https://github.com/lynx-family/lynx-stack/blob/main/CONTRIBUTING.md.
-->

<!-- The AI summary below will be auto-generated - feel free to replace
it with your own. -->

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

* **Chores**
* Added support for a newer version of a related build tool while
maintaining compatibility with previous versions.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Add missing `peerDependnecies` for #1956.

## Checklist

<!--- Check and mark with an "x" -->

- [ ] Tests updated (or not required).
- [ ] Documentation updated (or not required).
- [ ] Changeset added, and when a BREAKING CHANGE occurs, it needs to be
clearly marked (or not required).
colinaaa pushed a commit that referenced this pull request Dec 14, 2025
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @lynx-js/css-extract-webpack-plugin@0.7.0

### Minor Changes

- **BREAKING CHANGE**: Require `@lynx-js/template-webpack-plugin`
0.10.0. ([#1965](#1965))

- Merge all css chunk and generate a `.css.hot-update.json` file for
each bundle.
([#1965](#1965))

## @lynx-js/template-webpack-plugin@0.10.0

### Minor Changes

- Merge all css chunk and generate a `.css.hot-update.json` file for
each bundle.
([#1965](#1965))

## @lynx-js/react@0.115.1

### Patch Changes

- Auto define lynx.loadLazyBundle when using `import(/* relative path
*/)`. ([#1956](#1956))

- feat: support declaring cross-thread shared modules via Import
Attributes, enabling Main Thread Functions to call standard JS functions
directly. ([#1968](#1968))

- Usage: Add `with { runtime: "shared" }` to the `import` statement. For
example:

        ```ts
        import { func } from './utils.js' with { runtime: 'shared' };

        function worklet() {
          'main thread';
          func(); // callable inside a main thread function
        }
        ```

    -   Limitations:
- Only directly imported identifiers are treated as shared; assigning
the import to a new variable will result in the loss of this shared
capability.
- Functions defined within shared modules do not automatically become
Main Thread Functions. Accessing main-thread-only APIs (e.g.,
`MainThreadRef`) will cause errors.

## @lynx-js/rspeedy@0.12.2

### Patch Changes

- Bump Rsbuild v1.6.13 with Rspack v1.6.6.
([#1995](#1995))

-   Updated dependencies \[]:
    -   @lynx-js/web-rsbuild-server-middleware@0.19.1

## @lynx-js/react-rsbuild-plugin@0.12.1

### Patch Changes

- Avoid injecting hot update runtime when dev.hmr or dev.liveReload is
set to false.
([#1980](#1980))

- Updated dependencies
\[[`553ece1`](553ece1),
[`8cdb69d`](8cdb69d),
[`8cdb69d`](8cdb69d)]:
    -   @lynx-js/react-webpack-plugin@0.7.3
    -   @lynx-js/css-extract-webpack-plugin@0.7.0
    -   @lynx-js/template-webpack-plugin@0.10.0
    -   @lynx-js/react-alias-rsbuild-plugin@0.12.1
    -   @lynx-js/use-sync-external-store@1.5.0
    -   @lynx-js/react-refresh-webpack-plugin@0.3.4

## @lynx-js/web-constants@0.19.1

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-worker-rpc@0.19.1

## @lynx-js/web-core@0.19.1

### Patch Changes

- fix: support CSP for mts
([#1994](#1994))

- Updated dependencies
\[[`f7256d5`](f7256d5)]:
    -   @lynx-js/web-mainthread-apis@0.19.1
    -   @lynx-js/web-worker-runtime@0.19.1
    -   @lynx-js/web-constants@0.19.1
    -   @lynx-js/web-worker-rpc@0.19.1

## @lynx-js/web-mainthread-apis@0.19.1

### Patch Changes

- fix: fix reload lynx-view when `enableCSSSelector` false may cause css
style lost
([#1982](#1982))

-   Updated dependencies \[]:
    -   @lynx-js/web-constants@0.19.1

## @lynx-js/web-worker-runtime@0.19.1

### Patch Changes

- Updated dependencies
\[[`f7256d5`](f7256d5)]:
    -   @lynx-js/web-mainthread-apis@0.19.1
    -   @lynx-js/web-constants@0.19.1
    -   @lynx-js/web-worker-rpc@0.19.1

## @lynx-js/react-webpack-plugin@0.7.3

### Patch Changes

- Support `@lynx-js/template-webpack-plugin` v0.10.0.
([#1992](#1992))

## create-rspeedy@0.12.2



## @lynx-js/react-alias-rsbuild-plugin@0.12.1



## upgrade-rspeedy@0.12.2



## @lynx-js/web-core-server@0.19.1



## @lynx-js/web-rsbuild-server-middleware@0.19.1



## @lynx-js/web-worker-rpc@0.19.1

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
f0rdream pushed a commit to f0rdream/lynx-stack that referenced this pull request Dec 18, 2025
)

Auto define lynx.loadLazyBundle when using `import(/* relative path
*/)`.

close lynx-family#1954

<!--
  Thank you for submitting a pull request!

We appreciate the time and effort you have invested in making these
changes. Please ensure that you provide enough information to allow
others to review your pull request.

Upon submission, your pull request will be automatically assigned with
reviewers.

If you want to learn more about contributing to this project, please
visit:
https://github.com/lynx-family/lynx-stack/blob/main/CONTRIBUTING.md.
-->

<!-- The AI summary below will be auto-generated - feel free to replace
it with your own. -->

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

* **New Features**
* Automatic `lynx.loadLazyBundle` integration with dynamic imports for
streamlined code-splitting
* New React lazy-bundle example project demonstrating advanced
code-splitting patterns
* Enhanced component lazy-loading with experimental import capabilities

* **Tests**
* Expanded test coverage for dynamic import transformations and
lazy-loading scenarios

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

## Checklist

<!--- Check and mark with an "x" -->

- [ ] Tests updated (or not required).
- [ ] Documentation updated (or not required).
- [ ] Changeset added, and when a BREAKING CHANGE occurs, it needs to be
clearly marked (or not required).
f0rdream pushed a commit to f0rdream/lynx-stack that referenced this pull request Dec 18, 2025
<!--
  Thank you for submitting a pull request!

We appreciate the time and effort you have invested in making these
changes. Please ensure that you provide enough information to allow
others to review your pull request.

Upon submission, your pull request will be automatically assigned with
reviewers.

If you want to learn more about contributing to this project, please
visit:
https://github.com/lynx-family/lynx-stack/blob/main/CONTRIBUTING.md.
-->

<!-- The AI summary below will be auto-generated - feel free to replace
it with your own. -->

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

* **Chores**
* Added support for a newer version of a related build tool while
maintaining compatibility with previous versions.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Add missing `peerDependnecies` for lynx-family#1956.

## Checklist

<!--- Check and mark with an "x" -->

- [ ] Tests updated (or not required).
- [ ] Documentation updated (or not required).
- [ ] Changeset added, and when a BREAKING CHANGE occurs, it needs to be
clearly marked (or not required).
f0rdream pushed a commit to f0rdream/lynx-stack that referenced this pull request Dec 18, 2025
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @lynx-js/css-extract-webpack-plugin@0.7.0

### Minor Changes

- **BREAKING CHANGE**: Require `@lynx-js/template-webpack-plugin`
0.10.0. ([lynx-family#1965](lynx-family#1965))

- Merge all css chunk and generate a `.css.hot-update.json` file for
each bundle.
([lynx-family#1965](lynx-family#1965))

## @lynx-js/template-webpack-plugin@0.10.0

### Minor Changes

- Merge all css chunk and generate a `.css.hot-update.json` file for
each bundle.
([lynx-family#1965](lynx-family#1965))

## @lynx-js/react@0.115.1

### Patch Changes

- Auto define lynx.loadLazyBundle when using `import(/* relative path
*/)`. ([lynx-family#1956](lynx-family#1956))

- feat: support declaring cross-thread shared modules via Import
Attributes, enabling Main Thread Functions to call standard JS functions
directly. ([lynx-family#1968](lynx-family#1968))

- Usage: Add `with { runtime: "shared" }` to the `import` statement. For
example:

        ```ts
        import { func } from './utils.js' with { runtime: 'shared' };

        function worklet() {
          'main thread';
          func(); // callable inside a main thread function
        }
        ```

    -   Limitations:
- Only directly imported identifiers are treated as shared; assigning
the import to a new variable will result in the loss of this shared
capability.
- Functions defined within shared modules do not automatically become
Main Thread Functions. Accessing main-thread-only APIs (e.g.,
`MainThreadRef`) will cause errors.

## @lynx-js/rspeedy@0.12.2

### Patch Changes

- Bump Rsbuild v1.6.13 with Rspack v1.6.6.
([lynx-family#1995](lynx-family#1995))

-   Updated dependencies \[]:
    -   @lynx-js/web-rsbuild-server-middleware@0.19.1

## @lynx-js/react-rsbuild-plugin@0.12.1

### Patch Changes

- Avoid injecting hot update runtime when dev.hmr or dev.liveReload is
set to false.
([lynx-family#1980](lynx-family#1980))

- Updated dependencies
\[[`553ece1`](lynx-family@553ece1),
[`8cdb69d`](lynx-family@8cdb69d),
[`8cdb69d`](lynx-family@8cdb69d)]:
    -   @lynx-js/react-webpack-plugin@0.7.3
    -   @lynx-js/css-extract-webpack-plugin@0.7.0
    -   @lynx-js/template-webpack-plugin@0.10.0
    -   @lynx-js/react-alias-rsbuild-plugin@0.12.1
    -   @lynx-js/use-sync-external-store@1.5.0
    -   @lynx-js/react-refresh-webpack-plugin@0.3.4

## @lynx-js/web-constants@0.19.1

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-worker-rpc@0.19.1

## @lynx-js/web-core@0.19.1

### Patch Changes

- fix: support CSP for mts
([lynx-family#1994](lynx-family#1994))

- Updated dependencies
\[[`f7256d5`](lynx-family@f7256d5)]:
    -   @lynx-js/web-mainthread-apis@0.19.1
    -   @lynx-js/web-worker-runtime@0.19.1
    -   @lynx-js/web-constants@0.19.1
    -   @lynx-js/web-worker-rpc@0.19.1

## @lynx-js/web-mainthread-apis@0.19.1

### Patch Changes

- fix: fix reload lynx-view when `enableCSSSelector` false may cause css
style lost
([lynx-family#1982](lynx-family#1982))

-   Updated dependencies \[]:
    -   @lynx-js/web-constants@0.19.1

## @lynx-js/web-worker-runtime@0.19.1

### Patch Changes

- Updated dependencies
\[[`f7256d5`](lynx-family@f7256d5)]:
    -   @lynx-js/web-mainthread-apis@0.19.1
    -   @lynx-js/web-constants@0.19.1
    -   @lynx-js/web-worker-rpc@0.19.1

## @lynx-js/react-webpack-plugin@0.7.3

### Patch Changes

- Support `@lynx-js/template-webpack-plugin` v0.10.0.
([lynx-family#1992](lynx-family#1992))

## create-rspeedy@0.12.2



## @lynx-js/react-alias-rsbuild-plugin@0.12.1



## upgrade-rspeedy@0.12.2



## @lynx-js/web-core-server@0.19.1



## @lynx-js/web-rsbuild-server-middleware@0.19.1



## @lynx-js/web-worker-rpc@0.19.1

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

[Bug]: lynx.loadLazyBundle is not a function

6 participants