Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork5.5k
feat(kit): add support for defining moduleDependencies as an async function#33504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Conversation
|
coderabbitaibot commentedOct 17, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
WalkthroughThis pull request adds support for asynchronous module dependencies throughout the Nuxt kit ecosystem. The changes enable module developers to define moduleDependencies as an awaitable function that resolves asynchronously. The implementation updates type signatures in packages/schema to accept Awaitable<ModuleDependencies>, modifies the dependency resolution logic in packages/kit to await the result, introduces a test case verifying async dependency handling, and adds documentation demonstrating the async moduleDependencies pattern with runtime inspection and conditional IO operations. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes The changes introduce asynchronous capability to module dependencies across multiple integrated areas—type definitions, runtime implementation, test coverage, and documentation. Whilst the individual changes follow a consistent pattern of adding Awaitable support, the review requires verifying: type signature compatibility across interfaces, proper await handling in the installation flow, alignment between test scenarios and documented examples, and ensuring no breaking changes to existing synchronous dependency patterns. The spread across heterogeneous file types (schema, implementation, tests, docs) necessitates cross-disciplinary reasoning despite the homogeneous intent. Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for usingCodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
@nuxt/kitnuxt@nuxt/rspack-builder@nuxt/schema@nuxt/vite-builder@nuxt/webpack-buildercommit: |
There was a problem hiding this 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)
docs/2.guide/3.going-further/3.modules.md (1)
86-96:Replace npmjs.com link to resolve CI 403 errorThe link
https://www.npmjs.comat line 89 returns a 403 status and blocks the documentation pipeline. Change tohttps://docs.npmjs.com/, which returns a 200 status and is accessible.
🧹 Nitpick comments (5)
packages/kit/src/module/install.ts (1)
59-59:Attach module context to async dependency failures and prefer nullish coalescingThe await is correct. For clearer semantics and better diagnostics, catch errors here and use
?? {}instead of|| {}.Apply:
- const dependencyMeta = await res.nuxtModule.getModuleDependencies?.(nuxt) || {}+ let dependencyMeta = {}+ try {+ dependencyMeta = await res.nuxtModule.getModuleDependencies?.(nuxt) ?? {}+ } catch (e) {+ const which = typeof key === 'string' ? `\`${key}\`` : 'an inline module'+ throw new TypeError(`Error resolving moduleDependencies for ${which}: ${e instanceof Error ? e.message : String(e)}`)+ }docs/2.guide/3.going-further/3.modules.md (1)
549-573:Good example; add a short caveat about heavy I/OThe sample is clear. Consider a one‑line note that heavy I/O in
moduleDependenciesdelays start‑up and should be deferred to hooks when possible, to align with the “Async Modules” guidance below.packages/kit/test/module.test.ts (1)
138-157:Add coverage for async optional and async overrides/defaultsTo harden the contract, include:
- Async dependency returning
{ optional: true }→ not installed.- Async dependency that returns
overrides/defaults→ merged as in sync path.Example additions:
+ it('should honour optional when provided asynchronously', async () => {+ nuxt = await loadNuxt({+ cwd: tempDir,+ overrides: {+ modules: [+ defineNuxtModule({+ meta: { name: 'foo' },+ async moduleDependencies () {+ await Promise.resolve()+ return { 'some-module': { optional: true } }+ },+ }),+ ],+ },+ })+ expect(globalThis.someModuleLoaded).toBeUndefined()+ })++ it('should merge overrides/defaults from async dependencies', async () => {+ nuxt = await loadNuxt({+ cwd: tempDir,+ overrides: {+ // @ts-expect-error test-only option+ a: { user: 'provided by user' },+ modules: [+ defineNuxtModule({+ meta: { name: 'a' },+ defaults: { value: 'provided by a' },+ setup (options) {+ expect(options.value).toBe('provided by c')+ expect(options.user).toBe('provided by user')+ },+ }),+ defineNuxtModule({+ meta: { name: 'c' },+ async moduleDependencies () {+ await Promise.resolve()+ return {+ a: {+ overrides: { value: 'provided by c' },+ defaults: { user: 'provided by c' },+ },+ }+ },+ }),+ ],+ },+ })+ })packages/schema/src/types/module.ts (2)
87-87:Tighten union: avoid duplicationYou can simplify to a single async-capable function type.
Apply:
- moduleDependencies?: ModuleDependencies | ((nuxt: Nuxt) => ModuleDependencies) | ((nuxt: Nuxt) => Awaitable<ModuleDependencies>)+ moduleDependencies?: ModuleDependencies | ((nuxt: Nuxt) => Awaitable<ModuleDependencies>)
119-119:Return type simplificationPrefer
Awaitable<ModuleDependencies | undefined>for readability.Apply:
- getModuleDependencies?: (nuxt: Nuxt) => Awaitable<ModuleDependencies> | ModuleDependencies | undefined+ getModuleDependencies?: (nuxt: Nuxt) => Awaitable<ModuleDependencies | undefined>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
docs/2.guide/3.going-further/3.modules.md(1 hunks)packages/kit/src/module/install.ts(1 hunks)packages/kit/test/module.test.ts(1 hunks)packages/schema/src/types/module.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Follow standard TypeScript conventions and best practices
Files:
packages/schema/src/types/module.tspackages/kit/src/module/install.tspackages/kit/test/module.test.ts
**/*.{test,spec}.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Write unit tests for core functionality using
vitest
Files:
packages/kit/test/module.test.ts
🧬 Code graph analysis (1)
packages/kit/test/module.test.ts (2)
packages/nuxt/src/core/nuxt.ts (1)
loadNuxt(752-870)packages/kit/src/module/define.ts (1)
defineNuxtModule(23-35)
🪛 GitHub Actions: docs
docs/2.guide/3.going-further/3.modules.md
[error] 1-1: [403]https://www.npmjs.com/ Rejected status code (Forbidden)
⏰ 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). (2)
- GitHub Check: code
- GitHub Check: build
🔇 Additional comments (1)
packages/kit/test/module.test.ts (1)
138-157:LGTM: async moduleDependencies path is exercisedTest verifies awaiting and installation; simple and effective.
CodSpeed Performance ReportMerging#33504 willnot alter performanceComparing Summary
Footnotes |
danielroe commentedOct 23, 2025
the main reason I didn't make it support async functions initially was that this would be a way of slowing down the start of nuxt (and it wouldn't be easily trackable/attributable to the module which slowed down nuxt in this way). what use case are you imagining? |
linspw commentedOct 24, 2025
Thanks for the question,@danielroe ! Use case (why async): I want modules to be able to determine their own dependencies based on a user configuration file (for example, my-module.config.ts) and the project context. In practice, this usually means:
Today it’s possible to perform this logic inside setup, but it’s not possible to define moduleDependencies based on it without duplicating the configuration loading or creating awkward workarounds. But I understand your point about blocking the loading process, thinking about it, maybe a way to solve this could be optimizing with parallelism and/or a timeout. |
vis97c commentedDec 16, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I wanted to update a module where the dependencies options depended on my module options plus some extra logic, the current moduleDependencies implementation breaks that posibility. |
🔗 Linked issue
📚 Description
Example: