Skip to content

Commit

Permalink
Implements module preinitialization for SSR when using turbopack
Browse files Browse the repository at this point in the history
  • Loading branch information
gnoff committed Sep 26, 2023
1 parent 3391b48 commit e92e687
Show file tree
Hide file tree
Showing 21 changed files with 192 additions and 68 deletions.
1 change: 1 addition & 0 deletions packages/next-swc/crates/next-api/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ impl AppProject {
"next-dynamic".to_string(),
Vc::upcast(NextDynamicTransition::new(self.client_transition())),
),
("next-ssr".to_string(), Vc::upcast(self.ssr_transition())),
]
.into_iter()
.collect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { PassThrough } from 'node:stream'
import entry from 'APP_ENTRY'
import BOOTSTRAP from 'APP_BOOTSTRAP'
import { createServerResponse } from '../internal/http'
import { createManifests, installRequireAndChunkLoad } from './app/manifest'
import { createManifests } from './app/manifest'
import { join } from 'node:path'
import { nodeFs } from 'next/dist/server/lib/node-fs-methods'
import { IncrementalCache } from 'next/dist/server/lib/incremental-cache'
Expand All @@ -27,8 +27,6 @@ const {
renderToHTMLOrFlight,
} = require('next/dist/compiled/next-server/app-page.runtime.dev')

installRequireAndChunkLoad()

const MIME_TEXT_HTML_UTF8 = 'text/html; charset=utf-8'

startOperationStreamHandler(async (renderData: RenderData, respond) => {
Expand Down Expand Up @@ -92,10 +90,6 @@ async function runOperation(renderData: RenderData) {
},
ComponentMod: {
...entry,
__next_app__: {
require: __next_require__,
loadChunk: __next_chunk_load__,
},
pages: ['page.js'],
},
incrementalCache: new IncrementalCache({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ import { renderToHTMLOrFlight } from 'next/dist/server/app-render/app-render'
;('TURBOPACK { chunking-type: isolatedParallel }')
import entry from 'APP_ENTRY'
import BOOTSTRAP from 'APP_BOOTSTRAP'
import { createManifests, installRequireAndChunkLoad } from './manifest'
import { createManifests } from './manifest'
import type { NextRequest, NextFetchEvent } from 'next/server'
import type { RenderOpts } from 'next/dist/server/app-render/types'
import type { ParsedUrlQuery } from 'querystring'

installRequireAndChunkLoad()

// avoid limiting stack traces to 10 lines
Error.stackTraceLimit = 100

Expand Down Expand Up @@ -43,10 +41,6 @@ async function render(request: NextRequest, event: NextFetchEvent) {
},
ComponentMod: {
...entry,
__next_app__: {
require: __next_require__,
loadChunk: __next_chunk_load__,
},
pages: ['page.js'],
},
clientReferenceManifest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import ReactDOMClient from 'react-dom/client'
import React, { use } from 'react'
import type { ReactElement } from 'react'
import { version } from 'next/package.json'
import { createFromReadableStream } from 'next/dist/compiled/react-server-dom-webpack/client'
import { createFromReadableStream } from 'next/dist/compiled/react-server-dom-turbopack/client'
import { callServer } from 'next/dist/client/app-call-server'
import { linkGc } from 'next/dist/client/app-link-gc'

Expand All @@ -19,12 +19,6 @@ window.next = {
appDir: true,
}

globalThis.__next_require__ = (data) => {
const [client_id] = JSON.parse(data)
return __turbopack_require__(client_id)
}
globalThis.__next_chunk_load__ = __turbopack_load__

const appElement = document

const getCacheKey = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,3 @@ export function createManifests() {

return { clientReferenceManifest }
}

export function installRequireAndChunkLoad() {
globalThis.__next_require__ = (data) => {
const [, , ssr_id] = JSON.parse(data)
return __turbopack_require__(ssr_id)
}
globalThis.__next_chunk_load__ = () => Promise.resolve()
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
declare module 'next/dist/compiled/react-server-dom-webpack/client'
declare module 'next/dist/compiled/react-server-dom-turbopack/client'
2 changes: 0 additions & 2 deletions packages/next-swc/crates/next-core/js/types/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ declare global {
var __webpack_public_path__: string | undefined
var __DEV_MIDDLEWARE_MATCHERS: any[]

var __next_require__: (id: string) => any
var __next_chunk_load__: (id: string) => Promise
var __next_f: (
| [isBootStrap: 0]
| [isNotBootstrap: 1, responsePartial: string]
Expand Down
50 changes: 40 additions & 10 deletions packages/next-swc/crates/next-core/src/next_import_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ pub async fn get_next_client_import_map(
);
}
ClientContextType::App { app_dir } => {
import_map.insert_exact_alias(
"server-only",
request_to_import_mapping(app_dir, "next/dist/compiled/server-only"),
);
import_map.insert_exact_alias(
"client-only",
request_to_import_mapping(app_dir, "next/dist/compiled/client-only"),
);
import_map.insert_exact_alias(
"react",
request_to_import_mapping(app_dir, "next/dist/compiled/react"),
Expand All @@ -107,7 +115,10 @@ pub async fn get_next_client_import_map(
);
import_map.insert_wildcard_alias(
"react-server-dom-webpack/",
request_to_import_mapping(app_dir, "next/dist/compiled/react-server-dom-webpack/*"),
request_to_import_mapping(
app_dir,
"next/dist/compiled/react-server-dom-turbopack/*",
),
);
import_map.insert_exact_alias(
"next/head",
Expand Down Expand Up @@ -238,7 +249,10 @@ pub async fn get_next_server_import_map(
import_map.insert_wildcard_alias("react-dom/", external);
import_map.insert_exact_alias("styled-jsx", external);
import_map.insert_wildcard_alias("styled-jsx/", external);
import_map.insert_wildcard_alias("react-server-dom-webpack/", external);
import_map.insert_exact_alias(
"react-server-dom-webpack/",
ImportMapping::External(Some("react-server-dom-turbopack".into())).cell(),
);
// TODO: we should not bundle next/dist/build/utils in the pages renderer at all
import_map.insert_wildcard_alias("next/dist/build/utils", external);
}
Expand Down Expand Up @@ -498,11 +512,13 @@ async fn insert_next_server_special_aliases(
app_dir,
match runtime {
NextRuntime::Edge => {
"next/dist/compiled/react-server-dom-webpack/client.edge"
"next/dist/compiled/react-server-dom-turbopack/client.edge"
}
// When we access the runtime we still use the webpack name. The runtime
// itself will substitute in the turbopack variant
NextRuntime::NodeJs => {
"next/dist/server/future/route-modules/app-page/vendored/ssr/\
react-server-dom-webpack-client-edge"
react-server-dom-turbopack-client-edge"
}
},
),
Expand All @@ -516,11 +532,13 @@ async fn insert_next_server_special_aliases(
app_dir,
match runtime {
NextRuntime::Edge => {
"next/dist/compiled/react-server-dom-webpack/client.edge"
"next/dist/compiled/react-server-dom-turbopack/client.edge"
}
// When we access the runtime we still use the webpack name. The runtime
// itself will substitute in the turbopack variant
NextRuntime::NodeJs => {
"next/dist/server/future/route-modules/app-page/vendored/ssr/\
react-server-dom-webpack-client-edge"
react-server-dom-turbopack-client-edge"
}
},
),
Expand Down Expand Up @@ -591,6 +609,14 @@ async fn insert_next_server_special_aliases(
},
),
);
import_map.insert_exact_alias(
"server-only",
request_to_import_mapping(app_dir, "next/dist/compiled/server-only"),
);
import_map.insert_exact_alias(
"client-only",
request_to_import_mapping(app_dir, "next/dist/compiled/client-only"),
);
import_map.insert_exact_alias(
"react",
request_to_import_mapping(
Expand Down Expand Up @@ -621,11 +647,13 @@ async fn insert_next_server_special_aliases(
app_dir,
match runtime {
NextRuntime::Edge => {
"next/dist/compiled/react-server-dom-webpack/server.edge"
"next/dist/compiled/react-server-dom-turbopack/server.edge"
}
// When we access the runtime we still use the webpack name. The runtime
// itself will substitute in the turbopack variant
NextRuntime::NodeJs => {
"next/dist/server/future/route-modules/app-page/vendored/rsc/\
react-server-dom-webpack-server-edge"
react-server-dom-turbopack-server-edge"
}
},
),
Expand All @@ -636,11 +664,13 @@ async fn insert_next_server_special_aliases(
app_dir,
match runtime {
NextRuntime::Edge => {
"next/dist/compiled/react-server-dom-webpack/server.node"
"next/dist/compiled/react-server-dom-turbopack/server.node"
}
// When we access the runtime we still use the webpack name. The runtime
// itself will substitute in the turbopack variant
NextRuntime::NodeJs => {
"next/dist/server/future/route-modules/app-page/vendored/rsc/\
react-server-dom-webpack-server-node"
react-server-dom-turbopack-server-node"
}
},
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ impl ClientReferenceManifest {
ssr_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
) -> Result<Vc<Box<dyn OutputAsset>>> {
let mut entry_manifest: ClientReferenceManifest = Default::default();
entry_manifest.module_loading.prefix = "/_next/".to_string();
entry_manifest.module_loading.cross_origin = None;
let client_references_chunks = client_references_chunks.await?;
let client_relative_path = client_relative_path.await?;
let node_root_ref = node_root.await?;
Expand Down
8 changes: 8 additions & 0 deletions packages/next-swc/crates/next-core/src/next_manifests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ pub enum ActionManifestWorkerEntry {
#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ClientReferenceManifest {
pub module_loading: ModuleLoading,
/// Mapping of module path and export name to client module ID and required
/// client chunks.
pub client_modules: ManifestNode,
Expand All @@ -192,6 +193,13 @@ pub struct ClientReferenceManifest {
pub entry_css_files: HashMap<String, Vec<String>>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ModuleLoading {
pub prefix: String,
pub cross_origin: Option<String>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ManifestNode {
Expand Down
13 changes: 0 additions & 13 deletions packages/next/src/client/app-turbopack.ts
Original file line number Diff line number Diff line change
@@ -1,13 +0,0 @@
declare let __turbopack_require__: any

// @ts-expect-error
process.env.__NEXT_NEW_LINK_BEHAVIOR = true

// eslint-disable-next-line no-undef
;(self as any).__next_require__ = __turbopack_require__

// @ts-ignore
// eslint-disable-next-line no-undef
;(self as any).__next_chunk_load__ = __turbopack_load__

export {}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function getFramework(
if (!sourcePackage) return undefined

if (
/^(react|react-dom|react-is|react-refresh|react-server-dom-webpack|scheduler)$/.test(
/^(react|react-dom|react-is|react-refresh|react-server-dom-webpack|react-server-dom-turbopack|scheduler)$/.test(
sourcePackage
)
) {
Expand Down
Empty file.
6 changes: 0 additions & 6 deletions packages/next/src/server/app-render/ssr/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,75 @@ import * as React from 'react'

import * as ReactDOM from 'react-dom/server-rendering-stub'

// eslint-disable-next-line import/no-extraneous-dependencies
import * as ReactServerDOMWebpackServerNode from 'react-server-dom-webpack/server.node'
// eslint-disable-next-line import/no-extraneous-dependencies
import * as ReactServerDOMWebpackServerEdge from 'react-server-dom-webpack/server.edge'
function getAltProxyForBindingsDEV(
type: 'Turbopack' | 'Webpack',
pkg:
| 'react-server-dom-turbopack/server.edge'
| 'react-server-dom-turbopack/server.node'
| 'react-server-dom-webpack/server.edge'
| 'react-server-dom-webpack/server.node'
) {
if (process.env.NODE_ENV === 'development') {
const altType = type === 'Turbopack' ? 'Webpack' : 'Turbopack'
const altPkg = pkg.replace(new RegExp(type, 'gi'), altType.toLowerCase())

return new Proxy(
{},
{
get(_, prop: string) {
throw new Error(
`Expected to use ${type} bindings (${pkg}) for React but the current process is referencing '${prop}' from the ${altType} bindings (${altPkg}). This is likely a bug in our integration of the Next.js server runtime.`
)
},
}
)
}
}

let ReactServerDOMTurbopackServerEdge, ReactServerDOMWebpackServerEdge
let ReactServerDOMTurbopackServerNode, ReactServerDOMWebpackServerNode

if (process.env.TURBOPACK) {
// eslint-disable-next-line import/no-extraneous-dependencies
ReactServerDOMTurbopackServerEdge = require('react-server-dom-turbopack/server.edge')
if (process.env.NODE_ENV === 'development') {
ReactServerDOMWebpackServerEdge = getAltProxyForBindingsDEV(
'Turbopack',
'react-server-dom-turbopack/server.edge'
)
}
// eslint-disable-next-line import/no-extraneous-dependencies
ReactServerDOMTurbopackServerNode = require('react-server-dom-turbopack/server.node')
if (process.env.NODE_ENV === 'development') {
ReactServerDOMWebpackServerNode = getAltProxyForBindingsDEV(
'Turbopack',
'react-server-dom-turbopack/server.node'
)
}
} else {
// eslint-disable-next-line import/no-extraneous-dependencies
ReactServerDOMWebpackServerEdge = require('react-server-dom-webpack/server.edge')
if (process.env.NODE_ENV === 'development') {
ReactServerDOMTurbopackServerEdge = getAltProxyForBindingsDEV(
'Webpack',
'react-server-dom-webpack/server.edge'
)
}
// eslint-disable-next-line import/no-extraneous-dependencies
ReactServerDOMWebpackServerNode = require('react-server-dom-webpack/server.node')
if (process.env.NODE_ENV === 'development') {
ReactServerDOMTurbopackServerNode = getAltProxyForBindingsDEV(
'Webpack',
'react-server-dom-webpack/server.node'
)
}
}

export {
React,
ReactDOM,
ReactServerDOMWebpackServerNode,
ReactServerDOMWebpackServerEdge,
ReactServerDOMTurbopackServerEdge,
ReactServerDOMWebpackServerNode,
ReactServerDOMTurbopackServerNode,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = require('../../module.compiled').vendored[
'react-rsc'
].ReactServerDOMTurbopackServerEdge
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = require('../../module.compiled').vendored[
'react-rsc'
].ReactServerDOMTurbopackServerNode
Loading

0 comments on commit e92e687

Please sign in to comment.