Skip to content

Commit 6b1d41b

Browse files
committed
chore: upgrade to Vite 8 with rolldown
1 parent 2936f6a commit 6b1d41b

File tree

18 files changed

+392
-126
lines changed

18 files changed

+392
-126
lines changed

docs/pages/docs/quickstart.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ have you up and running with a modern, customizable site that your developers wi
1010

1111
## Prerequisites
1212

13-
- **Node.js** `22.7.0+` (or `20.19+`) - [Download here](https://nodejs.org/)
13+
- **Node.js** `22.12.0+` (or `20.19+`) - [Download here](https://nodejs.org/)
1414
- A terminal or command prompt
1515
- Your favorite code editor
1616

examples/with-vite-config/vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { visualizer } from "rollup-plugin-visualizer";
33
/** @type {import('vite').UserConfig} */
44
export default {
55
build: {
6-
rollupOptions: {
6+
rolldownOptions: {
77
plugins: [visualizer()],
88
},
99
},

packages/zudoku/cli.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
import semver from "semver";
44

5-
if (!semver.satisfies(process.version, ">=20.19.0 <21.0.0 || >=22.7.0")) {
5+
if (!semver.satisfies(process.version, ">=20.19.0 <21.0.0 || >=22.12.0")) {
66
// biome-ignore lint/suspicious/noConsole: Logging allowed here
77
console.error(
8-
`⚠️ Zudoku requires Node.js version >=20.19.0 or >=22.7.0. Your version: ${process.version}`,
8+
`⚠️ Zudoku requires Node.js version >=20.19.0 or >=22.12.0. Your version: ${process.version}`,
99
);
1010
process.exit(1);
1111
}

packages/zudoku/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@
176176
"remark-frontmatter": "5.0.0",
177177
"remark-gfm": "4.0.1",
178178
"remark-mdx-frontmatter": "5.2.0",
179-
"rollup": "4.59.0",
180179
"semver": "7.7.4",
181180
"shiki": "3.23.0",
182181
"sitemap": "9.0.1",
@@ -188,7 +187,7 @@
188187
"unist-util-visit": "5.1.0",
189188
"vaul": "1.1.2",
190189
"vfile": "6.0.3",
191-
"vite": "7.3.1",
190+
"vite": "8.0.0-beta.16",
192191
"yaml": "2.8.2",
193192
"yargs": "18.0.0",
194193
"zod": "4.3.6",

packages/zudoku/src/config/loader.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { stat } from "node:fs/promises";
22
import path from "node:path";
33
import colors from "picocolors";
4-
import type { RollupOutput, RollupWatcher } from "rollup";
54
import {
5+
type build,
66
type ConfigEnv,
77
runnerImport,
88
loadEnv as viteLoadEnv,
@@ -106,9 +106,9 @@ async function loadZudokuConfigWithMeta(
106106
return configWithMetadata;
107107
}
108108

109-
export function findOutputPathOfServerConfig(
110-
output: RollupOutput | RollupOutput[] | RollupWatcher,
111-
) {
109+
type BuildResult = Awaited<ReturnType<typeof build>>;
110+
111+
export function findOutputPathOfServerConfig(output: BuildResult) {
112112
if (Array.isArray(output)) {
113113
throw new Error("Expected a single output, but got an array");
114114
}

packages/zudoku/src/config/validators/icon-types.ts

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/zudoku/src/lib/authentication/errors.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ import { ZudokuError, type ZudokuErrorOptions } from "../util/invariant.js";
33
export class AuthorizationError extends Error {}
44

55
export class OAuthAuthorizationError extends ZudokuError {
6-
constructor(
7-
message: string,
8-
public error?: unknown,
9-
options?: ZudokuErrorOptions,
10-
) {
6+
error: unknown;
7+
8+
constructor(message: string, error?: unknown, options?: ZudokuErrorOptions) {
119
super(message, options);
10+
this.error = error;
1211
}
1312
}
1413

packages/zudoku/src/vite/build.ts

Lines changed: 36 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
22
import path from "node:path";
33
import { build as esbuild } from "esbuild";
4-
import type { Rollup } from "vite";
5-
import { build as viteBuild } from "vite";
4+
import { createBuilder } from "vite";
65
import { ZuploEnv } from "../app/env.js";
76
import { getZudokuRootDir } from "../cli/common/package-json.js";
87
import {
@@ -19,21 +18,6 @@ import { prerender } from "./prerender/prerender.js";
1918

2019
const DIST_DIR = "dist";
2120

22-
const extractAssets = (result: Rollup.RollupOutput) => {
23-
const jsEntry = result.output.find(
24-
(o) => "isEntry" in o && o.isEntry,
25-
)?.fileName;
26-
const cssEntries = result.output
27-
.filter((o) => o.fileName.endsWith(".css"))
28-
.map((o) => o.fileName);
29-
30-
if (!jsEntry || cssEntries.length === 0) {
31-
throw new Error("Build failed. No js or css assets found");
32-
}
33-
34-
return { jsEntry, cssEntries };
35-
};
36-
3721
export type BuildOptions = {
3822
dir: string;
3923
ssr?: boolean;
@@ -43,49 +27,56 @@ export type BuildOptions = {
4327
export async function runBuild(options: BuildOptions) {
4428
const { dir, ssr, adapter = "node" } = options;
4529

46-
// Build client and server bundles
47-
const viteClientConfig = await getViteConfig(dir, {
48-
mode: "production",
49-
command: "build",
50-
});
51-
const viteServerConfig = await getViteConfig(dir, {
30+
const viteConfig = await getViteConfig(dir, {
5231
mode: "production",
5332
command: "build",
54-
isSsrBuild: true,
5533
});
5634

57-
const clientResult = await viteBuild(viteClientConfig);
58-
const serverResult = await viteBuild({
59-
...viteServerConfig,
60-
logLevel: "silent",
61-
});
35+
const builder = await createBuilder(viteConfig);
6236

63-
if (Array.isArray(clientResult) || !("output" in clientResult)) {
64-
throw new Error("Client build failed");
65-
}
66-
if (Array.isArray(serverResult) || !("output" in serverResult)) {
67-
throw new Error("Server build failed");
68-
}
37+
invariant(builder.environments.client, "Client environment is missing");
38+
invariant(builder.environments.ssr, "SSR environment is missing");
39+
40+
const [clientResult, serverResult] = await Promise.all([
41+
builder.build(builder.environments.client),
42+
builder.build(builder.environments.ssr),
43+
]);
44+
45+
invariant(
46+
clientResult && !Array.isArray(clientResult) && "output" in clientResult,
47+
"Client build failed to produce valid output",
48+
);
49+
invariant(serverResult, "SSR build failed to produce valid output");
6950

7051
const { config } = await loadZudokuConfig(
7152
{ mode: "production", command: "build" },
7253
dir,
7354
);
7455

75-
const { jsEntry, cssEntries } = extractAssets(clientResult);
56+
const base = viteConfig.base ?? "/";
57+
const clientOutDir = viteConfig.environments?.client?.build?.outDir;
58+
const serverOutDir = viteConfig.environments?.ssr?.build?.outDir;
59+
60+
invariant(clientOutDir, "Client build outDir is missing");
61+
invariant(serverOutDir, "Server build outDir is missing");
62+
63+
const jsEntry = clientResult.output.find(
64+
(o) => "isEntry" in o && o.isEntry,
65+
)?.fileName;
66+
const cssEntries = clientResult.output
67+
.filter((o) => o.fileName.endsWith(".css"))
68+
.map((o) => o.fileName);
69+
70+
if (!jsEntry || cssEntries.length === 0) {
71+
throw new Error("Build failed. No js or css assets found");
72+
}
7673

7774
const html = getBuildHtml({
78-
jsEntry: joinUrl(viteClientConfig.base, jsEntry),
79-
cssEntries: cssEntries.map((css) => joinUrl(viteClientConfig.base, css)),
75+
jsEntry: joinUrl(base, jsEntry),
76+
cssEntries: cssEntries.map((css) => joinUrl(base, css)),
8077
dir: config.site?.dir,
8178
});
8279

83-
invariant(viteClientConfig.build?.outDir, "Client build outDir is missing");
84-
invariant(viteServerConfig.build?.outDir, "Server build outDir is missing");
85-
86-
const clientOutDir = viteClientConfig.build.outDir;
87-
const serverOutDir = viteServerConfig.build.outDir;
88-
8980
if (ssr) {
9081
// SSR: bundle entry.js and remove index.html
9182
await bundleSSREntry({
@@ -115,7 +106,7 @@ type PrerenderOptions = {
115106
html: string;
116107
clientOutDir: string;
117108
serverOutDir: string;
118-
serverResult: Rollup.RollupOutput;
109+
serverResult: Awaited<ReturnType<typeof import("vite").build>>;
119110
};
120111

121112
const runPrerender = async (options: PrerenderOptions) => {

packages/zudoku/src/vite/config.ts

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -134,29 +134,44 @@ export async function getViteConfig(
134134
},
135135
},
136136
build: {
137-
ssr: configEnv.isSsrBuild,
138137
sourcemap: true,
139138
target: "es2022",
140-
outDir: path.resolve(
141-
path.join(
142-
dir,
143-
"dist",
144-
config.basePath ?? "",
145-
configEnv.isSsrBuild ? "server" : "",
146-
),
147-
),
148-
emptyOutDir: true,
149-
rollupOptions: {
150-
input:
151-
configEnv.command === "build"
152-
? configEnv.isSsrBuild
153-
? ["zudoku/app/entry.server.tsx", config.__meta.configPath]
154-
: "zudoku/app/entry.client.tsx"
155-
: undefined,
156-
external: [joinUrl(config.basePath, "/pagefind/pagefind.js")],
157-
},
158139
chunkSizeWarningLimit: 1500,
159140
},
141+
environments: {
142+
client: {
143+
build: {
144+
outDir: path.resolve(path.join(dir, "dist", config.basePath ?? "")),
145+
emptyOutDir: true,
146+
rolldownOptions: {
147+
input:
148+
configEnv.command === "build"
149+
? "zudoku/app/entry.client.tsx"
150+
: undefined,
151+
external: [joinUrl(config.basePath, "/pagefind/pagefind.js")],
152+
},
153+
},
154+
},
155+
ssr: {
156+
build: {
157+
outDir: path.resolve(
158+
path.join(dir, "dist", config.basePath ?? "", "server"),
159+
),
160+
emptyOutDir: true,
161+
rolldownOptions: {
162+
logLevel: "warn",
163+
checks: {
164+
pluginTimings: process.env.ZUDOKU_ENV === "internal",
165+
},
166+
input:
167+
configEnv.command === "build"
168+
? ["zudoku/app/entry.server.tsx", config.__meta.configPath]
169+
: undefined,
170+
external: [joinUrl(config.basePath, "/pagefind/pagefind.js")],
171+
},
172+
},
173+
},
174+
},
160175
experimental: {
161176
renderBuiltUrl(filename) {
162177
if (cdnUrl?.base && [".js", ".css"].includes(path.extname(filename))) {
@@ -171,12 +186,9 @@ export async function getViteConfig(
171186
},
172187
},
173188
optimizeDeps: {
174-
esbuildOptions: {
175-
target: "es2022",
176-
},
177189
entries: [path.posix.join(getZudokuRootDir(), "src/{app,lib}/**")],
178-
exclude: ["zudoku"],
179190
include: [
191+
"@mdx-js/react",
180192
"react-dom/client",
181193
"zudoku/icons",
182194
...(process.env.SENTRY_DSN ? ["@sentry/react"] : []),
@@ -195,6 +207,8 @@ export async function getViteConfig(
195207
removePluginHookHandleHotUpdate: "warn",
196208
removePluginHookSsrArgument: "warn",
197209
removeServerHot: "warn",
210+
removeServerPluginContainer: "warn",
211+
removeServerReloadModule: "warn",
198212
},
199213
};
200214

packages/zudoku/src/vite/dev-server.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ export class DevServer {
6464
const configEnv: ZudokuConfigEnv = {
6565
mode: "development",
6666
command: "serve",
67-
isSsrBuild: this.options.ssr,
6867
};
6968
const viteConfig = await getViteConfig(this.options.dir, configEnv);
7069
const { config } = await loadZudokuConfig(configEnv, this.options.dir);

0 commit comments

Comments
 (0)