Skip to content

refactor(nuxt): move island renderer into its own event handler#31386

Merged
danielroe merged 33 commits intomainfrom
refactor/_nuxt_island
Apr 4, 2025
Merged

refactor(nuxt): move island renderer into its own event handler#31386
danielroe merged 33 commits intomainfrom
refactor/_nuxt_island

Conversation

@huang-julien
Copy link
Copy Markdown
Member

🔗 Linked issue

📚 Description

This PR moves nuxt island into its own endpoint for better readability of the render handler.
It also extract all shared logic within utils/renderer.

@bolt-new-by-stackblitz
Copy link
Copy Markdown

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 16, 2025

Open in StackBlitz

@nuxt/kit

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

nuxt

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

@nuxt/rspack-builder

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

@nuxt/schema

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

@nuxt/vite-builder

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

@nuxt/webpack-builder

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

commit: 63a98e6

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Mar 16, 2025

CodSpeed Performance Report

Merging #31386 will not alter performance

Comparing refactor/_nuxt_island (63a98e6) with main (c4af429)

Summary

✅ 10 untouched benchmarks

@huang-julien
Copy link
Copy Markdown
Member Author

wat
image

@huang-julien huang-julien force-pushed the refactor/_nuxt_island branch from ea566a0 to 29ed300 Compare March 28, 2025 21:25
@huang-julien huang-julien force-pushed the refactor/_nuxt_island branch from 6e56299 to 8250de0 Compare April 3, 2025 19:13
@huang-julien huang-julien marked this pull request as ready for review April 3, 2025 21:26
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2025

Walkthrough

This pull request restructures various aspects of the Nuxt codebase. Type exports have been reorganised by moving the island-related types to a new module and adjusting the export statements accordingly. The server initialisation process now includes an additional condition to add a new server handler for handling requests aimed at island components. Several functions and interfaces handling island rendering have been removed from the primary renderer, while new functions to create and manage the SSR context, alongside error handling, have been introduced. Furthermore, a new utility for inlining styles and a dedicated module for processing island responses and HTML manipulations have been added. Minor adjustments have been made to the build files and tests to reflect these changes.


📜 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 9eccac7 and 63a98e6.

📒 Files selected for processing (1)
  • packages/nuxt/src/core/nuxt.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: codeql (actions)
  • GitHub Check: codeql (javascript-typescript)
  • GitHub Check: build
🔇 Additional comments (3)
packages/nuxt/src/core/nuxt.ts (3)

9-9: No issues with the newly added imports.

This line cleanly introduces the necessary imports for adding the server template and handler.


628-637: Potential timing concern with nuxt.apps.default.

There remains a risk that nuxt.apps.default is not fully initialised when this conditional check runs. Consider moving the addition of this server template to a later hook or after Nitro is initialised to ensure that app data is fully available before referencing it.


638-642: Server handler route setup looks good.

Registering a dedicated route for the island renderer aligns with the refactor objective, with no apparent issues here.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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 (10)
packages/nuxt/src/core/runtime/nitro/utils/renderer/inline-styles.ts (1)

4-14: Consider adding error handling for style retrieval.

Everything appears correct, but you might want to handle potential load failures in styleMap[mod]() with a try/catch or fallback for safer runtime behaviour.

packages/nuxt/src/core/runtime/nitro/utils/renderer/app.ts (1)

12-36: Consider unifying noSSR logic
The createSSRContext function neatly sets up the SSR context, including environment checks and prerender logic. As a small improvement, you might consider extracting the repeating noSSR condition checks into a separate helper to maintain clarity.

packages/nuxt/src/core/runtime/nitro/handlers/__nuxt_island.ts (3)

30-42: SSR context creation & island context
You correctly initialise both SSR and island contexts here. A minor recommendation might be to verify that islandContext.url is safe or expected if altered. Overall, this is a solid approach.


71-85: Constructing the island head
Collecting all head entries into islandHead ensures consolidated control over metadata. Consider deduplicating entries if multiple identical tags appear.


103-128: Island context retrieval and TODO
getIslandContext gracefully combines URL parsing with property extraction. The TODO: Strict validation for url indicates a known gap. If you need assistance implementing robust validation, feel free to request.

packages/nuxt/src/core/runtime/nitro/utils/renderer/build-files.ts (2)

21-21: Dynamic server entry import
This approach provides flexibility, though be mindful of error handling if the file fails to load.


24-26: Client manifest import
Similarly, ensure proper fallback if the manifest is missing or invalid. Otherwise, this dynamic import pattern is consistent.

packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts (1)

87-87: Consider using optional chaining in the condition.
You can simplify this condition by using if (ssrError?.statusCode) { ... }. This helps reduce nesting and aligns with the static analysis hint.

-if (ssrError && ssrError.statusCode) {
+if (ssrError?.statusCode) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 87-87: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/nuxt/src/core/runtime/nitro/utils/renderer/islands.ts (2)

6-14: Graceful HTML extraction in getServerComponentHTML.
Returning the entire body if the root node is not matched ensures a safe fallback. If you want to debug or warn on unexpected content, consider adding logging for mismatch scenarios.


63-87: Island teleports replacement is robust.
This approach systematically patches the original HTML with teleport content based on SSR markers. Keep in mind any potential performance impact for very large HTML, though this is typically acceptable.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6abda6e and d72d9e8.

📒 Files selected for processing (9)
  • packages/nuxt/src/app/types.ts (1 hunks)
  • packages/nuxt/src/core/nuxt.ts (2 hunks)
  • packages/nuxt/src/core/runtime/nitro/handlers/__nuxt_island.ts (1 hunks)
  • packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts (9 hunks)
  • packages/nuxt/src/core/runtime/nitro/utils/renderer/app.ts (1 hunks)
  • packages/nuxt/src/core/runtime/nitro/utils/renderer/build-files.ts (3 hunks)
  • packages/nuxt/src/core/runtime/nitro/utils/renderer/inline-styles.ts (1 hunks)
  • packages/nuxt/src/core/runtime/nitro/utils/renderer/islands.ts (1 hunks)
  • test/bundle.test.ts (3 hunks)
🧰 Additional context used
🧬 Code Definitions (4)
packages/nuxt/src/core/runtime/nitro/utils/renderer/inline-styles.ts (1)
packages/nuxt/src/core/runtime/nitro/utils/renderer/build-files.ts (1)
  • getSSRStyles (118-118)
packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts (5)
packages/nuxt/src/app/nuxt.ts (1)
  • NuxtSSRContext (60-85)
packages/nuxt/src/core/runtime/nitro/utils/renderer/app.ts (2)
  • createSSRContext (12-36)
  • setSSRError (38-42)
packages/nuxt/src/core/runtime/nitro/utils/renderer/build-files.ts (1)
  • getRenderer (113-115)
packages/nuxt/src/core/runtime/nitro/utils/cache.ts (1)
  • payloadCache (3-3)
packages/nuxt/src/core/runtime/nitro/utils/renderer/payload.ts (1)
  • renderPayloadResponse (12-24)
packages/nuxt/src/core/runtime/nitro/handlers/__nuxt_island.ts (5)
packages/nuxt/src/core/runtime/nitro/utils/renderer/app.ts (1)
  • createSSRContext (12-36)
packages/nuxt/src/core/runtime/nitro/utils/renderer/build-files.ts (1)
  • getRenderer (113-115)
packages/nuxt/src/core/runtime/nitro/utils/renderer/inline-styles.ts (1)
  • renderInlineStyles (4-15)
packages/nuxt/src/app/types.ts (2)
  • NuxtIslandResponse (8-8)
  • NuxtIslandContext (8-8)
packages/nuxt/src/core/runtime/nitro/utils/renderer/islands.ts (5)
  • NuxtIslandResponse (103-110)
  • getServerComponentHTML (11-14)
  • getClientIslandResponse (32-46)
  • getSlotIslandResponse (20-30)
  • NuxtIslandContext (94-101)
packages/nuxt/src/core/runtime/nitro/utils/renderer/islands.ts (1)
packages/nuxt/src/app/types.ts (2)
  • NuxtIslandResponse (8-8)
  • NuxtIslandContext (8-8)
🪛 Biome (1.9.4)
packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts

[error] 87-87: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (25)
packages/nuxt/src/app/types.ts (1)

7-8: Re-export changes look valid.

These updated re-exports for island-related types appear consistent and tidy. No concerns.

packages/nuxt/src/core/nuxt.ts (2)

9-9: New import is appropriate.

Adding addServerHandler is needed for registering the new route. Approved.


628-631: Island route registration is correct.

This handler logic is clear. Consider verifying it does not conflict with existing routes, but otherwise it looks fine.

test/bundle.test.ts (1)

61-61: Updated snapshot values are acceptable.

These new inline snapshot values are consistent with the larger server bundles introduced by the new island rendering logic.

Also applies to: 64-64, 98-98, 101-101, 120-120

packages/nuxt/src/core/runtime/nitro/utils/renderer/app.ts (3)

1-9: Imports appear well-structured
These imports and type references look consistent, and the @ts-expect-error directive is clearly explained. No issues found.


10-11: Constant definition
Defining PRERENDER_NO_SSR_ROUTES here is straightforward and keeps the prerender routes clearly visible in the code.


38-42: Error handling
The setSSRError function succinctly marks the context as erroneous and injects details into the payload. This helps keep error states consolidated.

packages/nuxt/src/core/runtime/nitro/handlers/__nuxt_island.ts (6)

1-14: Import organisation
These imports are well-organised, providing clear entry points for rendering, caching, and event utilities. No issues identified.


16-28: Handler initialisation
Defining ISLAND_SUFFIX_RE and setting JSON response headers in defineEventHandler is straightforward and intuitive.


43-46: Post-render hook
Calling app:rendered allows for flexible post-render operations. This helps maintain separation of concerns and is a good practice.


47-69: Inline styles & development styling
Rendering inline styles and conditionally adding CSS links in dev mode is well handled. Ensuring no duplication of links in production is a nice efficiency measure.


86-93: Island response assembly
Building the NuxtIslandResponse object here is clear and expressive. The integration with server and client components is structured well.


94-101: Prerender caching
Storing the island output in caches facilitates subsequent quick lookups. The approach is robust for prerendered deployments.

packages/nuxt/src/core/runtime/nitro/utils/renderer/build-files.ts (4)

29-29: Lazy-cached SSR renderer
Wrapping getSSRRenderer with lazyCachedFunction makes sense for performance. No concerns here.


60-60: Lazy-cached SPA renderer
Applying the same pattern for the SPA renderer is consistent and ensures one-time setup. Looks good.


114-115: getRenderer unifies SSR & SPA
Exporting getRenderer to route logic through SSR or SPA rendering is cohesive. This centralises decision-making effectively.


117-124: Style retrieval
getSSRStyles and getEntryIds guarantee the retrieval of styles for inline injection. This is a straightforward, well-structured solution.

packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts (4)

9-23: All newly introduced imports are appropriately used.
These imports accurately reflect their usage across the file, such as payload caching, SSR context creation, and inline style rendering.


95-98: Validate edge cases for URL rewriting.
When extracting the preceding segment of the URL, ensure that unusual scenarios (e.g. no slashes in the path) are handled gracefully. The fallback to '/' is correct, but keep an eye on potential usage conflicts when modifying event.node.req.url.

Do you want to confirm or test how the system behaves with paths that lack slashes?


107-108: Neat approach for handling disabling SSR routes.
Setting ssrContext.noSSR to respect routeOptions.ssr === false is a clear and logical pattern.


273-281: Final response construction looks good.
The HTML is rendered with proper headers, status, and content type. No issues spotted here.

packages/nuxt/src/core/runtime/nitro/utils/renderer/islands.ts (4)

20-30: Slot island response logic is concise.
Retrieving slots from ssrContext.islandContext.slots and merging with fallback content is well-structured. The code clearly handles absent slots by returning undefined.


32-46: Client island response generation is clear.
Removing the teleport anchors via replaceAll is a practical approach to avoid hydration issues. The function appropriately organises slots in the returned object.


48-61: Clean slot teleport processing.
Using a straightforward loop and regex matching to locate teleports is a good pattern. No further issues found.


89-117: Interfaces for islands improve clarity and maintainability.
The definition of NuxtIslandSlotResponse, NuxtIslandContext, NuxtIslandResponse, and NuxtIslandClientResponse is precise and evidently suited to the use cases in the new SSR flow.

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 (4)
packages/nuxt/src/core/nuxt.ts (1)

628-635: Conditionally adding the __nuxt_island handler.

Registering the island handler (addServerHandler) under '/__nuxt_island/**' is a good solution for supporting the island functionality based on the current environment, componentIslands configuration, and server/client mode checks.

Consider verifying that no conflicts exist with other server routes and that any requests for this route inherently require the intended permissions/headers. Otherwise, this change looks solid.

packages/nuxt/src/core/runtime/nitro/handlers/island.ts (3)

43-69: Inline styles and development mode stylesheet injection.

Expanding the head with inlined styles and conditionally adding stylesheets in dev mode addresses CSS injection for scoped resources. Be mindful of potential performance implications if too many styles are inlined, especially in larger projects. Otherwise, this logic is a solid approach for local development.


71-101: Constructing the island response and caching.

Populating the islandHead, assembling the server-rendered HTML, and caching the final island response are essential to the island concept. The response structure is coherent. For future enhancements, consider fallback or retry logic when fetching from or setting to the cache, especially in distributed hosting scenarios.


103-128: Island context extraction and validation.

Retrieving the island context from the request is straightforward, but the TODO comments indicate areas for stricter URL and props validation. This is essential to secure the application against malformed requests. Consider adding robust validation or sanitisation steps for production reliability.

Do you want help generating a snippet with stricter property checks (e.g. using runtime validators) for the url and props fields?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d72d9e8 and 3810f78.

📒 Files selected for processing (3)
  • packages/nuxt/src/core/nuxt.ts (2 hunks)
  • packages/nuxt/src/core/runtime/nitro/handlers/island.ts (1 hunks)
  • test/bundle.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/bundle.test.ts
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: code
  • GitHub Check: build
🔇 Additional comments (3)
packages/nuxt/src/core/nuxt.ts (1)

9-9: Successfully imported addServerHandler.

The newly added import of addServerHandler from @nuxt/kit is correct and aligns with the usage in subsequent lines. No concerns regarding this addition.

packages/nuxt/src/core/runtime/nitro/handlers/island.ts (2)

1-17: Imports and constant definition.

All required imports are neatly organised, covering SSR context creation, caching, and relevant modules for island handling. The ISLAND_SUFFIX_RE constant clearly separates JSON suffix handling logic. This section appears well-structured.


18-41: Core event handler setup and error handling.

Defining a dedicated event handler for rendering islands sets a clear entry point. Error handling with app:error ensures that any rendering failures are captured by Nuxt error hooks. This approach looks correct and maintainable.

Copy link
Copy Markdown
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.

very nice

@danielroe danielroe changed the title refactor(nuxt): move __nuxt_islands into its own event handler refactor(nuxt): move island renderer into its own event handler Apr 4, 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: 5

🧹 Nitpick comments (12)
packages/nuxt/src/core/runtime/nitro/handlers/island.ts (5)

16-16: Track pending TODO items.
// TODO: remove for v4 implies an upcoming removal. Make sure to create or link to an issue to track this removal so it won't be overlooked.

Do you need assistance opening a ticket to ensure this is addressed before v4?


18-28: Consider validating JSON content header.
You are setting the response content type to JSON. If the request might return an error message or HTML snippet under some conditions, ensure that the code consistently returns valid JSON.


42-45: Surface more descriptive error messages.
Within the catch block, consider enhancing error logs to include context about the failed island rendering. This will aid debugging.


49-53: Watch out for potential memory bloat with inlined styles.
Inlined styles can quickly grow and inflate payload size. Consider implementing cache or usage checks for large modules to maintain performance.


86-86: Confirm the rationale for legacy support.
The TODO at this line suggests temporary support that might be removed later. Ensure you clearly communicate to maintainers or downstream consumers about the upcoming deprecation.

packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts (5)

11-11: Watch for performance overhead in renderSSRHead.
Since renderSSRHead can become expensive on large projects, ensure it’s not invoked unnecessarily.


92-99: Ensure accurate route rewriting for payload extraction.
Modifying event._path at line 98 can lead to confusion if other parts of the system rely on event.path. Document or double-check these references.


112-114: Clarify logic behind _PAYLOAD_EXTRACTION.
Combining import.meta.prerender checks with process.env.NUXT_PAYLOAD_EXTRACTION can become convoluted. Consider extracting into a helper function to keep this snippet simpler.


198-213: Optimise CSS loading in production.
Currently, all CSS resources are pushed into <head>. If the project grows, explore lazy-loading or chunk-based strategies to keep overhead minimal.


243-254: Account for script type in older browsers.
Some older browsers might fail to parse modules with type='module'. If supporting legacy browsers, consider a fallback or transpile approach.

packages/nuxt/src/core/runtime/nitro/utils/renderer/islands.ts (2)

11-14: Handle missing root node gracefully.
If regex fails to match the root node, you return the entire body. Consider logging a debug message or warning when fallback logic is triggered to aid debugging.


32-46: Consider deduplicating repeated code across component & slot responses.
getClientIslandResponse parallels the slot approach. Factor out shared logic to keep maintainability high and reduce potential bugs.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3810f78 and 6c65b56.

📒 Files selected for processing (5)
  • packages/nuxt/src/core/runtime/nitro/handlers/island.ts (1 hunks)
  • packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts (9 hunks)
  • packages/nuxt/src/core/runtime/nitro/utils/renderer/app.ts (1 hunks)
  • packages/nuxt/src/core/runtime/nitro/utils/renderer/build-files.ts (3 hunks)
  • packages/nuxt/src/core/runtime/nitro/utils/renderer/islands.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/nuxt/src/core/runtime/nitro/utils/renderer/app.ts
  • packages/nuxt/src/core/runtime/nitro/utils/renderer/build-files.ts
🧰 Additional context used
🧬 Code Definitions (3)
packages/nuxt/src/core/runtime/nitro/handlers/island.ts (3)
packages/nuxt/src/core/runtime/nitro/utils/renderer/app.ts (1)
  • createSSRContext (12-34)
packages/nuxt/src/core/runtime/nitro/utils/renderer/build-files.ts (1)
  • getSSRRenderer (29-57)
packages/nuxt/src/core/runtime/nitro/utils/renderer/islands.ts (5)
  • NuxtIslandResponse (103-110)
  • getServerComponentHTML (11-14)
  • getClientIslandResponse (32-46)
  • getSlotIslandResponse (20-30)
  • NuxtIslandContext (94-101)
packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts (5)
packages/nuxt/src/app/nuxt.ts (1)
  • NuxtSSRContext (60-85)
packages/nuxt/src/core/runtime/nitro/utils/renderer/app.ts (2)
  • createSSRContext (12-34)
  • setSSRError (36-40)
packages/nuxt/src/core/runtime/nitro/utils/renderer/build-files.ts (1)
  • getRenderer (113-115)
packages/nuxt/src/core/runtime/nitro/utils/cache.ts (1)
  • payloadCache (3-3)
packages/nuxt/src/core/runtime/nitro/utils/renderer/payload.ts (1)
  • renderPayloadResponse (12-24)
packages/nuxt/src/core/runtime/nitro/utils/renderer/islands.ts (1)
packages/nuxt/src/app/types.ts (2)
  • NuxtIslandResponse (8-8)
  • NuxtIslandContext (8-8)
🪛 Biome (1.9.4)
packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts

[error] 87-87: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build
  • GitHub Check: codeql (javascript-typescript)
  • GitHub Check: code
🔇 Additional comments (10)
packages/nuxt/src/core/runtime/nitro/handlers/island.ts (1)

30-37: Short-circuit the rendering flow if island context is invalid.
After extracting islandContext, consider validating required properties (like name) before proceeding to render. It prevents unexpected behaviour if the context is incomplete or corrupted.

packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts (7)

9-9: Ensure graceful fallback for unknown queries.
When importing getQuery from h3, confirm that it won't cause unexpected behaviour if the query is large, missing, or malformed.


17-18: Verify presence of caching strategy.
You now use a payloadCache but ensure that the entire route rendering is consistent with the intended caching model, especially under high concurrency.


81-84: Avoid potential duplication in SSR context creation.
You create the SSR context at line 81. Confirm that it’s only done once per request and that previous partial contexts are not reused.


87-90: Optional chaining trigger from static analysis.
Static analysis suggests changing the ssrError && ssrError.statusCode check to optional chaining. While not strictly necessary, it may simplify your condition:

-if (ssrError && ssrError.statusCode) {
+if (ssrError?.statusCode) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 87-87: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


107-108: Re-check SSR toggling logic.
Setting ssrContext.noSSR to true if routeOptions.ssr === false might ignore other conditions that disable SSR. Confirm no collisions occur with environment variables or runtime config.


116-116: Check rendering fallback for no renderer found.
getRenderer(ssrContext) can theoretically return undefined if something misfires. Consider handling that gracefully to avoid runtime exceptions.


225-239: Confirm script insertion order.
Payload scripts are appended with tagPosition: 'bodyClose' at line 236. Confirm that any dependencies they rely on are loaded beforehand.

packages/nuxt/src/core/runtime/nitro/utils/renderer/islands.ts (2)

1-5: Ensure appRootTag is guaranteed to exist.
If #internal/nuxt.config.mjs doesn't provide a valid appRootTag, ROOT_NODE_REGEX might fail or produce misleading matches.


20-30: Guard against empty slot data.
If ssrContext.islandContext.slots is empty or invalid, ensure the fallback logic doesn’t degrade performance or produce an unhandled error.

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c65b56 and 9eccac7.

📒 Files selected for processing (2)
  • packages/nuxt/src/core/nuxt.ts (2 hunks)
  • test/bundle.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/bundle.test.ts
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: code
🔇 Additional comments (1)
packages/nuxt/src/core/nuxt.ts (1)

9-9: Import statement addition for server handlers

The updated import statement now includes addServerHandler and addServerTemplate, which are required for the new island renderer functionality being implemented.

Comment on lines +628 to +642
// sync conditions with /packages/nuxt/src/core/templates.ts#L539
addServerTemplate({
filename: '#internal/nuxt/island-renderer.mjs',
getContents () {
if (nuxt.options.dev || nuxt.options.experimental.componentIslands !== 'auto' || nuxt.apps.default?.pages?.some(p => p.mode === 'server') || nuxt.apps.default?.components?.some(c => c.mode === 'server' && !nuxt.apps.default?.components.some(other => other.pascalName === c.pascalName && other.mode === 'client'))) {
return `export { default } from '${resolve(distDir, 'core/runtime/nitro/handlers/island')}'`
}
return `export default defineEventHandler(() => {})`
},
})
addServerHandler({
route: '/__nuxt_island/**',
handler: '#internal/nuxt/island-renderer.mjs',
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Island renderer implementation looks good, but timing concern persists

The code effectively separates the island rendering logic into its own server endpoint, which aligns with the PR objective of enhancing readability by moving this functionality out of the main render handler.

However, there's still a potential issue with accessing nuxt.apps.default before it's fully initialized, as noted in a previous review. While the optional chaining (?.) prevents errors, it might result in incorrect behavior if evaluation happens too early.

Consider moving this server handler registration after a point where nuxt.apps.default is guaranteed to be initialized, perhaps after the initNitro call on line 759 or by using a hook to defer this registration.


🌐 Web query:

When is nuxt.apps.default initialized in the Nuxt lifecycle?

💡 Result:

In Nuxt 3, the nuxtApp instance (commonly referred to as the runtime context) is initialized during the app creation phase of the lifecycle. This occurs in two key phases:

Server-Side Initialization

  1. After Nitro server setup but before server middleware/plugins
    The nuxtApp is initialized during Step 3 (Initialize Nuxt and Execute Nuxt App Plugins) of the server lifecycle[8]. This happens after Nitro server initialization but before server middleware and plugin execution.

Client-Side Initialization

  1. Early in client hydration
    On the client, nuxtApp is initialized during the hydration process before executing client plugins and middleware[8].

Key Lifecycle Hook

The app:created hook signals the availability of nuxtApp:

nuxtApp.hook('app:created', () => {
  // nuxtApp is now accessible
})

This hook executes:

  • On the server: before server middleware and plugins[9]
  • On the client: before client middleware and Vue component hydration[8]

Typical Access Points

nuxtApp becomes available in:

  1. Plugins via defineNuxtPlugin[1][3]
  2. Middleware through the runtime context
  3. Composables like useNuxtApp()[4]

The initialization timing ensures nuxtApp exists before essential operations like store initialization (Pinia) and data fetching (useAsyncData/useFetch)[3][8].

Citations:


Potential Timing Issue with Island Renderer Registration

The separation of the island rendering logic into its own server endpoint is a clear improvement. However, there remains a timing concern regarding the access of nuxt.apps.default. Although the use of optional chaining prevents runtime errors, if this evaluation occurs before nuxt.apps.default is fully initialised (which, as per Nuxt’s lifecycle, happens during the app creation phase—typically in the app:created hook or after Nitro initialisation), it may lead to unintended behaviour.

  • Actionable Recommendation:
    Consider deferring the registration of the server handler until after nuxt.apps.default is guaranteed to be initialised. This could be achieved by moving the registration to a later point—such as after the initNitro call on line 759—or by using an appropriate lifecycle hook (e.g. app:created).

@danielroe danielroe merged commit 1f6e6d3 into main Apr 4, 2025
46 checks passed
@danielroe danielroe deleted the refactor/_nuxt_island branch April 4, 2025 14:31
@github-actions github-actions bot mentioned this pull request Apr 4, 2025
@github-actions github-actions bot mentioned this pull request Apr 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants