Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

turbopack: defer dev code evaluation until after page render IPC connects #47888

Merged
merged 9 commits into from
Apr 4, 2023
18 changes: 10 additions & 8 deletions packages/next-swc/crates/next-core/js/src/entry/server-data.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
// IPC need to be the first import to allow it to catch errors happening during
// the other imports
import startHandler from "@vercel/turbopack-next/internal/page-server-handler";
import startHandler from '@vercel/turbopack-next/internal/page-server-handler'

// eslint-disable-next-line
import Document from "next/document";
import App from "next/app";

import * as otherExports from "INNER";
import Document from 'next/document'
import App from 'next/app'

startHandler({
isDataReq: true,
App,
Document,
Component: () => {},
otherExports,
});
mod: () => {
return import('INNER').then((namespace) => ({
Component: () => null,
namespace,
}))
},
})
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
// IPC need to be the first import to allow it to catch errors happening during
// the other imports
import startHandler from "@vercel/turbopack-next/internal/page-server-handler";
import startHandler from '@vercel/turbopack-next/internal/page-server-handler'

import App from "@vercel/turbopack-next/pages/_app";
import Document from "@vercel/turbopack-next/pages/_document";
import App from '@vercel/turbopack-next/pages/_app'
import Document from '@vercel/turbopack-next/pages/_document'
Comment on lines +5 to +6
Copy link
Member

Choose a reason for hiding this comment

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

These might also contain user code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you explain? Do they invoke user code as part of module evaluation? These are wrappers around next's code, right?


import Component, * as otherExports from "INNER";

import chunkGroup from "INNER_CLIENT_CHUNK_GROUP";
import chunkGroup from 'INNER_CLIENT_CHUNK_GROUP'

startHandler({
isDataReq: false,
App,
Document,
Component,
otherExports,
mod: () => {
return import('INNER').then((namespace) => ({
Component: namespace.default as any,
namespace,
}))
},
chunkGroup,
});
})
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { headersFromEntries } from "@vercel/turbopack-next/internal/headers";
import type { Ipc } from "@vercel/turbopack-next/ipc/index";
import type { RenderData } from "types/turbopack";
import type { ChunkGroup } from "types/next";
import type { NextComponentType } from "next/types";
import { parse } from "node:querystring";

const ipc = IPC as Ipc<IpcIncomingMessage, IpcOutgoingMessage>;
Expand All @@ -40,19 +41,22 @@ type IpcOutgoingMessage =
const MIME_APPLICATION_JAVASCRIPT = "application/javascript";
const MIME_TEXT_HTML_UTF8 = "text/html; charset=utf-8";

type ModuleImport = Promise<{
Component: NextComponentType,
namespace: Record<string, any>;
}>

export default function startHandler({
isDataReq,
App,
Document,
Component,
otherExports,
mod,
chunkGroup,
}: {
isDataReq: boolean;
App?: any;
Document?: any;
Component?: any;
otherExports: any;
mod: () => ModuleImport,
chunkGroup?: ChunkGroup;
}) {
(async () => {
Expand All @@ -71,7 +75,9 @@ export default function startHandler({
}
}

const res = await runOperation(renderData);
const { Component, namespace } = await mod();

const res = await runOperation(renderData, Component, namespace);

ipc.send(res);
}
Expand All @@ -80,16 +86,18 @@ export default function startHandler({
});

async function runOperation(
renderData: RenderData
renderData: RenderData,
Component: NextComponentType,
namespace: Record<string, any>,
): Promise<IpcOutgoingMessage> {
if ("getStaticPaths" in otherExports) {
if ("getStaticPaths" in namespace) {
const {
paths: prerenderRoutes,
fallback: prerenderFallback,
encodedPaths: _encodedPrerenderRoutes,
} = await buildStaticPaths({
page: renderData.path,
getStaticPaths: otherExports.getStaticPaths,
getStaticPaths: namespace.getStaticPaths,
// TODO(alexkirsz) Provide the correct next.config.js path.
configFileName: "next.config.js",
});
Expand Down Expand Up @@ -140,7 +148,7 @@ export default function startHandler({
const comp =
typeof Component === "undefined" ||
(typeof Component === "object" && Object.keys(Component).length === 0)
? () => {}
? () => null
: Component;

const renderOpts: RenderOpts = {
Expand All @@ -153,7 +161,7 @@ export default function startHandler({
reactLoadableManifest: createReactLoadableManifestProxy(),
ComponentMod: {
default: comp,
...otherExports,
...namespace,
},
pathname: renderData.path,
buildId: "development",
Expand Down Expand Up @@ -195,14 +203,14 @@ export default function startHandler({
},
};

if ("getStaticPaths" in otherExports) {
renderOpts.getStaticPaths = otherExports.getStaticPaths;
if ("getStaticPaths" in namespace) {
renderOpts.getStaticPaths = namespace.getStaticPaths;
}
if ("getStaticProps" in otherExports) {
renderOpts.getStaticProps = otherExports.getStaticProps;
if ("getStaticProps" in namespace) {
renderOpts.getStaticProps = namespace.getStaticProps;
}
if ("getServerSideProps" in otherExports) {
renderOpts.getServerSideProps = otherExports.getServerSideProps;
if ("getServerSideProps" in namespace) {
renderOpts.getServerSideProps = namespace.getServerSideProps;
}

const req: IncomingMessage = {
Expand Down