Seems like app layout was left behind while shipping features to normal
SSR rendering

* fixes fallback error pages (update to error fallback changes)
* fixes process communication (update to api route changes)
* avoid busy looping
* update to next.js updates
* fix resolving cycle
* fix HMR of client components
* add some hard coded external packages
This commit is contained in:
Tobias Koppers 2022-10-22 19:47:59 +02:00 committed by GitHub
parent 722930a006
commit 8fa162d5c5
9 changed files with 65 additions and 53 deletions

View file

@ -9,11 +9,10 @@
"build:compiled": "node build.mjs"
},
"dependencies": {
"@next/react-refresh-utils": "^12.2.5",
"@vercel/turbopack-runtime": "latest",
"anser": "2.1.1",
"css.escape": "1.5.1",
"next": "12.3.2-canary.32",
"next": "12.3.2-canary.33",
"platform": "1.3.6",
"react-dom": "^18.2.0",
"react": "^18.2.0",

View file

@ -6,8 +6,6 @@ declare global {
const BOOTSTRAP: string[];
}
const END_OF_OPERATION = process.argv[2];
import type { IncomingMessage, ServerResponse } from "node:http";
import type { FlightManifest } from "next/dist/build/webpack/plugins/flight-manifest-plugin";
import type { RenderData } from "types/turbopack";
@ -27,9 +25,18 @@ globalThis.__next_chunk_load__ = () => Promise.resolve();
process.env.__NEXT_NEW_LINK_BEHAVIOR = "true";
process.stdout.write("READY\n");
const [MARKER, _OPERATION_STEP, OPERATION_SUCCESS, _OPERATION_ERROR] =
process.argv.slice(2, 6).map((arg) => Buffer.from(arg, "utf8"));
const NEW_LINE = "\n".charCodeAt(0);
const OPERATION_SUCCESS_MARKER = Buffer.concat([
OPERATION_SUCCESS,
Buffer.from(" ", "utf8"),
MARKER,
]);
process.stdout.write("READY\n");
const buffer: Buffer[] = [];
process.stdin.on("data", async (data) => {
let idx = data.indexOf(NEW_LINE);
@ -53,7 +60,7 @@ process.stdin.on("data", async (data) => {
} catch (e: any) {
console.log(`ERROR=${JSON.stringify(e.stack)}`);
}
console.log(END_OF_OPERATION);
console.log(OPERATION_SUCCESS_MARKER.toString("utf8"));
data = data.slice(idx + 1);
idx = data.indexOf(NEW_LINE);
}

View file

@ -1,10 +1,16 @@
import ReactDOMClient from "react-dom/client";
import React, { experimental_use as use } from "react";
import type { ReactElement } from "react";
import { createFromReadableStream } from "next/dist/compiled/react-server-dom-webpack";
import { createFromReadableStream } from "next/dist/compiled/react-server-dom-webpack/client";
import { HeadManagerContext } from "next/dist/shared/lib/head-manager-context";
import { initializeHMR } from "@vercel/turbopack-next/dev/client";
initializeHMR({
assetPrefix: "",
});
globalThis.__next_require__ = (data) => {
const [, client_id] = JSON.parse(data);
return __turbopack_require__(client_id);

View file

@ -5,6 +5,6 @@ export { staticGenerationAsyncStorage } from "next/dist/esm/client/components/st
export { requestAsyncStorage } from "next/dist/esm/client/components/request-async-storage.js";
import * as serverHooks from "next/dist/esm/client/components/hooks-server-context.js";
export { serverHooks };
export { renderToReadableStream } from "next/dist/compiled/react-server-dom-webpack/writer.browser.server";
export { renderToReadableStream } from "next/dist/compiled/react-server-dom-webpack/server.browser";
export { default } from ".";

View file

@ -1,4 +1,4 @@
declare module "next/dist/esm/client/components/static-generation-async-storage.js";
declare module "next/dist/esm/client/components/request-async-storage.js";
declare module "next/dist/esm/client/components/hooks-server-context.js";
declare module "next/dist/compiled/react-server-dom-webpack/writer.browser.server";
declare module "next/dist/compiled/react-server-dom-webpack/server.browser";

View file

@ -108,14 +108,14 @@ async fn next_client_transition(
#[turbo_tasks::function]
fn next_ssr_client_module_transition(
project_path: FileSystemPathVc,
project_root: FileSystemPathVc,
app_dir: FileSystemPathVc,
process_env: ProcessEnvVc,
) -> TransitionVc {
let ty = Value::new(ServerContextType::AppSSR { app_dir });
NextSSRClientModuleTransition {
ssr_module_options_context: get_server_module_options_context(ty),
ssr_resolve_options_context: get_server_resolve_options_context(project_path, ty),
ssr_resolve_options_context: get_server_resolve_options_context(project_root, ty),
ssr_environment: get_server_environment(ty, process_env),
}
.cell()
@ -148,13 +148,13 @@ fn next_layout_entry_transition(
/// Next.js app folder.
#[turbo_tasks::function]
pub async fn create_app_source(
project_path: FileSystemPathVc,
project_root: FileSystemPathVc,
output_path: FileSystemPathVc,
server_root: FileSystemPathVc,
env: ProcessEnvVc,
browserslist_query: &str,
) -> Result<ContentSourceVc> {
let project_root = wrap_with_next_js_fs(project_path);
let project_root = wrap_with_next_js_fs(project_root);
let app = project_root.join("app");
let src_app = project_root.join("src/app");
@ -202,7 +202,7 @@ pub async fn create_app_source(
let server_runtime_entries =
vec![ProcessEnvAssetVc::new(project_root, env).as_ecmascript_chunk_placeable()];
let fallback_page = get_fallback_page(project_path, server_root, browserslist_query);
let fallback_page = get_fallback_page(project_root, server_root, browserslist_query);
Ok(create_app_source_for_directory(
context,

View file

@ -3,7 +3,7 @@ use turbo_tasks_fs::FileSystemPathVc;
use turbopack_core::resolve::options::{ImportMap, ImportMapVc, ImportMapping, ImportMappingVc};
use crate::{
embed_js::{attached_next_js_package_path, next_js_fs, VIRTUAL_PACKAGE_NAME},
embed_js::{attached_next_js_package_path, VIRTUAL_PACKAGE_NAME},
next_client::context::ContextType,
next_server::ServerContextType,
};
@ -39,21 +39,14 @@ pub fn get_next_client_import_map(
);
}
ContextType::App { app_dir } => {
import_map.insert_exact_alias(
"react",
request_to_import_mapping(app_dir, "next/dist/compiled/react"),
);
import_map.insert_wildcard_alias(
"react/",
request_to_import_mapping(app_dir, "next/dist/compiled/react/*"),
);
import_map.insert_exact_alias(
"react-dom",
request_to_import_mapping(app_dir, "next/dist/compiled/react-dom"),
);
import_map.insert_exact_alias("react", request_to_import_mapping(app_dir, "react"));
import_map
.insert_wildcard_alias("react/", request_to_import_mapping(app_dir, "react/*"));
import_map
.insert_exact_alias("react-dom", request_to_import_mapping(app_dir, "react-dom"));
import_map.insert_wildcard_alias(
"react-dom/",
request_to_import_mapping(app_dir, "next/dist/compiled/react-dom/*"),
request_to_import_mapping(app_dir, "react-dom/*"),
);
}
ContextType::Other => {}
@ -89,6 +82,10 @@ pub fn get_next_client_fallback_import_map(ty: Value<ContextType>) -> ImportMapV
import_map.cell()
}
// TODO this should be a user configurable option
/// Temporary hard coded externals list
static HARD_CODED_EXTERNALS: &[&str] = &["prisma", "@prisma/client", "@mux/blurhash"];
/// Computes the Next-specific server-side import map.
#[turbo_tasks::function]
pub fn get_next_server_import_map(
@ -119,37 +116,33 @@ pub fn get_next_server_import_map(
],
);
import_map.insert_wildcard_alias(
format!("{VIRTUAL_PACKAGE_NAME}/"),
ImportMapping::PrimaryAlternative("./*".to_string(), Some(next_js_fs().root()))
.cell(),
);
import_map.insert_exact_alias("next", ImportMapping::External(None).into());
import_map.insert_wildcard_alias("next/", ImportMapping::External(None).into());
import_map.insert_exact_alias("react", ImportMapping::External(None).into());
import_map.insert_wildcard_alias("react/", ImportMapping::External(None).into());
import_map.insert_exact_alias("react-dom", ImportMapping::External(None).into());
import_map.insert_wildcard_alias("react-dom/", ImportMapping::External(None).into());
}
ServerContextType::AppSSR { app_dir } | ServerContextType::AppRSC { app_dir } => {
import_map.insert_exact_alias(
"react",
request_to_import_mapping(app_dir, "next/dist/compiled/react"),
);
import_map.insert_wildcard_alias(
"react/",
request_to_import_mapping(app_dir, "next/dist/compiled/react/*"),
);
import_map.insert_exact_alias("react", request_to_import_mapping(app_dir, "react"));
import_map
.insert_wildcard_alias("react/", request_to_import_mapping(app_dir, "react/*"));
import_map.insert_exact_alias(
"react-dom",
request_to_import_mapping(
app_dir,
"next/dist/compiled/react-dom/server-rendering-stub.js",
),
request_to_import_mapping(app_dir, "react-dom/server-rendering-stub.js"),
);
import_map.insert_wildcard_alias(
"react-dom/",
request_to_import_mapping(app_dir, "next/dist/compiled/react-dom/*"),
request_to_import_mapping(app_dir, "react-dom/*"),
);
for &external in HARD_CODED_EXTERNALS {
import_map.insert_exact_alias(external, ImportMapping::External(None).into());
import_map.insert_wildcard_alias(
format!("{external}/"),
ImportMapping::External(None).into(),
);
}
}
}

View file

@ -1,6 +1,6 @@
use std::{
collections::HashMap,
io::{BufRead, BufReader, Write},
io::{BufRead, BufReader, ErrorKind, Write},
path::{Path, PathBuf},
process::{Child, ChildStdin, ChildStdout, Command, Stdio},
sync::{Arc, Mutex},
@ -280,14 +280,23 @@ impl NodeJsOperation {
let child = self.expect_child_mut();
let mut total_read = 0;
loop {
total_read += child.read_until(b'\n', buf)?;
let read = child.read_until(b'\n', buf)?;
total_read += read;
match child.marker.read_event(&buf) {
Some((read, event)) => {
buf.truncate(buf.len() - read);
break Ok((total_read - read, event));
}
None => {}
None => {
if read == 0 {
// we need to stop reading in this case otherwise this loop infinitely
return Err(std::io::Error::new(
ErrorKind::UnexpectedEof,
"process closed unexpectedly while waiting for an operation result",
));
}
}
}
}
}

View file

@ -47,9 +47,7 @@ impl Bundler for Turbopack {
npm::install(
install_dir,
&[
NpmPackage::new("react-refresh", "^0.12.0"),
NpmPackage::new("next", "^12.3.1"),
NpmPackage::new("@next/react-refresh-utils", "^12.3.1"),
NpmPackage::new("next", "12.3.2-canary.33"),
// Dependency on this is inserted by swc's preset_env
NpmPackage::new("@swc/helpers", "^0.4.11"),
],