Skip to content

Commit 6ce2250

Browse files
feat(remix-dev/vite): add buildDirectory and manifest options (#8575)
1 parent 8e9084c commit 6ce2250

File tree

7 files changed

+243
-126
lines changed

7 files changed

+243
-126
lines changed

integration/vite-adapter-test.ts

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ test.describe(async () => {
2020
return normalizePath(pathname).startsWith(normalizePath(cwd));
2121
}
2222

23-
function pathRelativeToCwd(pathname: string) {
23+
function relativeToCwd(pathname: string) {
2424
return normalizePath(path.relative(cwd, pathname));
2525
}
2626

@@ -57,35 +57,24 @@ test.describe(async () => {
5757
let { status } = viteBuild({ cwd });
5858
expect(status).toBe(0);
5959

60-
expect(
61-
Object.keys(
62-
JSON.parse(
63-
fs.readFileSync(path.join(cwd, "build/server/bundles.json"), "utf8")
64-
).serverBundles
65-
)
66-
).toEqual(["user-options--adapter-options"]);
67-
6860
let buildEndArgs: any = JSON.parse(
6961
fs.readFileSync(path.join(cwd, "BUILD_END_ARGS.json"), "utf8")
7062
);
63+
let { remixConfig } = buildEndArgs;
7164

7265
// Before rewriting to relative paths, assert that paths are absolute within cwd
73-
expect(pathStartsWithCwd(buildEndArgs.serverBuildDirectory)).toBe(true);
74-
expect(pathStartsWithCwd(buildEndArgs.assetsBuildDirectory)).toBe(true);
66+
expect(pathStartsWithCwd(remixConfig.buildDirectory)).toBe(true);
7567

7668
// Rewrite path args to be relative and normalized for snapshot test
77-
buildEndArgs.serverBuildDirectory = pathRelativeToCwd(
78-
buildEndArgs.serverBuildDirectory
79-
);
80-
buildEndArgs.assetsBuildDirectory = pathRelativeToCwd(
81-
buildEndArgs.assetsBuildDirectory
82-
);
69+
remixConfig.buildDirectory = relativeToCwd(remixConfig.buildDirectory);
8370

8471
expect(buildEndArgs).toEqual({
85-
assetsBuildDirectory: "build/client",
86-
serverBuildDirectory: "build/server",
87-
serverBuildFile: "index.js",
88-
unstable_serverBundlesManifest: {
72+
remixConfig: {
73+
buildDirectory: "build",
74+
serverBuildFile: "index.js",
75+
unstable_ssr: true,
76+
},
77+
buildManifest: {
8978
routeIdToServerBundleId: {
9079
"routes/_index": "user-options--adapter-options",
9180
},
@@ -109,7 +98,6 @@ test.describe(async () => {
10998
},
11099
},
111100
},
112-
unstable_ssr: true,
113101
});
114102
});
115103
});
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
import { test, expect } from "@playwright/test";
4+
import getPort from "get-port";
5+
6+
import { createProject, viteBuild, VITE_CONFIG } from "./helpers/vite.js";
7+
8+
function createRoute(path: string) {
9+
return {
10+
[`app/routes/${path}`]: `
11+
export default function Route() {
12+
return <p>Path: ${path}</p>;
13+
}
14+
`,
15+
};
16+
}
17+
18+
const TEST_ROUTES = [
19+
"_index.tsx",
20+
"parent-route.tsx",
21+
"parent-route.child-route.tsx",
22+
];
23+
24+
const files = {
25+
"app/root.tsx": `
26+
import { Links, Meta, Outlet, Scripts, LiveReload } from "@remix-run/react";
27+
28+
export default function Root() {
29+
return (
30+
<html lang="en">
31+
<head>
32+
<Meta />
33+
<Links />
34+
</head>
35+
<body>
36+
<Outlet />
37+
<Scripts />
38+
<LiveReload />
39+
</body>
40+
</html>
41+
);
42+
}
43+
`,
44+
...Object.assign({}, ...TEST_ROUTES.map(createRoute)),
45+
};
46+
47+
test.describe(() => {
48+
let cwd: string;
49+
let devPort: number;
50+
51+
test.beforeAll(async () => {
52+
devPort = await getPort();
53+
cwd = await createProject({
54+
"vite.config.ts": await VITE_CONFIG({
55+
port: devPort,
56+
pluginOptions: "{ manifest: true }",
57+
}),
58+
...files,
59+
});
60+
61+
await viteBuild({ cwd });
62+
});
63+
64+
test("Vite / build manifest", async () => {
65+
expect(
66+
JSON.parse(fs.readFileSync(path.join(cwd, "build/manifest.json"), "utf8"))
67+
).toEqual({
68+
routes: {
69+
root: {
70+
file: "root.tsx",
71+
id: "root",
72+
path: "",
73+
},
74+
"routes/_index": {
75+
file: "routes/_index.tsx",
76+
id: "routes/_index",
77+
index: true,
78+
parentId: "root",
79+
},
80+
"routes/parent-route": {
81+
file: "routes/parent-route.tsx",
82+
id: "routes/parent-route",
83+
parentId: "root",
84+
path: "parent-route",
85+
},
86+
"routes/parent-route.child-route": {
87+
file: "routes/parent-route.child-route.tsx",
88+
id: "routes/parent-route.child-route",
89+
parentId: "routes/parent-route",
90+
path: "child-route",
91+
},
92+
},
93+
});
94+
});
95+
});

integration/vite-server-bundles-test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function createRoute(path: string) {
2828
return {
2929
[`app/routes/${path}`]: `
3030
${ROUTE_FILE_COMMENT}
31-
import { Links, Meta, Outlet, Scripts, LiveReload } from "@remix-run/react";
31+
import { Outlet } from "@remix-run/react";
3232
import { useState, useEffect } from "react";
3333
3434
export default function Route() {
@@ -121,6 +121,7 @@ test.describe(() => {
121121
"vite.config.ts": await VITE_CONFIG({
122122
port: devPort,
123123
pluginOptions: `{
124+
manifest: true,
124125
unstable_serverBundles: async ({ branch }) => {
125126
// Smoke test to ensure we can read the route files via 'route.file'
126127
await Promise.all(branch.map(async (route) => {
@@ -291,7 +292,7 @@ test.describe(() => {
291292
test("Vite / server bundles / build / manifest", async () => {
292293
expect(
293294
JSON.parse(
294-
fs.readFileSync(path.join(cwd, "build/server/bundles.json"), "utf8")
295+
fs.readFileSync(path.join(cwd, "build/manifest.json"), "utf8")
295296
)
296297
).toEqual({
297298
serverBundles: {

packages/remix-dev/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export * as cli from "./cli/index";
77
export type { Manifest as AssetsManifest } from "./manifest";
88
export { getDependenciesToBundle } from "./dependencies";
99
export type {
10-
Unstable_ServerBundlesManifest,
10+
Unstable_BuildManifest,
1111
Unstable_VitePluginAdapter,
1212
} from "./vite";
1313
export { unstable_vitePlugin } from "./vite";

packages/remix-dev/vite/build.ts

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import colors from "picocolors";
66
import {
77
type ResolvedVitePluginConfig,
88
type ServerBundleBuildConfig,
9-
type ServerBundlesManifest,
9+
type BuildManifest,
10+
type ServerBundlesBuildManifest,
1011
configRouteToBranchRoute,
12+
getServerBuildDirectory,
1113
} from "./plugin";
1214
import type { ConfigRoute, RouteManifest } from "../config/routes";
1315
import invariant from "../invariant";
@@ -96,19 +98,24 @@ type RemixViteServerBuildArgs = {
9698

9799
type RemixViteBuildArgs = RemixViteClientBuildArgs | RemixViteServerBuildArgs;
98100

99-
async function getServerBuilds({
100-
routes,
101-
serverBuildDirectory,
102-
serverBuildFile,
103-
serverBundles,
104-
rootDirectory,
105-
appDirectory,
106-
}: ResolvedVitePluginConfig): Promise<{
101+
async function getServerBuilds(remixConfig: ResolvedVitePluginConfig): Promise<{
107102
serverBuilds: RemixViteServerBuildArgs[];
108-
serverBundlesManifest?: ServerBundlesManifest;
103+
buildManifest: BuildManifest;
109104
}> {
105+
// eslint-disable-next-line prefer-let/prefer-let -- Improve type narrowing
106+
const {
107+
routes,
108+
serverBuildFile,
109+
serverBundles,
110+
rootDirectory,
111+
appDirectory,
112+
} = remixConfig;
113+
let serverBuildDirectory = getServerBuildDirectory(remixConfig);
110114
if (!serverBundles) {
111-
return { serverBuilds: [{ ssr: true }] };
115+
return {
116+
serverBuilds: [{ ssr: true }],
117+
buildManifest: { routes },
118+
};
112119
}
113120

114121
let { normalizePath } = await import("vite");
@@ -124,7 +131,7 @@ async function getServerBuilds({
124131
})
125132
);
126133

127-
let serverBundlesManifest: ServerBundlesManifest = {
134+
let buildManifest: ServerBundlesBuildManifest = {
128135
serverBundles: {},
129136
routeIdToServerBundleId: {},
130137
routes: rootRelativeRoutes,
@@ -149,15 +156,15 @@ async function getServerBuilds({
149156
`The "unstable_serverBundles" function must return a string`
150157
);
151158
}
152-
serverBundlesManifest.routeIdToServerBundleId[route.id] = serverBundleId;
159+
buildManifest.routeIdToServerBundleId[route.id] = serverBundleId;
153160

154161
let relativeServerBundleDirectory = path.relative(
155162
rootDirectory,
156163
path.join(serverBuildDirectory, serverBundleId)
157164
);
158165
let serverBuildConfig = serverBundleBuildConfigById.get(serverBundleId);
159166
if (!serverBuildConfig) {
160-
serverBundlesManifest.serverBundles[serverBundleId] = {
167+
buildManifest.serverBundles[serverBundleId] = {
161168
id: serverBundleId,
162169
file: normalizePath(
163170
path.join(relativeServerBundleDirectory, serverBuildFile)
@@ -187,16 +194,20 @@ async function getServerBuilds({
187194

188195
return {
189196
serverBuilds,
190-
serverBundlesManifest,
197+
buildManifest,
191198
};
192199
}
193200

194201
async function cleanServerBuildDirectory(
195202
viteConfig: Vite.ResolvedConfig,
196-
{ rootDirectory, serverBuildDirectory }: ResolvedVitePluginConfig
203+
remixConfig: ResolvedVitePluginConfig
197204
) {
205+
let serverBuildDirectory = getServerBuildDirectory(remixConfig);
198206
let isWithinRoot = () => {
199-
let relativePath = path.relative(rootDirectory, serverBuildDirectory);
207+
let relativePath = path.relative(
208+
remixConfig.rootDirectory,
209+
serverBuildDirectory
210+
);
200211
return !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
201212
};
202213

@@ -270,28 +281,26 @@ export async function build(
270281
await viteBuild({ ssr: false });
271282

272283
// Then run Vite SSR builds in parallel
273-
let { serverBuilds, serverBundlesManifest } = await getServerBuilds(
274-
remixConfig
275-
);
284+
let { serverBuilds, buildManifest } = await getServerBuilds(remixConfig);
276285

277286
await Promise.all(serverBuilds.map(viteBuild));
278287

279-
if (serverBundlesManifest) {
288+
if (remixConfig.manifest) {
280289
await fse.writeFile(
281-
path.join(remixConfig.serverBuildDirectory, "bundles.json"),
282-
JSON.stringify(serverBundlesManifest, null, 2),
290+
path.join(remixConfig.buildDirectory, "manifest.json"),
291+
JSON.stringify(buildManifest, null, 2),
283292
"utf-8"
284293
);
285294
}
286295

287-
let { assetsBuildDirectory, serverBuildDirectory, serverBuildFile, ssr } =
288-
remixConfig;
296+
let { buildDirectory, serverBuildFile, ssr } = remixConfig;
289297

290298
await remixConfig.adapter?.buildEnd?.({
291-
assetsBuildDirectory,
292-
serverBuildDirectory,
293-
serverBuildFile,
294-
unstable_serverBundlesManifest: serverBundlesManifest,
295-
unstable_ssr: ssr,
299+
buildManifest,
300+
remixConfig: {
301+
buildDirectory,
302+
serverBuildFile,
303+
unstable_ssr: ssr,
304+
},
296305
});
297306
}

packages/remix-dev/vite/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// be imported at the top level.
44
import type { RemixVitePlugin } from "./plugin";
55
export type {
6-
ServerBundlesManifest as Unstable_ServerBundlesManifest,
6+
BuildManifest as Unstable_BuildManifest,
77
VitePluginAdapter as Unstable_VitePluginAdapter,
88
} from "./plugin";
99

0 commit comments

Comments
 (0)