perf!: resolve virtual templates with single plugin#3819
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughConsolidates many per-feature Rollup plugins into a template-driven virtual VFS: introduces VirtualModule API and Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Points to focus:
Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (9)
src/dev/vfs.ts (1)
33-37: Consider handling render errors gracefully.The VFS API usage is correct. However, if
render()throws an exception (e.g., during template generation), the error will propagate as a 500 error with potentially confusing details.Consider wrapping the render call to provide a clearer error message:
- const content = id ? await nitro.vfs.get(id)?.render() : undefined; + let content: string | undefined; + if (id) { + try { + content = await nitro.vfs.get(id)?.render(); + } catch (error) { + throw new HTTPError({ message: `Failed to render: ${id}`, status: 500 }); + } + }src/build/virtual/_all.ts (1)
26-40: Consider consistent function signatures.All template functions are invoked with
(nitro, _polyfills)but most only acceptnitroas a parameter. While extra arguments are silently ignored in JavaScript, consider updating the individual template function signatures to explicitly include the_polyfillsparameter (even if unused) for consistency, or pass it only to thepolyfillstemplate that actually requires it.src/build/virtual/routing.ts (1)
63-65: Consider extracting shareduniqueByhelper.This
uniqueByfunction is duplicated inrouting-meta.ts. Consider extracting it to a shared utility module to maintain DRY principles.For example, create
src/build/virtual/_utils.ts:export function uniqueBy<T>(arr: T[], key: keyof T): T[] { return [...new Map(arr.map((item) => [item[key], item])).values()]; }src/build/virtual/server-assets.ts (1)
41-53: Consider parallelizing file I/O for better build performance.The sequential
fsp.readFileandfsp.statcalls inside the nested loop could slow down builds with many assets. Processing files in parallel would improve performance.for (const _id of files) { const fsPath = resolve(asset.dir, _id); const id = asset.baseName + "/" + _id; - assets[id] = { fsPath, meta: {} }; - // @ts-ignore TODO: Use mime@2 types - let type = mime.getType(id) || "text/plain"; - if (type.startsWith("text")) { - type += "; charset=utf-8"; - } - const etag = createEtag(await fsp.readFile(fsPath)); - const mtime = await fsp.stat(fsPath).then((s) => s.mtime.toJSON()); - assets[id].meta = { type, etag, mtime }; + assets[id] = { fsPath, meta: {} }; } + + // Process file metadata in parallel + await Promise.all( + Object.entries(assets).map(async ([id, asset]) => { + // @ts-ignore TODO: Use mime@2 types + let type = mime.getType(id) || "text/plain"; + if (type.startsWith("text")) { + type += "; charset=utf-8"; + } + const etag = createEtag(await fsp.readFile(asset.fsPath)); + const mtime = await fsp.stat(asset.fsPath).then((s) => s.mtime.toJSON()); + asset.meta = { type, etag, mtime }; + }) + );src/build/virtual/error-handler.ts (1)
32-35: Variable shadowing: innererrorshadows outererrorparameter.In the generated template, the
catch(error)on line 32 shadows theerrorparameter from line 25. While intentional, renaming the caught error improves clarity.- } catch(error) { + } catch(handlerError) { // Handler itself thrown, log and continue - console.error(error); + console.error(handlerError); }src/build/virtual/tasks.ts (1)
29-45: Consider usingJSON.stringifyfor task names to handle special characters.Task names are quoted with template literals (
"${name}"), but if a task name contains special characters like backslashes or quotes, this could produce invalid JavaScript.- ([name, task]) => - `"${name}": { + ([name, task]) => + `${JSON.stringify(name)}: {src/build/virtual/renderer-template.ts (1)
39-48: Variable shadowing:templateredeclared within inner scope.The variable
templateon Line 40 shadows the outertemplatefrom Line 13. While this works correctly, it can cause confusion during maintenance.Consider renaming the inner variable for clarity:
} else { - const template = compileTemplateToString(html, { + const compiledTemplate = compileTemplateToString(html, { contextKeys: [...RENDER_CONTEXT_KEYS], }); return /* js */ ` import { renderToResponse } from 'rendu' import { serverFetch } from 'nitro/app' - const template = ${template}; + const template = ${compiledTemplate}; export const rendererTemplate = (request) => renderToResponse(template, { request, context: { serverFetch } }) `; }src/build/virtual/public-assets.ts (2)
156-165: Consider fixing indentation for consistency.The function body has extra indentation (4 spaces) compared to other modules. While not affecting functionality, normalizing to 0 leading spaces would improve consistency.
Apply this diff to normalize indentation:
{ id: "#nitro-internal-virtual/public-assets-null", template: () => { return /* js */ ` - export function readAsset (id) { - return Promise.resolve(null); - }`; +export function readAsset (id) { + return Promise.resolve(null); +}`; }, },
167-181: Consider improving indentation and clarifying guard clause logic.Two minor consistency improvements:
- The function body has extra indentation (2 spaces) compared to other modules
- Line 176's logic
if (!assets[id].data) { return assets[id].data }is confusing—returning a falsy value rather than an explicitundefinedobscures intentApply this diff to normalize indentation and clarify the guard clause:
{ id: "#nitro-internal-virtual/public-assets-inline", template: () => { return /* js */ ` - import assets from '#nitro-internal-virtual/public-assets-data' - export function readAsset (id) { - if (!assets[id]) { return undefined } - if (assets[id]._data) { return assets[id]._data } - if (!assets[id].data) { return assets[id].data } - assets[id]._data = Uint8Array.from(atob(assets[id].data), (c) => c.charCodeAt(0)) - return assets[id]._data +import assets from '#nitro-internal-virtual/public-assets-data' +export function readAsset (id) { + if (!assets[id]) { return undefined } + if (assets[id]._data) { return assets[id]._data } + if (!assets[id].data) { return undefined } + assets[id]._data = Uint8Array.from(atob(assets[id].data), (c) => c.charCodeAt(0)) + return assets[id]._data }`; }, },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (29)
src/build/plugins.ts(4 hunks)src/build/plugins/database.ts(0 hunks)src/build/plugins/feature-flags.ts(0 hunks)src/build/plugins/runtime-config.ts(0 hunks)src/build/plugins/server-assets.ts(0 hunks)src/build/plugins/storage.ts(0 hunks)src/build/plugins/virtual.ts(1 hunks)src/build/virtual/_all.ts(1 hunks)src/build/virtual/database.ts(1 hunks)src/build/virtual/error-handler.ts(2 hunks)src/build/virtual/feature-flags.ts(1 hunks)src/build/virtual/plugins.ts(1 hunks)src/build/virtual/polyfills.ts(1 hunks)src/build/virtual/public-assets.ts(4 hunks)src/build/virtual/renderer-template.ts(1 hunks)src/build/virtual/routing-meta.ts(1 hunks)src/build/virtual/routing.ts(2 hunks)src/build/virtual/runtime-config.ts(1 hunks)src/build/virtual/server-assets.ts(1 hunks)src/build/virtual/storage.ts(1 hunks)src/build/virtual/tasks.ts(1 hunks)src/dev/vfs.ts(2 hunks)src/nitro.ts(0 hunks)src/task.ts(1 hunks)src/types/nitro.ts(1 hunks)src/types/virtual/app-config.d.ts(0 hunks)src/utils/regex.ts(1 hunks)test/unit/runtime-config.env.test.ts(1 hunks)tsconfig.json(1 hunks)
💤 Files with no reviewable changes (7)
- src/nitro.ts
- src/build/plugins/runtime-config.ts
- src/build/plugins/feature-flags.ts
- src/build/plugins/database.ts
- src/build/plugins/server-assets.ts
- src/build/plugins/storage.ts
- src/types/virtual/app-config.d.ts
🧰 Additional context used
🧬 Code graph analysis (14)
src/build/plugins/virtual.ts (1)
src/utils/regex.ts (1)
escapeRegExp(1-3)
src/build/virtual/plugins.ts (2)
src/build/virtual/types/plugins.d.ts (1)
plugins(3-3)src/types/nitro.ts (1)
Nitro(16-37)
src/build/virtual/storage.ts (1)
src/types/nitro.ts (1)
Nitro(16-37)
src/build/virtual/feature-flags.ts (1)
src/types/nitro.ts (1)
Nitro(16-37)
src/build/plugins.ts (4)
src/build/plugins/virtual.ts (1)
virtual(11-64)src/build/virtual/_all.ts (1)
virtualTemplates(22-47)src/build/virtual/plugins.ts (1)
plugins(4-24)src/build/virtual/types/plugins.d.ts (1)
plugins(3-3)
src/build/virtual/tasks.ts (2)
src/build/virtual/types/tasks.d.ts (2)
tasks(3-6)scheduledTasks(8-8)src/types/nitro.ts (1)
Nitro(16-37)
src/build/virtual/database.ts (1)
src/types/nitro.ts (1)
Nitro(16-37)
src/build/virtual/server-assets.ts (2)
src/types/nitro.ts (1)
Nitro(16-37)src/rollup/plugins/server-assets.ts (1)
serverAssets(20-60)
src/build/virtual/routing-meta.ts (1)
src/types/nitro.ts (1)
Nitro(16-37)
src/build/virtual/renderer-template.ts (1)
src/types/nitro.ts (1)
Nitro(16-37)
src/build/virtual/runtime-config.ts (2)
src/build/virtual/types/runtime-config.d.ts (1)
runtimeConfig(3-3)src/types/nitro.ts (1)
Nitro(16-37)
src/build/virtual/error-handler.ts (2)
src/types/nitro.ts (1)
Nitro(16-37)src/runtime/meta.ts (1)
runtimeDir(10-10)
src/build/virtual/routing.ts (1)
src/types/nitro.ts (1)
Nitro(16-37)
src/build/virtual/public-assets.ts (1)
src/types/nitro.ts (1)
Nitro(16-37)
🪛 ast-grep (0.40.0)
src/build/plugins/virtual.ts
[warning] 33-35: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(
^(${[...modules.keys()].map((id) => escapeRegExp(id)).join("|")})$
)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
[warning] 48-48: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${escapeRegExp(PREFIX)})
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
🔇 Additional comments (27)
src/utils/regex.ts (1)
1-3: Canonical regex-escaping helper; implementation looks solid.The metacharacter class and
String.raw$&`` replacement follow the standard pattern for safely escaping strings for use in regular expressions. Export and typing are straightforward; no changes needed.test/unit/runtime-config.env.test.ts (1)
3-5: LGTM!The mock correctly provides an explicit empty
runtimeConfigobject, aligning with the updated virtual module system. This ensures the test environment matches the new runtime-config handling where the value is provided directly rather than relying on an imported variable.src/types/nitro.ts (1)
19-19: Breaking change is well-designed.The type change from
Record<string, string>toMap<string, { render: () => string | Promise<string> }>enables lazy rendering and better aligns with the new VFS plugin architecture. TheMapprovides efficienthas/get/keysoperations, and the asyncrendersupport allows for deferred content generation.src/dev/vfs.ts (1)
42-56: LGTM!The JSON response and directory generation correctly use the new Map-based VFS API. The spread operator for
keys()iteration and thecurrentfield with rendered content are well-implemented.src/task.ts (1)
3-5: LGTM!The import cleanup correctly removes unused
Nitrotype andnormalizefunction after theaddNitroTasksVirtualFilefunction was migrated to the new virtual module system undersrc/build/virtual/tasks.ts.tsconfig.json (1)
14-14: Path mapping verification successful — new directory and configuration are correct.The new path mapping target
src/build/virtual/types/exists and contains 13 type definition files. The old pathsrc/types/virtual/has been properly removed, and the alias is actively used across 34 files in runtime, presets, and build modules. The tsconfig.json configuration is properly set.src/build/virtual/runtime-config.ts (1)
1-12: LGTM!Clean implementation following the new virtual template pattern. The fallback to
{}for undefinedruntimeConfigis appropriate.src/build/virtual/plugins.ts (1)
4-24: LGTM!The implementation correctly handles identifier generation by prefixing with
_and stripping hyphens, ensuring valid JavaScript identifiers regardless of hash output. TheSetdeduplication is appropriate for preventing duplicate plugin imports.src/build/virtual/routing.ts (1)
10-60: LGTM!The refactored routing template correctly aggregates handlers from routes, routed middleware, and global middleware, deduplicates them, and generates appropriate import statements and exports. The lazy handler support with
h3.defineLazyEventHandleris properly handled.src/build/virtual/routing-meta.ts (1)
3-31: LGTM!The routing metadata template correctly generates per-handler meta imports with the
?metaquery suffix and builds thehandlersMetaarray with route, method, and meta references. The method normalization to lowercase is appropriate for consistent matching.src/build/virtual/polyfills.ts (1)
6-11: Template logic is clean and correctly handles empty polyfills.The fallback to a comment when no polyfills are provided is a good practice for debugging.
src/build/virtual/server-assets.ts (2)
69-69: InliningnormalizeKey.toString()is fragile.If
unstoragechanges thenormalizeKeyimplementation to rely on closures or external dependencies, this approach will break silently at runtime.Consider importing
normalizeKeydirectly in the generated code instead:-const normalizeKey = ${normalizeKey.toString()} +import { normalizeKey } from 'unstorage'This would require adding the import to the generated template string at line 31.
21-31: Dev mode template looks correct.The dev/prerender path correctly mounts filesystem drivers for each configured asset, enabling hot-reload during development.
src/build/virtual/error-handler.ts (1)
5-41: Refactored structure aligns with the new virtual module pattern.The conversion from a direct
virtual(...)wrapper to returning{ id, template }is consistent with the PR's architectural changes.src/build/virtual/storage.ts (1)
30-48: Template generation logic is well-structured.The use of
genImportandgenSafeVariableNamefrom knitwork ensures safe code generation. The assets mount and storage initialization follow the expected pattern.src/build/virtual/database.ts (2)
23-27: Good validation of connector names before code generation.Throwing early with a clear error message when an invalid connector is specified helps developers debug configuration issues.
9-11: Clean early return for disabled feature.Returning an empty
connectionConfigsobject when the experimental database feature is disabled is the right approach.src/build/plugins/virtual.ts (2)
30-45: Static analysis false positive for ReDoS - the regex is safely constructed.The static analysis warning about ReDoS (Lines 33-35) is a false positive. The
escapeRegExputility properly escapes all regex metacharacters, and the module IDs come from a controlled set of internal virtual templates. The resulting pattern is a simple alternation of literal strings, which is O(n) and not vulnerable to catastrophic backtracking.
46-62: LGTM! Clean load handler implementation.The load handler correctly strips the prefix, looks up the module, and awaits the async render. Proper error handling for missing modules ensures clear failure modes.
src/build/plugins.ts (2)
18-50: LGTM! Clean consolidation of virtual module handling.The refactoring consolidates previously scattered virtual module handling into a single
virtualPlugin, which aligns with the PR objectives. The plugin ordering appears correct, with virtual templates resolved after raw imports but before the replace plugin.
45-50: I'll verify the type compatibility concern raised in this review comment. Let me start by examining the relevant files and type definitions.
<function_calls>
#!/bin/bashFind and examine the virtual template configuration and type definitions
First, find the virtual.ts file referenced
fd -t f "virtual" --extension ts | head -20
</function_calls>
<function_calls>
#!/bin/bashSearch for the virtualTemplates function and virtual plugin definition
rg -n "virtualTemplates|virtualPlugin" src/build/plugins.ts -A 5 -B 2
</function_calls>
<function_calls>
#!/bin/bashFind where virtualTemplates is imported from
rg -n "import.*virtualTemplates" src/build/plugins.ts
</function_calls>
<function_calls>
#!/bin/bashLook for the virtual module definition
fd -path "build/virtual" -type f -name "*.ts" | head -20
</function_calls>
<function_calls>
#!/bin/bashCheck the structure of src/build/plugins.ts around line 45-50
sed -n '40,55p' src/build/plugins.ts
</function_calls>
<function_calls>
#!/bin/bashCheck the type definition of nitro.vfs in types file
rg -n "vfs" src/types/nitro.ts -B 2 -A 2
</function_calls>
<function_calls>
#!/bin/bashLook for the virtual plugin API structure - search for where api.modules is defined
rg -n "api.modules|virtualPlugin.api" src/build/ -B 3 -A 3
</function_calls>
<function_calls>
#!/bin/bashFind the virtual function/module definition
fd -type f -name "_all.ts" -o -name "virtual.ts" | xargs ls -la 2>/dev/null | head -10
</function_calls>
<function_calls>
#!/bin/bashLook for files in virtual directory
find src/build/virtual -type f -name "*.ts" 2>/dev/null
</function_calls>
<function_calls>
#!/bin/bashCheck the virtual plugin implementation
find . -path "/build/virtual" -name "*.ts" -type f | head -20
</function_calls>
<function_calls>
#!/bin/bashGet the full plugins.ts file to understand context
wc -l src/build/plugins.ts
</function_calls>
<function_calls>
#!/bin/bashRead the plugins.ts file to see imports and the full context
head -50 src/build/plugins.ts
</function_calls>
<function_calls>
#!/bin/bashSearch for where virtual function comes from
rg -n "from.*virtual|import.*virtual" src/build/plugins.ts
</function_calls>
<function_calls>
#!/bin/bashLook at the build directory structure
ls -la src/build/
</function_calls>
<function_calls>
#!/bin/bashSearch for the virtual function definition anywhere in the codebase
rg -n "^export.virtual|^function virtual|virtual.=.*function" --type ts | head -30
</function_calls>
<function_calls>
#!/bin/bashLook for nitro.vfs type definition
rg -n "interface Nitro|type Nitro" src/types/ -A 50 | head -100
</function_calls>
<function_calls>
#!/bin/bashSearch for vfs property specifically in Nitro type
rg -n "vfs\s*[:?]" src/types/nitro.ts -B 2 -A 2
</function_calls>Now let me check what the actual structure of the plugins.ts file is, including all imports:
<function_calls>
#!/bin/bashRead full plugins.ts to understand it completely
cat -n src/build/plugins.ts
</function_calls>Let me check the types file as well:
<function_calls>
#!/bin/bashSearch for Nitro interface in types
cat -n src/types/nitro.ts | head -100
</function_calls>Let me search more broadly for the virtual module and vfs definition:
<function_calls>
#!/bin/bashSearch more flexibly for vfs
rg -n "vfs" src/types/ --type ts -B 3 -A 3
</function_calls>
<function_calls>
#!/bin/bashLook for how virtualTemplates and virtual are used
rg -n "virtual(" src/build/plugins.ts -B 5 -A 10
</function_calls>Let me check if there's package information or look at the structure differently:
<function_calls>
#!/bin/bashList files in src/types
ls -la src/types/
</function_calls>
<function_calls>
#!/bin/bashLook at all type files
find src/types -name "*.ts" -type f
</function_calls>
<function_calls>
#!/bin/bashSearch entire codebase for vfs definition
rg -n "^\svfs\s[:?]" --type ts
</function_calls>
<function_calls>
#!/bin/bashSearch for VirtualModule type
rg -n "VirtualModule|type.*Module.*render" --type ts | head -30
</function_calls>Let me get a comprehensive view of all TypeScript files in the repository to understand structure:
<function_calls>
#!/bin/bashFind all main type/interface files
fd -e ts -type f src/ | grep -E "(types|interface)" | head -20
</function_calls>
<function_calls>
#!/bin/bashGet a high-level view of src structure
find src -maxdepth 2 -type d | sort
</function_calls>Now let me search for the actual usage pattern more directly:
<function_calls>
#!/bin/bashSearch for nitro.vfs assignments or references
rg -n "nitro.vfs\s*=" --type ts -B 3 -A 3
</function_calls>
<function_calls>
#!/bin/bashTry to understand the virtual plugin package being used
rg -n "virtual|rollup" src/build/plugins.ts | head -20
</function_calls>Let me examine the package.json to understand external dependencies:
<function_calls>
#!/bin/bashCheck package.json for relevant packages
cat package.json | grep -A 20 -B 2 "virtual|rollup"
</function_calls>
<function_calls>
#!/bin/bashLet me read the entire plugins.ts more carefully with context
sed -n '1,100p' src/build/plugins.ts | cat -n
</function_calls>Let me check if there's a compiled version or build output that might give us hints:
<function_calls>
#!/bin/bashSearch for all references to .api.modules
rg -n ".api.modules" --type ts -B 5 -A 3
</function_calls>Let me search for the Nitro class/interface definition more systematically:
<function_calls>
#!/bin/bashSearch for where Nitro type is defined or extended
rg -n "class Nitro|interface Nitro|type Nitro|export.*Nitro" --type ts | head -20
</function_calls>
<function_calls>
#!/bin/bashLook at all files in src directory
find src -name "*.ts" -type f | sort
</function_calls>Let me try a different approach - check if there's a dist or other compiled outputs:
<function_calls>
#!/bin/bashCheck what's in the root directory
ls -la | grep -E "^d"
</function_calls>
<function_calls>
#!/bin/bashList all TS files in src to understand structure
fd -t f -e ts src/ | sort
</function_calls>Now let me read the actual files mentioned:
<function_calls>
#!/bin/bashRead plugins.ts completely
cat src/build/plugins.ts
</function_calls>Perfect! Now let me check the types file:
<function_calls>
#!/bin/bashRead the nitro types file
cat src/types/nitro.ts
</function_calls>Now let me check the virtual/_all.ts file to understand the structure of virtualTemplates:
<function_calls>
#!/bin/bashFind and read virtual/_all.ts
if [ -f "src/build/virtual/_all.ts" ]; then
cat src/build/virtual/_all.ts
fi
</function_calls>
<function_calls>
#!/bin/bashList files in virtual directory
ls -la src/build/virtual/
</function_calls>Let me check the package.json for the virtual plugin dependency:
<function_calls>
#!/bin/bashRead package.json to find the virtual plugin
cat package.json | python3 -m json.tool | grep -A 10 -B 2 "virtual"
</function_calls>Let me check what virtual refers to in the imports more carefully:
<function_calls>
#!/bin/bashSearch for external 'virtual' module usage
rg -n "from\s+['"]virtual['"]" --type ts
</function_calls>
<function_calls>
#!/bin/bashCheck if it's from @rollup/plugin-virtual
rg -n "@rollup|rollup.*virtual" --type ts -C 3
</function_calls>Let me check the actual imports in plugins.ts:
<function_calls>
#!/bin/bashExtract all imports from plugins.ts
sed -n '1,20p' src/build/plugins.ts
</function_calls>Now let me search for the virtual function type definition:
<function_calls>
#!/bin/bashSearch for the virtual function in node_modules or type stubs
First check what virtual is imported from
rg -n "virtual" src/build/plugins.ts | head -10
</function_calls>Let me check the full plugins.ts import section more carefully:
<function_calls>
#!/bin/bashGet first 25 lines of plugins.ts to see all imports
head -25 src/build/plugins.ts
</function_calls>Now let me look at the actual type definition by searching package.json dependencies:
<function_calls>
#!/bin/bashCheck dependencies
grep -E "virtual|rollup" package.json
</function_calls>Let me search for TypeScript configuration to understand module resolution:
<function_calls>
#!/bin/bashCheck tsconfig
cat tsconfig.json 2>/dev/null | head -50
</function_calls>Let me check if there's path aliases:
<function_calls>
#!/bin/bashLook for path aliases
cat tsconfig.json | grep -A 10 "paths"
</function_calls>Now let me check the actual implementation by reviewing where virtual plugin gets assigned:
<function_calls>
#!/bin/bashGet lines around the virtualPlugin creation (lines 45-50)
sed -n '40,60p' src/build/plugins.ts | cat -n
</function_calls>Let me look for how the virtual function is imported by checking the full import section:
<function_calls>
#!/bin/bashShow first 50 lines to capture all imports and understand where virtual comes from
head -50 src/build/plugins.ts | cat -n
</function_calls>Now let me examine the full nitro types to check vfs property type:
<function_calls>
#!/bin/bashLook at nitro.ts around vfs definition
grep -n "vfs" src/types/nitro.ts -B 5 -A 5
</function_calls>Let me check web resources about @rollup/plugin-virtual to understand its API:
<function_calls>
@rollup/plugin-virtual API modules structure TypeScript
</function_calls>src/build/virtual/renderer-template.ts (1)
9-52: LGTM! Well-structured renderer template with proper dev/prod branching.The template correctly handles three scenarios:
- No template configured → static placeholder
- Development → dynamic file reading for HMR
- Production → static vs dynamic rendering based on template syntax
The use of
compileTemplateToStringfrom rendu for dynamic templates and pre-reading files during production builds is appropriate.src/build/virtual/feature-flags.ts (1)
3-30: All verification checks passed—no issues found.The
hasRoutes()method is confirmed to exist on the Router class (src/routing.ts:179-181), and all three routing properties (routes,routeRules,routedMiddleware) are correctly typed asRouter<T>instances in the Nitro type definition (src/types/nitro.ts:26-32). The feature flags template correctly calls this method on each property.The observation about
Boolean(value)being redundant is valid—all values in thefeatureFlagsobject are already booleans—but this is harmless and defensive coding. The implementation is correct.src/build/virtual/public-assets.ts (4)
21-72: LGTM! Clean refactoring of asset data generation.The shift from a plugin-based approach to a template-based virtual module is well-structured. The asset metadata computation correctly handles MIME types, encodings, and conditional inlining.
74-122: LGTM! Solid integration of virtual module imports.The dynamic handler selection and helper function exports provide a clean API surface. The logic correctly filters and transforms publicAssets configuration.
126-140: LGTM! Node.js asset reader implementation is correct.Properly uses Node.js filesystem APIs and resolves paths relative to the server directory.
142-154: LGTM! Deno asset reader implementation is correct.Properly uses Deno's file reading API and constructs paths appropriately for Deno Deploy.
commit: |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/build/virtual/storage.ts (1)
17-26: Add validation for required driver property.The destructuring on line 18 correctly separates the driver from options, addressing the past review comment. However, there's no validation that each mount configuration has a
driverproperty. Ifdriveris missing,driverNamebecomesundefined, which would cause issues in the generated import and mount statements.Consider adding validation similar to the database module:
for (const path in storageMounts) { - const { driver: driverName, ...driverOpts } = storageMounts[path]; + const mount = storageMounts[path]; + if (!mount?.driver) { + throw new Error(`Storage mount "${path}" is missing required "driver" property.`); + } + const { driver: driverName, ...driverOpts } = mount; mounts.push({
🧹 Nitpick comments (1)
src/presets/winterjs/runtime/winterjs.ts (1)
2-2: WinterJS now imports the shared polyfills alias; consider future cleanupThe switch to
#nitro-internal-polyfillsis correct and keeps this entry in sync with the rest of the presets. Given the// TODO: Remove after removing polyfillsnote and the custom polyfill block below, it may be worth revisiting this file in a follow-up to consolidate on the shared polyfills module and drop the local shims/@ts-nocheckonce safe.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (29)
src/build/virtual/database.ts(1 hunks)src/build/virtual/polyfills.ts(1 hunks)src/build/virtual/storage.ts(1 hunks)src/presets/_nitro/runtime/nitro-dev.ts(1 hunks)src/presets/_nitro/runtime/nitro-prerenderer.ts(1 hunks)src/presets/_nitro/runtime/service-worker.ts(1 hunks)src/presets/aws-amplify/runtime/aws-amplify.ts(1 hunks)src/presets/aws-lambda/runtime/aws-lambda-streaming.ts(1 hunks)src/presets/aws-lambda/runtime/aws-lambda.ts(1 hunks)src/presets/azure/runtime/azure-swa.ts(1 hunks)src/presets/bun/runtime/bun.ts(1 hunks)src/presets/cloudflare/runtime/_module-handler.ts(1 hunks)src/presets/cloudflare/runtime/cloudflare-durable.ts(1 hunks)src/presets/cloudflare/runtime/cloudflare-module.ts(1 hunks)src/presets/cloudflare/runtime/cloudflare-pages.ts(1 hunks)src/presets/deno/runtime/deno-deploy.ts(1 hunks)src/presets/deno/runtime/deno-server.ts(1 hunks)src/presets/netlify/runtime/netlify-edge.ts(1 hunks)src/presets/netlify/runtime/netlify.ts(1 hunks)src/presets/node/runtime/node-cluster.ts(1 hunks)src/presets/node/runtime/node-middleware.ts(1 hunks)src/presets/node/runtime/node-server.ts(1 hunks)src/presets/standard/runtime/server.ts(1 hunks)src/presets/stormkit/runtime/stormkit.ts(1 hunks)src/presets/vercel/runtime/vercel.node.ts(1 hunks)src/presets/vercel/runtime/vercel.web.ts(1 hunks)src/presets/winterjs/runtime/winterjs.ts(1 hunks)src/presets/zeabur/runtime/zeabur.ts(1 hunks)src/runtime/internal/vite/dev-entry.mjs(1 hunks)
✅ Files skipped from review due to trivial changes (8)
- src/presets/stormkit/runtime/stormkit.ts
- src/presets/deno/runtime/deno-deploy.ts
- src/presets/_nitro/runtime/service-worker.ts
- src/presets/standard/runtime/server.ts
- src/presets/aws-lambda/runtime/aws-lambda.ts
- src/presets/cloudflare/runtime/_module-handler.ts
- src/presets/vercel/runtime/vercel.web.ts
- src/presets/netlify/runtime/netlify.ts
🧰 Additional context used
🧬 Code graph analysis (3)
src/build/virtual/storage.ts (1)
src/types/nitro.ts (1)
Nitro(16-37)
src/build/virtual/polyfills.ts (1)
src/types/nitro.ts (1)
Nitro(16-37)
src/build/virtual/database.ts (1)
src/types/nitro.ts (1)
Nitro(16-37)
⏰ 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: tests-rolldown (windows-latest)
- GitHub Check: tests-rollup (windows-latest)
🔇 Additional comments (25)
src/presets/cloudflare/runtime/cloudflare-durable.ts (1)
1-1: LGTM! Typo fix aligns with standardization effort.The import path correction from "pollyfills" to "polyfills" is accurate and aligns with the broader standardization of polyfills imports across the codebase.
src/presets/_nitro/runtime/nitro-dev.ts (1)
1-1: Typo fix verified as complete and consistent across the codebase.The import path correction from "pollyfills" to "polyfills" has been applied comprehensively. Search results confirm:
- Zero remaining references to the old typo'd path "#nitro-internal-pollyfills"
- 27+ files consistently using the corrected path "#nitro-internal-polyfills"
- The corrected path is properly defined in
src/build/virtual/polyfills.tsas a virtual moduleThe change is correct and requires no further action.
src/presets/node/runtime/node-cluster.ts (1)
1-1: Polyfills alias rename looks correctSwitching to
"#nitro-internal-polyfills"aligns this runtime with the standardized internal polyfills alias and keeps the side‑effect import ordering intact. No further changes needed in this file.src/presets/_nitro/runtime/nitro-prerenderer.ts (1)
1-1: Polyfills alias correction looks goodUsing
#nitro-internal-polyfillshere keeps the prerender entry consistent with the new shared polyfills virtual module; no other behavior changes.src/presets/cloudflare/runtime/cloudflare-pages.ts (1)
1-1: Cloudflare Pages now uses the canonical polyfills aliasThe corrected
#nitro-internal-polyfillsimport matches the rest of the presets and keeps polyfills loaded before any runtime logic.src/presets/azure/runtime/azure-swa.ts (1)
1-1: Azure SWA polyfills import is correctly alignedSwitch to
#nitro-internal-polyfillsis consistent with the new virtual polyfills module; no further adjustments needed here.src/presets/zeabur/runtime/zeabur.ts (1)
1-1: Zeabur runtime uses the unified polyfills aliasThe updated
#nitro-internal-polyfillsimport matches the rest of the runtime entries; wrapper logic stays the same.src/presets/cloudflare/runtime/cloudflare-module.ts (1)
1-1: Cloudflare module polyfills import correctedUsing
#nitro-internal-polyfillshere matches the rest of the Cloudflare runtimes and ensures polyfills load before handler creation.src/presets/aws-amplify/runtime/aws-amplify.ts (1)
1-1: AWS Amplify runtime aligned to shared polyfills aliasThe updated
#nitro-internal-polyfillsimport is consistent with other Node-style presets; server startup logic remains the same.src/presets/aws-lambda/runtime/aws-lambda-streaming.ts (1)
1-1: AWS Lambda streaming entry now uses the canonical polyfills moduleCorrecting the import to
#nitro-internal-polyfillsbrings this entry in line with the rest of the runtime surface; streaming behavior is unchanged.src/presets/netlify/runtime/netlify-edge.ts (1)
1-1: LGTM: Polyfills import path corrected.The import path has been correctly updated from the typo
#nitro-internal-pollyfillsto#nitro-internal-polyfills.src/presets/node/runtime/node-server.ts (1)
1-1: LGTM: Polyfills import path corrected.The import path has been correctly updated from the typo
#nitro-internal-pollyfillsto#nitro-internal-polyfills.src/presets/bun/runtime/bun.ts (1)
1-1: LGTM: Polyfills import path corrected.The import path has been correctly updated from the typo
#nitro-internal-pollyfillsto#nitro-internal-polyfills.src/presets/node/runtime/node-middleware.ts (1)
1-1: LGTM: Polyfills import path corrected.The import path has been correctly updated from the typo
#nitro-internal-pollyfillsto#nitro-internal-polyfills.src/runtime/internal/vite/dev-entry.mjs (1)
1-1: LGTM: Polyfills import path corrected.The import path has been correctly updated from the typo
#nitro-internal-pollyfillsto#nitro-internal-polyfills.src/presets/deno/runtime/deno-server.ts (1)
1-1: LGTM: Polyfills import path corrected.The import path has been correctly updated from the typo
#nitro-internal-pollyfillsto#nitro-internal-polyfills.src/presets/vercel/runtime/vercel.node.ts (1)
1-1: LGTM: Polyfills import path corrected.The import path has been correctly updated from the typo
#nitro-internal-pollyfillsto#nitro-internal-polyfills.src/build/virtual/polyfills.ts (1)
1-14: Typo fix verified: No references to old path remain in codebase.The virtual module implementation is correct, and the typo fix (
"#nitro-internal-pollyfills"→"#nitro-internal-polyfills") has been comprehensively addressed with no lingering references to the old path detected anywhere in the codebase.src/build/virtual/database.ts (4)
1-4: LGTM!The imports are appropriate for the virtual module's functionality.
5-11: LGTM!The early return for disabled experimental database feature is appropriate and efficient.
13-21: LGTM!The connector name extraction correctly handles dev/prerender mode fallback and safely filters undefined connectors using optional chaining and Boolean filtering.
23-27: LGTM!The connector validation provides early, clear feedback for invalid connector names, which is essential for catching configuration errors at build time.
src/build/virtual/storage.ts (3)
1-4: LGTM!The imports are appropriate for generating the storage virtual module.
5-16: LGTM!The dev/prerender mode detection and storage config merging logic correctly prioritizes devStorage when appropriate.
28-49: LGTM!The template generation correctly deduplicates driver imports, uses safe variable names, and properly serializes mount options. The generated
initStorage()function structure is sound.
Nitro has several virtual templates which were being provided individually, each as a rollup plugin.
This PR refactors them into build/templates as abstract entries and uses a single VFS plugin that resolves them. Now with filter hooks that also reduce builder hook calls.
Minor breaking change: Type of
nitro.vfschange toMap<string, { render }>as this allowed better lazy rendering.