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 6, 2023
1 parent 084f364 commit abc0a2c
Show file tree
Hide file tree
Showing 19 changed files with 148 additions and 67 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 @@ -207,6 +207,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 @@ -6,7 +6,6 @@ import '../shims'
import { appBootstrap } from 'next/dist/client/app-bootstrap'

appBootstrap(() => {
require('./app-turbopack')
const { hydrate } = require('./app-index')
hydrate()
})

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ 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'

installRequireAndChunkLoad()

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

startOperationStreamHandler(async (renderData: RenderData, respond) => {
Expand Down Expand Up @@ -88,10 +86,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
4 changes: 3 additions & 1 deletion packages/next-swc/crates/next-core/src/app_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,8 @@ impl AppRenderer {
const { GlobalError } = GlobalErrorMod;
\"TURBOPACK { chunking-type: isolatedParallel; transition: next-edge-server-component }\";
import base from \"next/dist/server/app-render/entry-base\"\n
\"TURBOPACK { chunking-type: isolatedParallel; transition: next-ssr }\";
import baseSsr from \"next/dist/server/app-render/entry-base-ssr\"\n
"});

for import in loader_tree_module.imports {
Expand All @@ -990,7 +992,7 @@ impl AppRenderer {
result,
// Need this hack because "export *" from CommonJS will trigger a warning
// otherwise
"__turbopack_export_value__({{ tree, GlobalError, pathname, ...base }});\n"
"__turbopack_export_value__({{ tree, GlobalError, pathname, ...base, ...baseSsr }});\n"
)?;

let file = File::from(result.build());
Expand Down
67 changes: 56 additions & 11 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/dynamic",
Expand Down Expand Up @@ -228,7 +239,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_exact_alias("react-server-dom-webpack/", external);
import_map.insert_exact_alias(
"react-server-dom-webpack/",
ImportMapping::External(Some("react-server-dom-turbopack".into())).cell(),
);
}
ServerContextType::AppSSR { .. }
| ServerContextType::AppRSC { .. }
Expand Down Expand Up @@ -446,7 +460,10 @@ async fn insert_next_server_special_aliases(
);
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/*",
),
);
}
// NOTE(alexkirsz) This logic maps loosely to
Expand All @@ -469,6 +486,14 @@ async fn insert_next_server_special_aliases(
// @opentelemetry/api
request_to_import_mapping(app_dir, "next/dist/compiled/@opentelemetry/api"),
);
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/react.shared-subset"),
Expand All @@ -485,7 +510,7 @@ async fn insert_next_server_special_aliases(
("react-dom/", "next/dist/compiled/react-dom/*"),
(
"react-server-dom-webpack/",
"next/dist/compiled/react-server-dom-webpack/*",
"next/dist/compiled/react-server-dom-turbopack/*",
),
] {
import_map.insert_wildcard_alias(
Expand All @@ -496,12 +521,21 @@ async fn insert_next_server_special_aliases(
}
// ## SSR
//
// * always uses externals, to ensure we're using the same React instance as the Next.js
// runtime
// * uses externals (except for react-server-dom-turbopack), to ensure we're using the same
// React instance as the Next.js runtime
// * maps react-dom -> react-dom/server-rendering-stub
// * passes through react and (react|react-dom|react-server-dom-webpack)/(.*) to
// * maps react-server-dom-webpack -> react-server-dom-turbopack
// * passes through react and (react|react-dom|react-server-dom-turbopack)/(.*) to
// next/dist/compiled/react and next/dist/compiled/$1/$2 resp.
(NextMode::Build | NextMode::Development, ServerContextType::AppSSR { 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",
external_if_node(app_dir, "next/dist/compiled/react"),
Expand All @@ -514,13 +548,24 @@ async fn insert_next_server_special_aliases(
),
);

// The react-server-dom-webpack mappings are intended to be bundled in every
// environment. These imports contain references to magic globals
// for bundlers that need to be processed by that bundler to work effectively
import_map.insert_exact_alias(
"react-server-dom-webpack",
request_to_import_mapping(app_dir, "next/dist/compiled/react-server-dom-turbopack"),
);
import_map.insert_wildcard_alias(
"react-server-dom-webpack/",
request_to_import_mapping(
app_dir,
"next/dist/compiled/react-server-dom-turbopack/*",
),
);

for (wildcard_alias, request) in [
("react/", "next/dist/compiled/react/*"),
("react-dom/", "next/dist/compiled/react-dom/*"),
(
"react-server-dom-webpack/",
"next/dist/compiled/react-server-dom-webpack/*",
),
] {
let import_mapping = external_if_node(app_dir, request);
import_map.insert_wildcard_alias(wildcard_alias, import_mapping);
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
6 changes: 6 additions & 0 deletions packages/next/src/server/lib/router-utils/setup-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,16 @@ async function startWatcher(opts: SetupOpts) {
require.resolve(
'next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js'
),
require.resolve(
'next/dist/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js'
),
// And this redirecting module as well
require.resolve(
'next/dist/compiled/react-server-dom-webpack/client.edge.js'
),
require.resolve(
'next/dist/compiled/react-server-dom-turbopack/client.edge.js'
),
])
)

Expand Down
31 changes: 31 additions & 0 deletions packages/next/src/server/require-hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ export const baseOverrides = {
'next/dist/compiled/react-server-dom-webpack/server.edge',
'react-server-dom-webpack/server.node':
'next/dist/compiled/react-server-dom-webpack/server.node',
'react-server-dom-turbopack/client':
'next/dist/compiled/react-server-dom-turbopack/client',
'react-server-dom-turbopack/client.edge':
'next/dist/compiled/react-server-dom-turbopack/client.edge',
'react-server-dom-turbopack/server.edge':
'next/dist/compiled/react-server-dom-turbopack/server.edge',
'react-server-dom-turbopack/server.node':
'next/dist/compiled/react-server-dom-turbopack/server.node',
}

export const experimentalOverrides = {
Expand All @@ -70,6 +78,14 @@ export const experimentalOverrides = {
'next/dist/compiled/react-server-dom-webpack-experimental/server.edge',
'react-server-dom-webpack/server.node':
'next/dist/compiled/react-server-dom-webpack-experimental/server.node',
'react-server-dom-turbopack/client':
'next/dist/compiled/react-server-dom-turbopack-experimental/client',
'react-server-dom-turbopack/client.edge':
'next/dist/compiled/react-server-dom-turbopack-experimental/client.edge',
'react-server-dom-turbopack/server.edge':
'next/dist/compiled/react-server-dom-turbopack-experimental/server.edge',
'react-server-dom-turbopack/server.node':
'next/dist/compiled/react-server-dom-turbopack-experimental/server.node',
}

export function addHookAliases(aliases: [string, string][] = []) {
Expand All @@ -95,6 +111,21 @@ function overrideReact() {
addHookAliases(toResolveMap(baseOverrides))
}
}

if (process.env.TURBOPACK || process.env.EXPERIMENTAL_TURBOPACK) {
addHookAliases(
toResolveMap({
'react-server-dom-webpack/client':
'next/dist/compiled/react-server-dom-turbopack/client',
'react-server-dom-webpack/client.edge':
'next/dist/compiled/react-server-dom-turbopack/client.edge',
'react-server-dom-webpack/server.edge':
'next/dist/compiled/react-server-dom-turbopack/server.edge',
'react-server-dom-webpack/server.node':
'next/dist/compiled/react-server-dom-turbopack/server.node',
})
)
}
}
overrideReact()

Expand Down
Loading

0 comments on commit abc0a2c

Please sign in to comment.