fix app layouts (vercel/turbo#190)
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:
parent
722930a006
commit
8fa162d5c5
9 changed files with 65 additions and 53 deletions
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ".";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"),
|
||||
],
|
||||
|
|
Loading…
Reference in a new issue