Skip to content

Conversation

@antfu
Copy link
Member

@antfu antfu commented Oct 31, 2025

I think it's a common use case to install plugins lazily, imagine:

addVitePlugin(() => import('my-cool-plugin').then(r => r.default()))

The current workaround is:

const plugin = await import('my-cool-plugin').then(r => r.default)
addVitePlugin(() => plugin())

But this would defeat the point of the factory function to lazy load, as

const pluginVite = await import('my-cool-plugin/vite').then(r => r.default)
const pluginWebpack = await import('my-cool-plugin/webpack').then(r => r.default)
addVitePlugin(() => pluginVite())
addWebpackPlugin(() => pluginWebpack())

would result in loading unnecessary code.

This PR makes those utility support async usages.

Not sure if there are any performance concerns on this tho.

@antfu antfu requested a review from danielroe as a code owner October 31, 2025 06:50
@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@coderabbitai
Copy link

coderabbitai bot commented Oct 31, 2025

Walkthrough

This PR converts several build-plugin APIs in packages/kit/src/build.ts to support asynchronous resolution. It adds local utility types Arrayable and Thenable, and changes signatures and internal flows to accept/return Thenable values. Updated members include extendViteConfig, extendWebpackCompatibleConfig, addVitePlugin, addWebpackPlugin, addRspackPlugin, AddBuildPluginFactory, and the internal wiring that awaits plugin getters and config mutation hooks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Review focus:
    • Correct placement of await/async in hook registrations (vite:extend, vite:extendConfig, webpack/rspack extend hooks)
    • Verification of updated function signatures and propagated Thenable<Arrayable<...>> types
    • addBuildPlugin usage sites and propagation of new factory return types
    • Handling of arrayable plugin inputs and functions returning promises
    • Potential impacts on callers that relied on synchronous behaviour (ensure compatibility or documented change)

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "feat(kit): support async constructor for adding plugins" directly and clearly describes the main objective of the changeset. The modifications introduce support for Thenable-based (async-compatible) callback functions across all plugin-adding utilities (addVitePlugin, addWebpackPlugin, addRspackPlugin) and configuration extension functions. The title is concise, specific, and uses clear language that accurately conveys the primary change without vague terms or noise.
Description Check ✅ Passed The pull request description is clearly related to the changeset and provides meaningful context for the changes. It explains the practical use case (lazy-loading plugins via dynamic imports), demonstrates the desired code pattern that motivates these modifications, and contrasts it with the current workaround that defeats lazy-loading benefits. The description directly addresses why async support in plugin factories is valuable, making it entirely relevant to the implementation of Thenable-based signatures across the plugin-adding functions.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/async-add-plugin

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c39fa64 and 8bcdbdc.

📒 Files selected for processing (1)
  • packages/kit/src/build.ts (10 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Follow standard TypeScript conventions and best practices

Files:

  • packages/kit/src/build.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: GalacticHypernova
Repo: nuxt/nuxt PR: 26468
File: packages/nuxt/src/components/plugins/loader.ts:24-24
Timestamp: 2024-11-05T15:22:54.759Z
Learning: In `packages/nuxt/src/components/plugins/loader.ts`, the references to `resolve` and `distDir` are legacy code from before Nuxt used the new unplugin VFS and will be removed.
📚 Learning: 2024-11-28T21:22:40.496Z
Learnt from: GalacticHypernova
Repo: nuxt/nuxt PR: 29661
File: packages/kit/src/template.ts:227-229
Timestamp: 2024-11-28T21:22:40.496Z
Learning: In `packages/kit/src/template.ts`, when updating the `EXTENSION_RE` regular expression for TypeScript configuration, avoid using patterns like `(\.\w+)+$` as they can result in catastrophic backtracking.

Applied to files:

  • packages/kit/src/build.ts
📚 Learning: 2024-11-11T12:34:22.648Z
Learnt from: Tofandel
Repo: nuxt/nuxt PR: 0
File: :0-0
Timestamp: 2024-11-11T12:34:22.648Z
Learning: Ensure that AI-generated summaries accurately reflect the key changes in the PR, focusing on notable changes such as the removal of unused imports and variables starting with underscores.

Applied to files:

  • packages/kit/src/build.ts
📚 Learning: 2024-11-05T15:22:54.759Z
Learnt from: GalacticHypernova
Repo: nuxt/nuxt PR: 26468
File: packages/nuxt/src/components/plugins/loader.ts:24-24
Timestamp: 2024-11-05T15:22:54.759Z
Learning: In `packages/nuxt/src/components/plugins/loader.ts`, the references to `resolve` and `distDir` are legacy code from before Nuxt used the new unplugin VFS and will be removed.

Applied to files:

  • packages/kit/src/build.ts
🧬 Code graph analysis (1)
packages/kit/src/build.ts (1)
packages/kit/src/utils.ts (1)
  • toArray (2-4)
⏰ 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). (12)
  • GitHub Check: test-fixtures (ubuntu-latest, built, webpack, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, rspack, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, rspack, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite, default, manifest-off, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite, async, manifest-off, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite-env-api, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite-env-api, async, manifest-on, json, lts/-1)
  • GitHub Check: release-pkg-pr-new
  • GitHub Check: test-benchmark
  • GitHub Check: typecheck (ubuntu-latest, bundler)
  • GitHub Check: test-size
  • GitHub Check: code
🔇 Additional comments (5)
packages/kit/src/build.ts (5)

9-10: LGTM: Clean utility types for async support.

The Arrayable and Thenable utility types provide a clear, concise way to handle both synchronous and asynchronous plugin values, improving the API ergonomics for the async plugin support feature.


61-85: LGTM: Proper async handling in webpack/rspack config extension.

The implementation correctly handles both synchronous and asynchronous config callbacks by making the hook handler async and awaiting the user-provided function. This maintains backwards compatibility whilst enabling lazy plugin loading.


130-150: LGTM: Correct async plugin resolution for webpack and rspack.

Both functions properly handle asynchronous plugin factories by making the config callback async and awaiting the factory result. The implementation is consistent and maintains backwards compatibility with synchronous plugin values.


209-213: LGTM: Interface updated to support async plugin factories.

The AddBuildPluginFactory interface correctly reflects the new async-capable signatures, maintaining consistency across all three bundler options (vite, webpack, rspack).


215-227: LGTM: Correctly delegates to async-capable plugin functions.

The addBuildPlugin function requires no changes as it properly delegates to the updated addVitePlugin, addWebpackPlugin, and addRspackPlugin functions, which now handle asynchronous factory resolution.


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.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 31, 2025

Open in StackBlitz

@nuxt/kit

npm i https://pkg.pr.new/@nuxt/kit@33619

nuxt

npm i https://pkg.pr.new/nuxt@33619

@nuxt/rspack-builder

npm i https://pkg.pr.new/@nuxt/rspack-builder@33619

@nuxt/schema

npm i https://pkg.pr.new/@nuxt/schema@33619

@nuxt/vite-builder

npm i https://pkg.pr.new/@nuxt/vite-builder@33619

@nuxt/webpack-builder

npm i https://pkg.pr.new/@nuxt/webpack-builder@33619

commit: 8bcdbdc

@codspeed-hq
Copy link

codspeed-hq bot commented Oct 31, 2025

CodSpeed Performance Report

Merging #33619 will not alter performance

Comparing feat/async-add-plugin (8bcdbdc) with main (456cc36)

Summary

✅ 10 untouched

Copy link
Member

@danielroe danielroe left a comment

Choose a reason for hiding this comment

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

👌

(need to investigate lint failure)

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.

3 participants