diff --git a/.changeset/lovely-files-move.md b/.changeset/lovely-files-move.md
new file mode 100644
index 00000000000..d092bc1a9b3
--- /dev/null
+++ b/.changeset/lovely-files-move.md
@@ -0,0 +1,5 @@
+---
+"@remix-run/dev": minor
+---
+
+Add Vite v6 support
diff --git a/.gitignore b/.gitignore
index 19829b12fcb..6f3911b5c21 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,7 +14,7 @@ tsconfig.tsbuildinfo
/fixtures/my-remix-app
/fixtures/deno-app
/integration/playwright-report
-/test-results
+test-results
/uploads
.eslintcache
diff --git a/docs/guides/typescript.md b/docs/guides/typescript.md
index e57e15e74e9..d09978e8ea9 100644
--- a/docs/guides/typescript.md
+++ b/docs/guides/typescript.md
@@ -35,7 +35,7 @@ The Remix CLI will not perform any type checking. Instead, you'll want to use Ty
"@types/react-dom": "^18.2.7",
"eslint": "^8.23.1",
"typescript": "^5.1.6",
- "vite": "^5.1.4"
+ "vite": "^6.0.0"
},
"engines": {
"node": ">=18.0.0"
diff --git a/integration/helpers/vite-template/.gitignore b/integration/helpers/vite-5-template/.gitignore
similarity index 100%
rename from integration/helpers/vite-template/.gitignore
rename to integration/helpers/vite-5-template/.gitignore
diff --git a/integration/helpers/vite-template/app/root.tsx b/integration/helpers/vite-5-template/app/root.tsx
similarity index 100%
rename from integration/helpers/vite-template/app/root.tsx
rename to integration/helpers/vite-5-template/app/root.tsx
diff --git a/integration/helpers/vite-template/app/routes/_index.tsx b/integration/helpers/vite-5-template/app/routes/_index.tsx
similarity index 100%
rename from integration/helpers/vite-template/app/routes/_index.tsx
rename to integration/helpers/vite-5-template/app/routes/_index.tsx
diff --git a/integration/helpers/vite-template/env.d.ts b/integration/helpers/vite-5-template/env.d.ts
similarity index 100%
rename from integration/helpers/vite-template/env.d.ts
rename to integration/helpers/vite-5-template/env.d.ts
diff --git a/integration/helpers/vite-5-template/package.json b/integration/helpers/vite-5-template/package.json
new file mode 100644
index 00000000000..e436e3ec831
--- /dev/null
+++ b/integration/helpers/vite-5-template/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "integration-vite-5-template",
+ "version": "0.0.0",
+ "private": true,
+ "sideEffects": false,
+ "type": "module",
+ "scripts": {
+ "dev": "remix vite:dev",
+ "build": "remix vite:build",
+ "start": "remix-serve ./build/server/index.js",
+ "typecheck": "tsc"
+ },
+ "dependencies": {
+ "@remix-run/express": "workspace:*",
+ "@remix-run/node": "workspace:*",
+ "@remix-run/react": "workspace:*",
+ "@remix-run/serve": "workspace:*",
+ "@remix-run/server-runtime": "workspace:*",
+ "@vanilla-extract/css": "^1.10.0",
+ "@vanilla-extract/vite-plugin": "^3.9.2",
+ "express": "^4.20.0",
+ "isbot": "^4.1.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "serialize-javascript": "^6.0.1"
+ },
+ "devDependencies": {
+ "@remix-run/dev": "workspace:*",
+ "@remix-run/eslint-config": "workspace:*",
+ "@remix-run/route-config": "workspace:*",
+ "@types/react": "^18.2.20",
+ "@types/react-dom": "^18.2.7",
+ "eslint": "^8.38.0",
+ "typescript": "^5.1.6",
+ "vite": "5.1.8",
+ "vite-env-only": "^2.0.0",
+ "vite-tsconfig-paths": "^4.2.1",
+ "wrangler": "^3.24.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+}
diff --git a/integration/helpers/vite-template/public/favicon.ico b/integration/helpers/vite-5-template/public/favicon.ico
similarity index 100%
rename from integration/helpers/vite-template/public/favicon.ico
rename to integration/helpers/vite-5-template/public/favicon.ico
diff --git a/integration/helpers/vite-template/tsconfig.json b/integration/helpers/vite-5-template/tsconfig.json
similarity index 100%
rename from integration/helpers/vite-template/tsconfig.json
rename to integration/helpers/vite-5-template/tsconfig.json
diff --git a/integration/helpers/vite-template/vite.config.ts b/integration/helpers/vite-5-template/vite.config.ts
similarity index 100%
rename from integration/helpers/vite-template/vite.config.ts
rename to integration/helpers/vite-5-template/vite.config.ts
diff --git a/integration/helpers/vite-6-template/.gitignore b/integration/helpers/vite-6-template/.gitignore
new file mode 100644
index 00000000000..80ec311f4ff
--- /dev/null
+++ b/integration/helpers/vite-6-template/.gitignore
@@ -0,0 +1,5 @@
+node_modules
+
+/.cache
+/build
+.env
diff --git a/integration/helpers/vite-6-template/app/root.tsx b/integration/helpers/vite-6-template/app/root.tsx
new file mode 100644
index 00000000000..e31409ca31d
--- /dev/null
+++ b/integration/helpers/vite-6-template/app/root.tsx
@@ -0,0 +1,25 @@
+import {
+ Links,
+ Meta,
+ Outlet,
+ Scripts,
+ ScrollRestoration,
+} from "@remix-run/react";
+
+export default function App() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/integration/helpers/vite-6-template/app/routes/_index.tsx b/integration/helpers/vite-6-template/app/routes/_index.tsx
new file mode 100644
index 00000000000..5347369230e
--- /dev/null
+++ b/integration/helpers/vite-6-template/app/routes/_index.tsx
@@ -0,0 +1,41 @@
+import type { MetaFunction } from "@remix-run/node";
+
+export const meta: MetaFunction = () => {
+ return [
+ { title: "New Remix App" },
+ { name: "description", content: "Welcome to Remix!" },
+ ];
+};
+
+export default function Index() {
+ return (
+
+ );
+}
diff --git a/integration/helpers/vite-6-template/env.d.ts b/integration/helpers/vite-6-template/env.d.ts
new file mode 100644
index 00000000000..78ed2345c6e
--- /dev/null
+++ b/integration/helpers/vite-6-template/env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/integration/helpers/vite-template/package.json b/integration/helpers/vite-6-template/package.json
similarity index 91%
rename from integration/helpers/vite-template/package.json
rename to integration/helpers/vite-6-template/package.json
index b2b9b38c7cd..a4b1372b930 100644
--- a/integration/helpers/vite-template/package.json
+++ b/integration/helpers/vite-6-template/package.json
@@ -1,5 +1,5 @@
{
- "name": "integration-vite-template",
+ "name": "integration-vite-6-template",
"version": "0.0.0",
"private": true,
"sideEffects": false,
@@ -15,6 +15,7 @@
"@remix-run/node": "workspace:*",
"@remix-run/react": "workspace:*",
"@remix-run/serve": "workspace:*",
+ "@remix-run/server-runtime": "workspace:*",
"@vanilla-extract/css": "^1.10.0",
"@vanilla-extract/vite-plugin": "^3.9.2",
"express": "^4.20.0",
@@ -31,7 +32,7 @@
"@types/react-dom": "^18.2.7",
"eslint": "^8.38.0",
"typescript": "^5.1.6",
- "vite": "5.1.8",
+ "vite": "^6.0.0",
"vite-env-only": "^2.0.0",
"vite-tsconfig-paths": "^4.2.1",
"wrangler": "^3.24.0"
diff --git a/integration/helpers/vite-6-template/public/favicon.ico b/integration/helpers/vite-6-template/public/favicon.ico
new file mode 100644
index 00000000000..8830cf6821b
Binary files /dev/null and b/integration/helpers/vite-6-template/public/favicon.ico differ
diff --git a/integration/helpers/vite-6-template/tsconfig.json b/integration/helpers/vite-6-template/tsconfig.json
new file mode 100644
index 00000000000..ad5ae05598e
--- /dev/null
+++ b/integration/helpers/vite-6-template/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "include": ["env.d.ts", "**/*.ts", "**/*.tsx"],
+ "compilerOptions": {
+ "lib": ["DOM", "DOM.Iterable", "ES2022"],
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "jsx": "react-jsx",
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "resolveJsonModule": true,
+ "target": "ES2022",
+ "strict": true,
+ "allowJs": true,
+ "forceConsistentCasingInFileNames": true,
+ "baseUrl": ".",
+ "paths": {
+ "~/*": ["./app/*"]
+ },
+ "noEmit": true
+ }
+}
diff --git a/integration/helpers/vite-6-template/vite.config.ts b/integration/helpers/vite-6-template/vite.config.ts
new file mode 100644
index 00000000000..a1fcb5a7b79
--- /dev/null
+++ b/integration/helpers/vite-6-template/vite.config.ts
@@ -0,0 +1,7 @@
+import { vitePlugin as remix } from "@remix-run/dev";
+import { defineConfig } from "vite";
+import tsconfigPaths from "vite-tsconfig-paths";
+
+export default defineConfig({
+ plugins: [remix(), tsconfigPaths()],
+});
diff --git a/integration/helpers/vite-cloudflare-template/package.json b/integration/helpers/vite-cloudflare-template/package.json
index 7ea4574904b..d220b231c31 100644
--- a/integration/helpers/vite-cloudflare-template/package.json
+++ b/integration/helpers/vite-cloudflare-template/package.json
@@ -11,9 +11,10 @@
"typecheck": "tsc"
},
"dependencies": {
- "@remix-run/cloudflare": "2.15.1",
- "@remix-run/cloudflare-pages": "2.15.1",
- "@remix-run/react": "2.15.1",
+ "@remix-run/cloudflare": "workspace:*",
+ "@remix-run/cloudflare-pages": "workspace:*",
+ "@remix-run/react": "workspace:*",
+ "@remix-run/server-runtime": "workspace:*",
"isbot": "^4.1.0",
"miniflare": "^3.20231030.4",
"react": "^18.2.0",
@@ -26,7 +27,7 @@
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"typescript": "^5.1.6",
- "vite": "5.1.8",
+ "vite": "^6.0.0",
"vite-tsconfig-paths": "^4.2.1",
"wrangler": "^3.24.0"
},
diff --git a/integration/helpers/vite.ts b/integration/helpers/vite.ts
index cf6cc609dbf..784413bc3f0 100644
--- a/integration/helpers/vite.ts
+++ b/integration/helpers/vite.ts
@@ -96,11 +96,45 @@ export const EXPRESS_SERVER = (args: {
app.listen(port, () => console.log('http://localhost:' + port));
`;
-type TemplateName = "vite-template" | "vite-cloudflare-template";
+type TemplateName =
+ | "vite-5-template"
+ | "vite-6-template"
+ | "vite-cloudflare-template";
+
+export const viteMajorTemplates = [
+ { templateName: "vite-5-template", templateDisplayName: "Vite 5" },
+ { templateName: "vite-6-template", templateDisplayName: "Vite 6" },
+] as const satisfies ReadonlyArray<{
+ templateName: TemplateName;
+ templateDisplayName: string;
+}>;
+
+function resolveDevPackageDir(root: string) {
+ return path.join(root, "node_modules", "@remix-run", "dev");
+}
+
+function resolveDevPackageNodeModulesDir(root: string) {
+ return path.join(resolveDevPackageDir(root), "node_modules");
+}
+
+async function copyDirContents(
+ srcDir: string,
+ destDir: string,
+ filter?: (file: string) => boolean
+) {
+ for (let file of await fse.readdir(srcDir)) {
+ if (filter && !filter(path.normalize(file))) {
+ continue;
+ }
+ let srcFile = path.join(srcDir, file);
+ let destFile = path.join(destDir, file);
+ await fse.copy(srcFile, destFile, { errorOnExist: true });
+ }
+}
export async function createProject(
files: Record = {},
- templateName: TemplateName = "vite-template"
+ templateName: TemplateName = "vite-5-template"
) {
let projectName = `remix-${Math.random().toString(32).slice(2)}`;
let projectDir = path.join(TMP_DIR, projectName);
@@ -108,7 +142,27 @@ export async function createProject(
// base template
let templateDir = path.resolve(__dirname, templateName);
- await fse.copy(templateDir, projectDir, { errorOnExist: true });
+
+ // When we copy the template, we need to filter out the version of Vite
+ // installed locally within @remix-run/dev. If we don't do this, the dev
+ // package doesn't use the version of Vite defined within the test template
+ // which means we can't run integration tests across different versions of
+ // Vite. Since pnpm uses symlinks for dependencies, we need to perform the
+ // copy in multiple steps so that we can filter at each level.
+ await fse.copy(templateDir, projectDir, {
+ errorOnExist: true,
+ filter: (src) => !path.normalize(src).endsWith("/@remix-run/dev"),
+ });
+ await copyDirContents(
+ resolveDevPackageDir(templateDir),
+ resolveDevPackageDir(projectDir),
+ (file) => file !== "node_modules"
+ );
+ await copyDirContents(
+ resolveDevPackageNodeModulesDir(templateDir),
+ resolveDevPackageNodeModulesDir(projectDir),
+ (file) => file !== "vite"
+ );
// user-defined files
await Promise.all(
@@ -246,7 +300,10 @@ type Fixtures = {
port: number;
cwd: string;
}>;
- customDev: (files: Files) => Promise<{
+ customDev: (
+ files: Files,
+ templateName?: TemplateName
+ ) => Promise<{
port: number;
cwd: string;
}>;
@@ -280,7 +337,7 @@ export const test = base.extend({
// eslint-disable-next-line no-empty-pattern
customDev: async ({}, use) => {
let stop: (() => unknown) | undefined;
- await use(async (files) => {
+ await use(async (files, template) => {
let port = await getPort();
let cwd = await createProject(await files({ port }));
stop = await customDev({ cwd, port });
diff --git a/integration/package.json b/integration/package.json
index 4ced519bc75..3a63a551fe3 100644
--- a/integration/package.json
+++ b/integration/package.json
@@ -10,7 +10,7 @@
"dependencies": {
"@cloudflare/kv-asset-handler": "^0.3.0",
"@cloudflare/workers-types": "^4.20230518.0",
- "@playwright/test": "^1.33.0",
+ "@playwright/test": "^1.49.1",
"@remix-run/dev": "workspace:*",
"@remix-run/express": "workspace:*",
"@remix-run/node": "workspace:*",
@@ -30,6 +30,7 @@
"globby": "^11.1.0",
"isbot": "^4.1.0",
"npm-run-all": "^4.1.5",
+ "pathe": "^1.1.2",
"pidtree": "^0.6.0",
"postcss": "^8.4.19",
"postcss-import": "^15.1.0",
diff --git a/integration/vite-css-test.ts b/integration/vite-css-test.ts
index 77bc5ccc2f6..cd58b00c3b5 100644
--- a/integration/vite-css-test.ts
+++ b/integration/vite-css-test.ts
@@ -12,6 +12,7 @@ import {
customDev,
EXPRESS_SERVER,
viteConfig,
+ viteMajorTemplates,
} from "./helpers/vite.js";
const js = String.raw;
@@ -171,114 +172,132 @@ const VITE_CONFIG = async (port: number) => dedent`
}
`;
-test.describe(() => {
- test.describe(async () => {
- let port: number;
- let cwd: string;
- let stop: () => void;
-
- test.beforeAll(async () => {
- port = await getPort();
- cwd = await createProject({
- "vite.config.ts": await VITE_CONFIG(port),
- ...files,
- });
- stop = await viteDev({ cwd, port });
- });
- test.afterAll(() => stop());
-
- test.describe(() => {
- test.use({ javaScriptEnabled: false });
- test("Vite / CSS / vite dev / without JS", async ({ page }) => {
- await pageLoadWorkflow({ page, port });
- });
- });
-
- test.describe(() => {
- test.use({ javaScriptEnabled: true });
- test("Vite / CSS / vite dev / with JS", async ({ page }) => {
- await pageLoadWorkflow({ page, port });
- await hmrWorkflow({ page, port, cwd });
- });
- });
- });
-
- test.describe(async () => {
- let port: number;
- let cwd: string;
- let stop: () => void;
-
- test.beforeAll(async () => {
- port = await getPort();
- cwd = await createProject({
- "vite.config.ts": await VITE_CONFIG(port),
- "server.mjs": EXPRESS_SERVER({ port }),
- ...files,
- });
- stop = await customDev({ cwd, port });
- });
- test.afterAll(() => stop());
-
- test.describe(() => {
- test.use({ javaScriptEnabled: false });
- test("Vite / CSS / express / without JS", async ({ page }) => {
- await pageLoadWorkflow({ page, port });
- });
- });
-
- test.describe(() => {
- test.use({ javaScriptEnabled: true });
- test("Vite / CSS / express / with JS", async ({ page }) => {
- await pageLoadWorkflow({ page, port });
- await hmrWorkflow({ page, port, cwd });
- });
- });
- });
-
- test.describe(async () => {
- let port: number;
- let cwd: string;
- let stop: () => void;
-
- test.beforeAll(async () => {
- port = await getPort();
- cwd = await createProject({
- "vite.config.ts": await VITE_CONFIG(port),
- ...files,
- });
-
- let edit = createEditor(cwd);
- await edit("package.json", (contents) =>
- contents.replace('"sideEffects": false', '"sideEffects": ["*.css.ts"]')
- );
-
- let { stderr, status } = viteBuild({
- cwd,
- env: {
- // Vanilla Extract uses Vite's CJS build which emits a warning to stderr
- VITE_CJS_IGNORE_WARNING: "true",
- },
- });
- expect(stderr.toString()).toBeFalsy();
- expect(status).toBe(0);
- stop = await viteRemixServe({ cwd, port });
- });
- test.afterAll(() => stop());
-
- test.describe(() => {
- test.use({ javaScriptEnabled: false });
- test("Vite / CSS / vite build / without JS", async ({ page }) => {
- await pageLoadWorkflow({ page, port });
- });
- });
-
- test.describe(() => {
- test.use({ javaScriptEnabled: true });
- test("Vite / CSS / vite build / with JS", async ({ page }) => {
- await pageLoadWorkflow({ page, port });
+test.describe("Vite CSS", () => {
+ viteMajorTemplates
+ // .filter(({ templateName }) => templateName === "vite-5-template")
+ .forEach(({ templateName, templateDisplayName }) => {
+ test.describe(templateDisplayName, () => {
+ test.describe("vite dev", async () => {
+ let port: number;
+ let cwd: string;
+ let stop: () => void;
+
+ test.beforeAll(async () => {
+ port = await getPort();
+ cwd = await createProject(
+ {
+ "vite.config.ts": await VITE_CONFIG(port),
+ ...files,
+ },
+ templateName
+ );
+ stop = await viteDev({ cwd, port });
+ });
+ test.afterAll(() => stop());
+
+ test.describe(() => {
+ test.use({ javaScriptEnabled: false });
+ test("without JS", async ({ page }) => {
+ await pageLoadWorkflow({ page, port });
+ });
+ });
+
+ test.describe(() => {
+ test.use({ javaScriptEnabled: true });
+ test("with JS", async ({ page }) => {
+ await pageLoadWorkflow({ page, port });
+ await hmrWorkflow({ page, port, cwd });
+ });
+ });
+ });
+
+ test.describe("express", async () => {
+ let port: number;
+ let cwd: string;
+ let stop: () => void;
+
+ test.beforeAll(async () => {
+ port = await getPort();
+ cwd = await createProject(
+ {
+ "vite.config.ts": await VITE_CONFIG(port),
+ "server.mjs": EXPRESS_SERVER({ port }),
+ ...files,
+ },
+ templateName
+ );
+ stop = await customDev({ cwd, port });
+ });
+ test.afterAll(() => stop());
+
+ test.describe(() => {
+ test.use({ javaScriptEnabled: false });
+ test("without JS", async ({ page }) => {
+ await pageLoadWorkflow({ page, port });
+ });
+ });
+
+ test.describe(() => {
+ test.use({ javaScriptEnabled: true });
+ test("with JS", async ({ page }) => {
+ await pageLoadWorkflow({ page, port });
+ await hmrWorkflow({ page, port, cwd });
+ });
+ });
+ });
+
+ test.describe("vite build", async () => {
+ let port: number;
+ let cwd: string;
+ let stop: () => void;
+
+ test.beforeAll(async () => {
+ port = await getPort();
+ cwd = await createProject(
+ {
+ "vite.config.ts": await VITE_CONFIG(port),
+ ...files,
+ },
+ templateName
+ );
+
+ let edit = createEditor(cwd);
+ await edit("package.json", (contents) =>
+ contents.replace(
+ '"sideEffects": false',
+ '"sideEffects": ["*.css.ts"]'
+ )
+ );
+
+ let { stderr, status } = viteBuild({
+ cwd,
+ env: {
+ // Vanilla Extract uses Vite's CJS build which emits a warning to stderr
+ VITE_CJS_IGNORE_WARNING: "true",
+ },
+ });
+ expect(stderr.toString()).toBeFalsy();
+ expect(status).toBe(0);
+ stop = await viteRemixServe({ cwd, port });
+ });
+ test.afterAll(() => stop());
+
+ test.describe(() => {
+ test.use({ javaScriptEnabled: false });
+ test("without JS", async ({ page }) => {
+ await pageLoadWorkflow({ page, port });
+ });
+ });
+
+ test.describe(() => {
+ test.use({ javaScriptEnabled: true });
+ test("with JS", async ({ page }) => {
+ await pageLoadWorkflow({ page, port });
+ });
+ });
+ });
});
});
- });
});
async function pageLoadWorkflow({ page, port }: { page: Page; port: number }) {
diff --git a/integration/vite-hmr-hdr-test.ts b/integration/vite-hmr-hdr-test.ts
index aca542c36d7..19ef3622567 100644
--- a/integration/vite-hmr-hdr-test.ts
+++ b/integration/vite-hmr-hdr-test.ts
@@ -9,6 +9,7 @@ import {
createEditor,
EXPRESS_SERVER,
viteConfig,
+ viteMajorTemplates,
} from "./helpers/vite.js";
import { js } from "./helpers/create-fixture.js";
@@ -39,132 +40,130 @@ const indexRoute = `
}
`;
-test("Vite / HMR & HDR / vite dev", async ({ page, browserName, viteDev }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.js": await viteConfig.basic({ port }),
- "app/routes/_index.tsx": indexRoute,
- });
- let { cwd, port } = await viteDev(files);
- await workflow({ page, browserName, cwd, port });
-});
-
-test("Vite / HMR & HDR / express", async ({ page, browserName, customDev }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.js": await viteConfig.basic({ port }),
- "server.mjs": EXPRESS_SERVER({ port }),
- "app/routes/_index.tsx": indexRoute,
- });
- let { cwd, port } = await customDev(files);
- await workflow({ page, browserName, cwd, port });
-});
-
-test("Vite / HMR & HDR / mdx", async ({ page, viteDev }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.ts": `
- import { defineConfig } from "vite";
- import { vitePlugin as remix } from "@remix-run/dev";
- import mdx from "@mdx-js/rollup";
-
- export default defineConfig({
- ${await viteConfig.server({ port })}
- plugins: [
- mdx(),
- remix(),
- ],
+test.describe("Vite HMR & HDR", () => {
+ viteMajorTemplates.forEach(({ templateName, templateDisplayName }) => {
+ test.describe(templateDisplayName, () => {
+ test("vite dev", async ({ page, browserName, viteDev }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.js": await viteConfig.basic({ port }),
+ "app/routes/_index.tsx": indexRoute,
+ });
+ let { cwd, port } = await viteDev(files, templateName);
+ await workflow({ page, browserName, cwd, port });
});
- `,
- "app/component.tsx": `
- import {useState} from "react";
- export const Counter = () => {
- const [count, setCount] = useState(0);
- return
- }
- `,
- "app/routes/mdx.mdx": `
- import { Counter } from "../component";
-
- # MDX Title (HMR: 0)
-
-
- `,
- });
-
- let { port, cwd } = await viteDev(files);
- let edit = createEditor(cwd);
- await page.goto(`http://localhost:${port}/mdx`, {
- waitUntil: "networkidle",
- });
-
- await expect(page.locator("h1")).toHaveText("MDX Title (HMR: 0)");
- let button = page.locator("button");
- await expect(button).toHaveText("Count: 0");
- await button.click();
- await expect(button).toHaveText("Count: 1");
-
- await edit("app/routes/mdx.mdx", (contents) =>
- contents.replace("(HMR: 0)", "(HMR: 1)")
- );
- await page.waitForLoadState("networkidle");
-
- await expect(page.locator("h1")).toHaveText("MDX Title (HMR: 1)");
- await expect(page.locator("button")).toHaveText("Count: 1");
-
- expect(page.errors).toEqual([]);
-});
+ test("express", async ({ page, browserName, customDev }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.js": await viteConfig.basic({ port }),
+ "server.mjs": EXPRESS_SERVER({ port }),
+ "app/routes/_index.tsx": indexRoute,
+ });
+ let { cwd, port } = await customDev(files, templateName);
+ await workflow({ page, browserName, cwd, port });
+ });
-test.describe("single fetch", () => {
- test("Vite / HMR & HDR / vite dev", async ({
- page,
- browserName,
- viteDev,
- }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.js": js`
- import { vitePlugin as remix } from "@remix-run/dev";
-
- export default {
- ${await viteConfig.server({ port })}
- plugins: [
- remix({
- future: {
- v3_singleFetch: true
- },
- })
- ]
- }
- `,
- "app/routes/_index.tsx": indexRoute,
- });
- let { cwd, port } = await viteDev(files);
- await workflow({ page, browserName, cwd, port });
- });
+ test("mdx", async ({ page, viteDev }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.ts": `
+ import { defineConfig } from "vite";
+ import { vitePlugin as remix } from "@remix-run/dev";
+ import mdx from "@mdx-js/rollup";
+
+ export default defineConfig({
+ ${await viteConfig.server({ port })}
+ plugins: [
+ mdx(),
+ remix(),
+ ],
+ });
+ `,
+ "app/component.tsx": `
+ import {useState} from "react";
+
+ export const Counter = () => {
+ const [count, setCount] = useState(0);
+ return
+ }
+ `,
+ "app/routes/mdx.mdx": `
+ import { Counter } from "../component";
+
+ # MDX Title (HMR: 0)
+
+
+ `,
+ });
+
+ let { port, cwd } = await viteDev(files, templateName);
+ let edit = createEditor(cwd);
+ await page.goto(`http://localhost:${port}/mdx`, {
+ waitUntil: "networkidle",
+ });
+
+ await expect(page.locator("h1")).toHaveText("MDX Title (HMR: 0)");
+ let button = page.locator("button");
+ await expect(button).toHaveText("Count: 0");
+ await button.click();
+ await expect(button).toHaveText("Count: 1");
+
+ await edit("app/routes/mdx.mdx", (contents) =>
+ contents.replace("(HMR: 0)", "(HMR: 1)")
+ );
+ await page.waitForLoadState("networkidle");
+
+ await expect(page.locator("h1")).toHaveText("MDX Title (HMR: 1)");
+ await expect(page.locator("button")).toHaveText("Count: 1");
+
+ expect(page.errors).toEqual([]);
+ });
- test("Vite / HMR & HDR / express", async ({
- page,
- browserName,
- customDev,
- }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.js": js`
- import { vitePlugin as remix } from "@remix-run/dev";
-
- export default {
- ${await viteConfig.server({ port })}
- plugins: [
- remix({
- future: {
- v3_singleFetch: true
- },
- })
- ]
- }
- `,
- "server.mjs": EXPRESS_SERVER({ port }),
- "app/routes/_index.tsx": indexRoute,
+ test.describe("single fetch", () => {
+ test("vite dev", async ({ page, browserName, viteDev }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.js": js`
+ import { vitePlugin as remix } from "@remix-run/dev";
+
+ export default {
+ ${await viteConfig.server({ port })}
+ plugins: [
+ remix({
+ future: {
+ v3_singleFetch: true
+ },
+ })
+ ]
+ }
+ `,
+ "app/routes/_index.tsx": indexRoute,
+ });
+ let { cwd, port } = await viteDev(files, templateName);
+ await workflow({ page, browserName, cwd, port });
+ });
+
+ test("express", async ({ page, browserName, customDev }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.js": js`
+ import { vitePlugin as remix } from "@remix-run/dev";
+
+ export default {
+ ${await viteConfig.server({ port })}
+ plugins: [
+ remix({
+ future: {
+ v3_singleFetch: true
+ },
+ })
+ ]
+ }
+ `,
+ "server.mjs": EXPRESS_SERVER({ port }),
+ "app/routes/_index.tsx": indexRoute,
+ });
+ let { cwd, port } = await customDev(files, templateName);
+ await workflow({ page, browserName, cwd, port });
+ });
+ });
});
- let { cwd, port } = await customDev(files);
- await workflow({ page, browserName, cwd, port });
});
});
diff --git a/integration/vite-route-config-test.ts b/integration/vite-route-config-test.ts
index daf2e1a25be..258ef08bc67 100644
--- a/integration/vite-route-config-test.ts
+++ b/integration/vite-route-config-test.ts
@@ -9,6 +9,7 @@ import {
test,
viteConfig,
createEditor,
+ viteMajorTemplates,
} from "./helpers/vite.js";
const js = String.raw;
@@ -36,53 +37,61 @@ async function reloadPage({
}
test.describe("route config", () => {
- test("fails the build if route config is missing", async () => {
- let cwd = await createProject({
- "vite.config.js": `
- import { vitePlugin as remix } from "@remix-run/dev";
-
- export default {
- plugins: [remix({
- future: { v3_routeConfig: true },
- })]
- }
- `,
- });
- // Ensure file is missing in case it's ever added to test fixture
- await fs.rm(path.join(cwd, "app/routes.ts"), { force: true });
- let buildResult = viteBuild({ cwd });
- expect(buildResult.status).toBe(1);
- expect(buildResult.stderr.toString()).toContain(
- 'Route config file not found at "app/routes.ts"'
- );
- });
-
- test("fails the build if routes option is used", async () => {
- let cwd = await createProject({
- "vite.config.js": `
- import { vitePlugin as remix } from "@remix-run/dev";
-
- export default {
- plugins: [remix({
- future: { v3_routeConfig: true },
- routes: () => {},
- })]
- }
- `,
- "app/routes.ts": `export default [];`,
- });
- let buildResult = viteBuild({ cwd });
- expect(buildResult.status).toBe(1);
- expect(buildResult.stderr.toString()).toContain(
- 'The "routes" config option is not supported when a "routes.ts" file is present. You should migrate these routes into "routes.ts".'
- );
- });
-
- test("fails the dev process if routes option is used", async ({
- viteDev,
- }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.js": `
+ viteMajorTemplates.forEach(({ templateName, templateDisplayName }) => {
+ test.describe(templateDisplayName, () => {
+ test("fails the build if route config is missing", async () => {
+ let cwd = await createProject(
+ {
+ "vite.config.js": `
+ import { vitePlugin as remix } from "@remix-run/dev";
+
+ export default {
+ plugins: [remix({
+ future: { v3_routeConfig: true },
+ })]
+ }
+ `,
+ },
+ templateName
+ );
+ // Ensure file is missing in case it's ever added to test fixture
+ await fs.rm(path.join(cwd, "app/routes.ts"), { force: true });
+ let buildResult = viteBuild({ cwd });
+ expect(buildResult.status).toBe(1);
+ expect(buildResult.stderr.toString()).toContain(
+ 'Route config file not found at "app/routes.ts"'
+ );
+ });
+
+ test("fails the build if routes option is used", async () => {
+ let cwd = await createProject(
+ {
+ "vite.config.js": `
+ import { vitePlugin as remix } from "@remix-run/dev";
+
+ export default {
+ plugins: [remix({
+ future: { v3_routeConfig: true },
+ routes: () => {},
+ })]
+ }
+ `,
+ "app/routes.ts": `export default [];`,
+ },
+ templateName
+ );
+ let buildResult = viteBuild({ cwd });
+ expect(buildResult.status).toBe(1);
+ expect(buildResult.stderr.toString()).toContain(
+ 'The "routes" config option is not supported when a "routes.ts" file is present. You should migrate these routes into "routes.ts".'
+ );
+ });
+
+ test("fails the dev process if routes option is used", async ({
+ viteDev,
+ }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.js": `
import { vitePlugin as remix } from "@remix-run/dev";
export default {
@@ -93,280 +102,305 @@ test.describe("route config", () => {
})]
}
`,
- "app/routes.ts": `export default [];`,
- });
- let devError: Error | undefined;
- try {
- await viteDev(files);
- } catch (error: any) {
- devError = error;
- }
- expect(devError?.toString()).toContain(
- 'The "routes" config option is not supported when a "routes.ts" file is present. You should migrate these routes into "routes.ts".'
- );
- });
-
- test("fails the build if route config is invalid", async () => {
- let cwd = await createProject({
- "vite.config.js": `
- import { vitePlugin as remix } from "@remix-run/dev";
-
- export default {
- plugins: [remix({
- future: { v3_routeConfig: true },
- })]
- }
- `,
- "app/routes.ts": `export default INVALID(`,
- });
- let buildResult = viteBuild({ cwd });
- expect(buildResult.status).toBe(1);
- expect(buildResult.stderr.toString()).toContain(
- 'Route config in "routes.ts" is invalid.'
- );
- });
-
- test("fails the dev process if route config is initially invalid", async ({
- viteDev,
- }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.js": await viteConfig.basic({
- routeConfig: true,
- port,
- }),
- "app/routes.ts": `export default INVALID(`,
- });
- let devError: Error | undefined;
- try {
- await viteDev(files);
- } catch (error: any) {
- devError = error;
- }
- expect(devError?.toString()).toContain(
- 'Route config in "routes.ts" is invalid.'
- );
- });
-
- test("supports correcting an invalid route config", async ({
- browserName,
- page,
- context,
- viteDev,
- }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.js": await viteConfig.basic({
- routeConfig: true,
- port,
- }),
- "app/routes.ts": js`
- import { type RouteConfig, index } from "@remix-run/route-config";
-
- export default [
- index("test-route-1.tsx"),
- ] satisfies RouteConfig;
- `,
- "app/test-route-1.tsx": `
- export default function TestRoute1() {
- return Test route 1
- }
- `,
- "app/test-route-2.tsx": `
- export default function TestRoute2() {
- return Test route 2
- }
- `,
- });
- let { cwd, port } = await viteDev(files);
-
- await page.goto(`http://localhost:${port}/`, { waitUntil: "networkidle" });
- await expect(page.locator("[data-test-route]")).toHaveText("Test route 1");
-
- let edit = createEditor(cwd);
-
- // Make config invalid
- await edit("app/routes.ts", (contents) => contents + "INVALID");
-
- // Ensure dev server is still running with old config + HMR
- await edit("app/test-route-1.tsx", (contents) =>
- contents.replace("Test route 1", "Test route 1 updated")
- );
- await expect(page.locator("[data-test-route]")).toHaveText(
- "Test route 1 updated"
- );
-
- // Fix config with new route
- await edit("app/routes.ts", (contents) =>
- contents.replace("INVALID", "").replace("test-route-1", "test-route-2")
- );
-
- await expect(async () => {
- // Reload to pick up new route for current path
- page = await reloadPage({ browserName, page, context });
- await expect(page.locator("[data-test-route]")).toHaveText(
- "Test route 2"
- );
- }).toPass();
- });
-
- test("supports correcting an invalid route config module graph", async ({
- page,
- context,
- browserName,
- viteDev,
- }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.js": await viteConfig.basic({
- routeConfig: true,
- port,
- }),
- "app/routes.ts": js`
- export { default } from "./actual-routes";
- `,
- "app/actual-routes.ts": js`
- import { type RouteConfig, index } from "@remix-run/route-config";
-
- export default [
- index("test-route-1.tsx"),
- ] satisfies RouteConfig;
- `,
- "app/test-route-1.tsx": `
- export default function TestRoute1() {
- return Test route 1
+ "app/routes.ts": `export default [];`,
+ });
+ let devError: Error | undefined;
+ try {
+ await viteDev(files, templateName);
+ } catch (error: any) {
+ devError = error;
}
- `,
- "app/test-route-2.tsx": `
- export default function TestRoute2() {
- return Test route 2
+ expect(devError?.toString()).toContain(
+ 'The "routes" config option is not supported when a "routes.ts" file is present. You should migrate these routes into "routes.ts".'
+ );
+ });
+
+ test("fails the build if route config is invalid", async () => {
+ let cwd = await createProject(
+ {
+ "vite.config.js": `
+ import { vitePlugin as remix } from "@remix-run/dev";
+
+ export default {
+ plugins: [remix({
+ future: { v3_routeConfig: true },
+ })]
+ }
+ `,
+ "app/routes.ts": `export default INVALID(`,
+ },
+ templateName
+ );
+ let buildResult = viteBuild({ cwd });
+ expect(buildResult.status).toBe(1);
+ expect(buildResult.stderr.toString()).toContain(
+ 'Route config in "routes.ts" is invalid.'
+ );
+ });
+
+ test("fails the dev process if route config is initially invalid", async ({
+ viteDev,
+ }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.js": await viteConfig.basic({
+ routeConfig: true,
+ port,
+ }),
+ "app/routes.ts": `export default INVALID(`,
+ });
+ let devError: Error | undefined;
+ try {
+ await viteDev(files, templateName);
+ } catch (error: any) {
+ devError = error;
}
- `,
- });
- let { cwd, port } = await viteDev(files);
-
- await page.goto(`http://localhost:${port}/`, { waitUntil: "networkidle" });
- await expect(page.locator("[data-test-route]")).toHaveText("Test route 1");
-
- let edit = createEditor(cwd);
-
- // Make config invalid
- await edit("app/actual-routes.ts", (contents) => contents + "INVALID");
-
- // Ensure dev server is still running with old config + HMR
- await edit("app/test-route-1.tsx", (contents) =>
- contents.replace("Test route 1", "Test route 1 updated")
- );
- await expect(page.locator("[data-test-route]")).toHaveText(
- "Test route 1 updated"
- );
-
- // Fix config with new route
- await edit("app/actual-routes.ts", (contents) =>
- contents.replace("INVALID", "").replace("test-route-1", "test-route-2")
- );
-
- await expect(async () => {
- // Reload to pick up new route for current path
- page = await reloadPage({ browserName, page, context });
- await expect(page.locator("[data-test-route]")).toHaveText(
- "Test route 2"
- );
- }).toPass();
- });
-
- test("supports correcting a missing route config", async ({
- browserName,
- page,
- context,
- viteDev,
- }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.js": await viteConfig.basic({
- routeConfig: true,
- port,
- }),
- "app/routes.ts": js`
+ expect(devError?.toString()).toContain(
+ 'Route config in "routes.ts" is invalid.'
+ );
+ });
+
+ test("supports correcting an invalid route config", async ({
+ browserName,
+ page,
+ context,
+ viteDev,
+ }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.js": await viteConfig.basic({
+ routeConfig: true,
+ port,
+ }),
+ "app/routes.ts": js`
import { type RouteConfig, index } from "@remix-run/route-config";
export default [
index("test-route-1.tsx"),
] satisfies RouteConfig;
`,
- "app/test-route-1.tsx": `
- export default function TestRoute1() {
- return Test route 1
- }
- `,
- "app/test-route-2.tsx": `
- export default function TestRoute2() {
- return Test route 2
- }
- `,
- });
- let { cwd, port } = await viteDev(files);
-
- await page.goto(`http://localhost:${port}/`, { waitUntil: "networkidle" });
- await expect(page.locator("[data-test-route]")).toHaveText("Test route 1");
-
- let edit = createEditor(cwd);
-
- let INVALID_FILENAME = "app/routes.ts.oops";
-
- // Rename config to make it missing
- await fs.rename(
- path.join(cwd, "app/routes.ts"),
- path.join(cwd, INVALID_FILENAME)
- );
-
- // Ensure dev server is still running with old config + HMR
- await edit("app/test-route-1.tsx", (contents) =>
- contents.replace("Test route 1", "Test route 1 updated")
- );
- await expect(page.locator("[data-test-route]")).toHaveText(
- "Test route 1 updated"
- );
-
- // Add new route
- await edit(INVALID_FILENAME, (contents) =>
- contents.replace("test-route-1", "test-route-2")
- );
-
- // Rename config to bring it back
- await fs.rename(
- path.join(cwd, INVALID_FILENAME),
- path.join(cwd, "app/routes.ts")
- );
-
- await expect(async () => {
- // Reload to pick up new route for current path
- page = await reloadPage({ browserName, page, context });
- await expect(page.locator("[data-test-route]")).toHaveText(
- "Test route 2"
- );
- }).toPass();
- });
-
- test("supports absolute route file paths", async ({ page, viteDev }) => {
- let files: Files = async ({ port }) => ({
- "vite.config.js": await viteConfig.basic({
- routeConfig: true,
- port,
- }),
- "app/routes.ts": js`
- import path from "node:path";
- import { type RouteConfig, index } from "@remix-run/route-config";
-
- export default [
- index(path.resolve(import.meta.dirname, "test-route.tsx")),
- ] satisfies RouteConfig;
- `,
- "app/test-route.tsx": `
- export default function TestRoute() {
- return Test route
- }
- `,
+ "app/test-route-1.tsx": `
+ export default function TestRoute1() {
+ return Test route 1
+ }
+ `,
+ "app/test-route-2.tsx": `
+ export default function TestRoute2() {
+ return Test route 2
+ }
+ `,
+ });
+ let { cwd, port } = await viteDev(files, templateName);
+
+ await page.goto(`http://localhost:${port}/`, {
+ waitUntil: "networkidle",
+ });
+ await expect(page.locator("[data-test-route]")).toHaveText(
+ "Test route 1"
+ );
+
+ let edit = createEditor(cwd);
+
+ // Make config invalid
+ await edit("app/routes.ts", (contents) => contents + "INVALID");
+
+ // Ensure dev server is still running with old config + HMR
+ await edit("app/test-route-1.tsx", (contents) =>
+ contents.replace("Test route 1", "Test route 1 updated")
+ );
+ await expect(page.locator("[data-test-route]")).toHaveText(
+ "Test route 1 updated"
+ );
+
+ // Fix config with new route
+ await edit("app/routes.ts", (contents) =>
+ contents
+ .replace("INVALID", "")
+ .replace("test-route-1", "test-route-2")
+ );
+
+ await expect(async () => {
+ // Reload to pick up new route for current path
+ page = await reloadPage({ browserName, page, context });
+ await expect(page.locator("[data-test-route]")).toHaveText(
+ "Test route 2"
+ );
+ }).toPass();
+ });
+
+ test("supports correcting an invalid route config module graph", async ({
+ page,
+ context,
+ browserName,
+ viteDev,
+ }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.js": await viteConfig.basic({
+ routeConfig: true,
+ port,
+ }),
+ "app/routes.ts": js`
+ export { default } from "./actual-routes";
+ `,
+ "app/actual-routes.ts": js`
+ import { type RouteConfig, index } from "@remix-run/route-config";
+
+ export default [
+ index("test-route-1.tsx"),
+ ] satisfies RouteConfig;
+ `,
+ "app/test-route-1.tsx": `
+ export default function TestRoute1() {
+ return Test route 1
+ }
+ `,
+ "app/test-route-2.tsx": `
+ export default function TestRoute2() {
+ return Test route 2
+ }
+ `,
+ });
+ let { cwd, port } = await viteDev(files, templateName);
+
+ await page.goto(`http://localhost:${port}/`, {
+ waitUntil: "networkidle",
+ });
+ await expect(page.locator("[data-test-route]")).toHaveText(
+ "Test route 1"
+ );
+
+ let edit = createEditor(cwd);
+
+ // Make config invalid
+ await edit("app/actual-routes.ts", (contents) => contents + "INVALID");
+
+ // Ensure dev server is still running with old config + HMR
+ await edit("app/test-route-1.tsx", (contents) =>
+ contents.replace("Test route 1", "Test route 1 updated")
+ );
+ await expect(page.locator("[data-test-route]")).toHaveText(
+ "Test route 1 updated"
+ );
+
+ // Fix config with new route
+ await edit("app/actual-routes.ts", (contents) =>
+ contents
+ .replace("INVALID", "")
+ .replace("test-route-1", "test-route-2")
+ );
+
+ await expect(async () => {
+ // Reload to pick up new route for current path
+ page = await reloadPage({ browserName, page, context });
+ await expect(page.locator("[data-test-route]")).toHaveText(
+ "Test route 2"
+ );
+ }).toPass();
+ });
+
+ test("supports correcting a missing route config", async ({
+ browserName,
+ page,
+ context,
+ viteDev,
+ }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.js": await viteConfig.basic({
+ routeConfig: true,
+ port,
+ }),
+ "app/routes.ts": js`
+ import { type RouteConfig, index } from "@remix-run/route-config";
+
+ export default [
+ index("test-route-1.tsx"),
+ ] satisfies RouteConfig;
+ `,
+ "app/test-route-1.tsx": `
+ export default function TestRoute1() {
+ return Test route 1
+ }
+ `,
+ "app/test-route-2.tsx": `
+ export default function TestRoute2() {
+ return Test route 2
+ }
+ `,
+ });
+ let { cwd, port } = await viteDev(files, templateName);
+
+ await page.goto(`http://localhost:${port}/`, {
+ waitUntil: "networkidle",
+ });
+ await expect(page.locator("[data-test-route]")).toHaveText(
+ "Test route 1"
+ );
+
+ let edit = createEditor(cwd);
+
+ let INVALID_FILENAME = "app/routes.ts.oops";
+
+ // Rename config to make it missing
+ await fs.rename(
+ path.join(cwd, "app/routes.ts"),
+ path.join(cwd, INVALID_FILENAME)
+ );
+
+ // Ensure dev server is still running with old config + HMR
+ await edit("app/test-route-1.tsx", (contents) =>
+ contents.replace("Test route 1", "Test route 1 updated")
+ );
+ await expect(page.locator("[data-test-route]")).toHaveText(
+ "Test route 1 updated"
+ );
+
+ // Add new route
+ await edit(INVALID_FILENAME, (contents) =>
+ contents.replace("test-route-1", "test-route-2")
+ );
+
+ // Rename config to bring it back
+ await fs.rename(
+ path.join(cwd, INVALID_FILENAME),
+ path.join(cwd, "app/routes.ts")
+ );
+
+ await expect(async () => {
+ // Reload to pick up new route for current path
+ page = await reloadPage({ browserName, page, context });
+ await expect(page.locator("[data-test-route]")).toHaveText(
+ "Test route 2"
+ );
+ }).toPass();
+ });
+
+ test("supports absolute route file paths", async ({ page, viteDev }) => {
+ let files: Files = async ({ port }) => ({
+ "vite.config.js": await viteConfig.basic({
+ routeConfig: true,
+ port,
+ }),
+ "app/routes.ts": js`
+ import path from "node:path";
+ import { type RouteConfig, index } from "@remix-run/route-config";
+
+ export default [
+ index(path.resolve(import.meta.dirname, "test-route.tsx")),
+ ] satisfies RouteConfig;
+ `,
+ "app/test-route.tsx": `
+ export default function TestRoute() {
+ return Test route
+ }
+ `,
+ });
+ let { port } = await viteDev(files, templateName);
+
+ await page.goto(`http://localhost:${port}/`, {
+ waitUntil: "networkidle",
+ });
+ await expect(page.locator("[data-test-route]")).toHaveText(
+ "Test route"
+ );
+ });
});
- let { port } = await viteDev(files);
-
- await page.goto(`http://localhost:${port}/`, { waitUntil: "networkidle" });
- await expect(page.locator("[data-test-route]")).toHaveText("Test route");
});
});
diff --git a/package.json b/package.json
index 511e6694e4c..2a0afe76882 100644
--- a/package.json
+++ b/package.json
@@ -53,7 +53,7 @@
"@octokit/graphql": "^4.8.0",
"@octokit/plugin-paginate-rest": "^2.17.0",
"@octokit/rest": "^18.12.0",
- "@playwright/test": "^1.33.0",
+ "@playwright/test": "^1.49.1",
"@remix-run/architect": "workspace:*",
"@remix-run/changelog-github": "^0.0.5",
"@remix-run/cloudflare": "workspace:*",
@@ -129,7 +129,7 @@
"unified": "^10.1.2",
"unist-util-remove": "^3.1.0",
"unist-util-visit": "^4.1.1",
- "vite": "5.1.8",
+ "vite": "^6.0.0",
"vite-tsconfig-paths": "^4.2.2",
"wait-on": "^7.0.1",
"wrangler": "^3.72.3"
diff --git a/packages/remix-dev/package.json b/packages/remix-dev/package.json
index e7fd64e8795..5d4bc2be4a1 100644
--- a/packages/remix-dev/package.json
+++ b/packages/remix-dev/package.json
@@ -74,7 +74,7 @@
"tar-fs": "^2.1.1",
"tsconfig-paths": "^4.0.0",
"valibot": "^0.41.0",
- "vite-node": "^1.6.0",
+ "vite-node": "3.0.0-beta.2",
"ws": "^7.5.10"
},
"devDependencies": {
@@ -104,14 +104,13 @@
"msw": "^1.2.3",
"strip-ansi": "^6.0.1",
"tiny-invariant": "^1.2.0",
- "vite": "5.1.8",
"wrangler": "^3.28.2"
},
"peerDependencies": {
"@remix-run/react": "^2.15.1",
"@remix-run/serve": "^2.15.1",
"typescript": "^5.1.0",
- "vite": "^5.1.0",
+ "vite": "^5.1.0 || ^6.0.0",
"wrangler": "^3.28.2"
},
"peerDependenciesMeta": {
diff --git a/packages/remix-dev/vite/plugin.ts b/packages/remix-dev/vite/plugin.ts
index e18bf788568..882d3b5d61d 100644
--- a/packages/remix-dev/vite/plugin.ts
+++ b/packages/remix-dev/vite/plugin.ts
@@ -1815,13 +1815,74 @@ export const remixVitePlugin: RemixVitePlugin = (remixUserConfig = {}) => {
return modules;
},
},
+ {
+ name: "react-router-server-change-trigger-client-hmr",
+ // This hook is only available in Vite v6+ so this is a no-op in v5.
+ // Previously the server and client modules were shared in a single module
+ // graph. This meant that changes to server code automatically resulted in
+ // client HMR updates. In Vite v6+ these module graphs are separate from
+ // each other so we need to manually trigger client HMR updates if server
+ // code has changed.
+ hotUpdate(this, { server, modules }) {
+ if (this.environment.name !== "ssr" && modules.length <= 0) {
+ return;
+ }
+
+ let clientModules = uniqueNodes(
+ modules.flatMap((mod) =>
+ getParentClientNodes(server.environments.client.moduleGraph, mod)
+ )
+ );
+
+ for (let clientModule of clientModules) {
+ server.environments.client.reloadModule(clientModule);
+ }
+ },
+ },
];
};
+function getParentClientNodes(
+ clientModuleGraph: Vite.EnvironmentModuleGraph,
+ module: Vite.EnvironmentModuleNode
+): Vite.EnvironmentModuleNode[] {
+ if (!module.id) {
+ return [];
+ }
+
+ let clientModule = clientModuleGraph.getModuleById(module.id);
+ if (clientModule) {
+ return [clientModule];
+ }
+
+ return [...module.importers].flatMap((importer) =>
+ getParentClientNodes(clientModuleGraph, importer)
+ );
+}
+
+function uniqueNodes(
+ nodes: Vite.EnvironmentModuleNode[]
+): Vite.EnvironmentModuleNode[] {
+ let nodeUrls = new Set();
+ let unique: Vite.EnvironmentModuleNode[] = [];
+ for (let node of nodes) {
+ if (nodeUrls.has(node.url)) {
+ continue;
+ }
+ nodeUrls.add(node.url);
+ unique.push(node);
+ }
+ return unique;
+}
+
function isInRemixMonorepo() {
- let devPath = path.dirname(require.resolve("@remix-run/dev/package.json"));
- let devParentDir = path.basename(path.resolve(devPath, ".."));
- return devParentDir === "packages";
+ try {
+ let devPath = path.dirname(require.resolve("@remix-run/node/package.json"));
+ let devParentDir = path.basename(path.resolve(devPath, ".."));
+ return devParentDir === "packages";
+ } catch {
+ return false;
+ }
}
function isEqualJson(v1: unknown, v2: unknown) {
diff --git a/packages/remix-dev/vite/styles.ts b/packages/remix-dev/vite/styles.ts
index f2910da5f89..7c9e85d309c 100644
--- a/packages/remix-dev/vite/styles.ts
+++ b/packages/remix-dev/vite/styles.ts
@@ -5,6 +5,7 @@ import { type ModuleNode, type ViteDevServer } from "vite";
import { type RemixConfig as ResolvedRemixConfig } from "../config";
import { resolveFileUrl } from "./resolve-file-url";
+import { importViteEsmSync } from "./import-vite-esm-sync";
type ServerRouteManifest = ServerBuild["routes"];
type ServerRoute = ServerRouteManifest[string];
@@ -48,6 +49,9 @@ export const isCssUrlWithoutSideEffects = (url: string) => {
return false;
};
+const injectQuery = (url: string, query: string) =>
+ url.includes("?") ? url.replace("?", `?${query}&`) : `${url}?${query}`;
+
const getStylesForFiles = async ({
viteDevServer,
rootDirectory,
@@ -59,6 +63,9 @@ const getStylesForFiles = async ({
cssModulesManifest: Record;
files: string[];
}): Promise => {
+ let vite = importViteEsmSync();
+ let viteMajor = parseInt(vite.version.split(".")[0], 10);
+
let styles: Record = {};
let deps = new Set();
@@ -103,15 +110,26 @@ const getStylesForFiles = async ({
try {
let css = isCssModulesFile(dep.file)
? cssModulesManifest[dep.file]
- : (await viteDevServer.ssrLoadModule(dep.url)).default;
+ : (
+ await viteDevServer.ssrLoadModule(
+ // We need the ?inline query in Vite v6 when loading CSS in SSR
+ // since it does not expose the default export for CSS in a
+ // server environment. This is to align with non-SSR
+ // environments. For backwards compatibility with v5 we keep
+ // using the URL without ?inline query because the HMR code was
+ // relying on the implicit SSR-client module graph relationship.
+ viteMajor >= 6 ? injectQuery(dep.url, "inline") : dep.url
+ )
+ ).default;
if (css === undefined) {
throw new Error();
}
styles[dep.url] = css;
- } catch {
+ } catch (err) {
console.warn(`Could not load ${dep.file}`);
+ console.error(err);
// this can happen with dynamically imported modules, I think
// because the Vite module graph doesn't distinguish between
// static and dynamic imports? TODO investigate, submit fix
diff --git a/packages/remix-route-config/package.json b/packages/remix-route-config/package.json
index 175af0bcbfe..b7f4a47d663 100644
--- a/packages/remix-route-config/package.json
+++ b/packages/remix-route-config/package.json
@@ -23,7 +23,7 @@
"@remix-run/dev": "workspace:*",
"@types/lodash": "^4.14.182",
"typescript": "^5.1.6",
- "vite": "5.1.8"
+ "vite": "^6.0.0"
},
"peerDependencies": {
"@remix-run/dev": "^2.15.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5e0dd0f6f2c..e7658f510b9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -62,8 +62,8 @@ importers:
specifier: ^18.12.0
version: 18.12.0
'@playwright/test':
- specifier: ^1.33.0
- version: 1.41.2
+ specifier: ^1.49.1
+ version: 1.49.1
'@remix-run/architect':
specifier: workspace:*
version: link:packages/remix-architect
@@ -290,11 +290,11 @@ importers:
specifier: ^4.1.1
version: 4.1.1
vite:
- specifier: 5.1.8
- version: 5.1.8(@types/node@18.17.1)
+ specifier: ^6.0.0
+ version: 6.0.3(@types/node@18.17.1)
vite-tsconfig-paths:
specifier: ^4.2.2
- version: 4.3.1(typescript@5.1.6)(vite@5.1.8)
+ version: 4.3.1(typescript@5.1.6)(vite@6.0.3)
wait-on:
specifier: ^7.0.1
version: 7.0.1
@@ -311,8 +311,8 @@ importers:
specifier: ^4.20230518.0
version: 4.20240208.0
'@playwright/test':
- specifier: ^1.33.0
- version: 1.41.2
+ specifier: ^1.49.1
+ version: 1.49.1
'@remix-run/dev':
specifier: workspace:*
version: link:../packages/remix-dev
@@ -370,6 +370,9 @@ importers:
npm-run-all:
specifier: ^4.1.5
version: 4.1.5
+ pathe:
+ specifier: ^1.1.2
+ version: 1.1.2
pidtree:
specifier: ^0.6.0
version: 0.6.0
@@ -546,7 +549,7 @@ importers:
version: 3.2.1
postcss-import:
specifier: ^15.1.0
- version: 15.1.0(postcss@8.4.35)
+ version: 15.1.0(postcss@8.4.49)
tailwindcss:
specifier: ^3.3.0
version: 3.4.1
@@ -554,51 +557,72 @@ importers:
specifier: ^5.1.0
version: 5.1.6
- integration/helpers/vite-cloudflare-template:
+ integration/helpers/vite-5-template:
dependencies:
- '@remix-run/cloudflare':
- specifier: 2.15.1
- version: link:../../../packages/remix-cloudflare
- '@remix-run/cloudflare-pages':
- specifier: 2.15.1
- version: link:../../../packages/remix-cloudflare-pages
+ '@remix-run/express':
+ specifier: workspace:*
+ version: link:../../../packages/remix-express
+ '@remix-run/node':
+ specifier: workspace:*
+ version: link:../../../packages/remix-node
'@remix-run/react':
- specifier: 2.15.1
+ specifier: workspace:*
version: link:../../../packages/remix-react
+ '@remix-run/serve':
+ specifier: workspace:*
+ version: link:../../../packages/remix-serve
+ '@remix-run/server-runtime':
+ specifier: workspace:*
+ version: link:../../../packages/remix-server-runtime
+ '@vanilla-extract/css':
+ specifier: ^1.10.0
+ version: 1.14.1
+ '@vanilla-extract/vite-plugin':
+ specifier: ^3.9.2
+ version: 3.9.5(vite@5.1.8)
+ express:
+ specifier: ^4.20.0
+ version: 4.21.1
isbot:
specifier: ^4.1.0
version: 4.4.0
- miniflare:
- specifier: ^3.20231030.4
- version: 3.20240821.1
react:
specifier: ^18.2.0
version: 18.2.0
react-dom:
specifier: ^18.2.0
version: 18.2.0(react@18.2.0)
+ serialize-javascript:
+ specifier: ^6.0.1
+ version: 6.0.2
devDependencies:
- '@cloudflare/workers-types':
- specifier: ^4.20230518.0
- version: 4.20240208.0
'@remix-run/dev':
specifier: workspace:*
version: link:../../../packages/remix-dev
'@remix-run/eslint-config':
specifier: workspace:*
version: link:../../../packages/remix-eslint-config
+ '@remix-run/route-config':
+ specifier: workspace:*
+ version: link:../../../packages/remix-route-config
'@types/react':
specifier: ^18.2.20
version: 18.2.20
'@types/react-dom':
specifier: ^18.2.7
version: 18.2.7
+ eslint:
+ specifier: ^8.38.0
+ version: 8.56.0
typescript:
specifier: ^5.1.6
version: 5.1.6
vite:
specifier: 5.1.8
version: 5.1.8(@types/node@18.17.1)
+ vite-env-only:
+ specifier: ^2.0.0
+ version: 2.2.0
vite-tsconfig-paths:
specifier: ^4.2.1
version: 4.3.1(typescript@5.1.6)(vite@5.1.8)
@@ -606,7 +630,7 @@ importers:
specifier: ^3.24.0
version: 3.74.0(@cloudflare/workers-types@4.20240208.0)
- integration/helpers/vite-template:
+ integration/helpers/vite-6-template:
dependencies:
'@remix-run/express':
specifier: workspace:*
@@ -620,12 +644,15 @@ importers:
'@remix-run/serve':
specifier: workspace:*
version: link:../../../packages/remix-serve
+ '@remix-run/server-runtime':
+ specifier: workspace:*
+ version: link:../../../packages/remix-server-runtime
'@vanilla-extract/css':
specifier: ^1.10.0
version: 1.14.1
'@vanilla-extract/vite-plugin':
specifier: ^3.9.2
- version: 3.9.5(vite@5.1.8)
+ version: 3.9.5(vite@6.0.3)
express:
specifier: ^4.20.0
version: 4.21.1
@@ -664,14 +691,69 @@ importers:
specifier: ^5.1.6
version: 5.1.6
vite:
- specifier: 5.1.8
- version: 5.1.8(@types/node@18.17.1)
+ specifier: ^6.0.0
+ version: 6.0.3(@types/node@18.17.1)
vite-env-only:
specifier: ^2.0.0
version: 2.2.0
vite-tsconfig-paths:
specifier: ^4.2.1
- version: 4.3.1(typescript@5.1.6)(vite@5.1.8)
+ version: 4.3.1(typescript@5.1.6)(vite@6.0.3)
+ wrangler:
+ specifier: ^3.24.0
+ version: 3.74.0(@cloudflare/workers-types@4.20240208.0)
+
+ integration/helpers/vite-cloudflare-template:
+ dependencies:
+ '@remix-run/cloudflare':
+ specifier: workspace:*
+ version: link:../../../packages/remix-cloudflare
+ '@remix-run/cloudflare-pages':
+ specifier: workspace:*
+ version: link:../../../packages/remix-cloudflare-pages
+ '@remix-run/react':
+ specifier: workspace:*
+ version: link:../../../packages/remix-react
+ '@remix-run/server-runtime':
+ specifier: workspace:*
+ version: link:../../../packages/remix-server-runtime
+ isbot:
+ specifier: ^4.1.0
+ version: 4.4.0
+ miniflare:
+ specifier: ^3.20231030.4
+ version: 3.20240821.1
+ react:
+ specifier: ^18.2.0
+ version: 18.2.0
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.2.0(react@18.2.0)
+ devDependencies:
+ '@cloudflare/workers-types':
+ specifier: ^4.20230518.0
+ version: 4.20240208.0
+ '@remix-run/dev':
+ specifier: workspace:*
+ version: link:../../../packages/remix-dev
+ '@remix-run/eslint-config':
+ specifier: workspace:*
+ version: link:../../../packages/remix-eslint-config
+ '@types/react':
+ specifier: ^18.2.20
+ version: 18.2.20
+ '@types/react-dom':
+ specifier: ^18.2.7
+ version: 18.2.7
+ typescript:
+ specifier: ^5.1.6
+ version: 5.1.6
+ vite:
+ specifier: ^6.0.0
+ version: 6.0.3(@types/node@18.17.1)
+ vite-tsconfig-paths:
+ specifier: ^4.2.1
+ version: 4.3.1(typescript@5.1.6)(vite@6.0.3)
wrangler:
specifier: ^3.24.0
version: 3.74.0(@cloudflare/workers-types@4.20240208.0)
@@ -1011,9 +1093,12 @@ importers:
valibot:
specifier: ^0.41.0
version: 0.41.0(typescript@5.1.6)
+ vite:
+ specifier: ^5.1.0 || ^6.0.0
+ version: 6.0.3(@types/node@18.17.1)
vite-node:
- specifier: ^1.6.0
- version: 1.6.0(@types/node@18.17.1)
+ specifier: 3.0.0-beta.2
+ version: 3.0.0-beta.2(@types/node@18.17.1)
ws:
specifier: ^7.5.10
version: 7.5.10
@@ -1096,9 +1181,6 @@ importers:
tiny-invariant:
specifier: ^1.2.0
version: 1.3.1
- vite:
- specifier: 5.1.8
- version: 5.1.8(@types/node@18.17.1)
wrangler:
specifier: ^3.28.2
version: 3.74.0(@cloudflare/workers-types@4.20240208.0)
@@ -1306,8 +1388,8 @@ importers:
specifier: ^5.1.6
version: 5.1.6
vite:
- specifier: 5.1.8
- version: 5.1.8(@types/node@18.17.1)
+ specifier: ^6.0.0
+ version: 6.0.3(@types/node@18.17.1)
packages/remix-routes-option-adapter:
devDependencies:
@@ -3064,6 +3146,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/aix-ppc64@0.24.0:
+ resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+ requiresBuild: true
+ optional: true
+
/@esbuild/android-arm64@0.17.19:
resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
engines: {node: '>=12'}
@@ -3088,6 +3178,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/android-arm64@0.24.0:
+ resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ optional: true
+
/@esbuild/android-arm@0.17.19:
resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
engines: {node: '>=12'}
@@ -3112,6 +3210,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/android-arm@0.24.0:
+ resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ optional: true
+
/@esbuild/android-x64@0.17.19:
resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
engines: {node: '>=12'}
@@ -3136,6 +3242,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/android-x64@0.24.0:
+ resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ optional: true
+
/@esbuild/darwin-arm64@0.17.19:
resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
engines: {node: '>=12'}
@@ -3160,6 +3274,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/darwin-arm64@0.24.0:
+ resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ optional: true
+
/@esbuild/darwin-x64@0.17.19:
resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
engines: {node: '>=12'}
@@ -3184,6 +3306,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/darwin-x64@0.24.0:
+ resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ optional: true
+
/@esbuild/freebsd-arm64@0.17.19:
resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
engines: {node: '>=12'}
@@ -3208,6 +3338,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/freebsd-arm64@0.24.0:
+ resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ optional: true
+
/@esbuild/freebsd-x64@0.17.19:
resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
engines: {node: '>=12'}
@@ -3232,6 +3370,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/freebsd-x64@0.24.0:
+ resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ optional: true
+
/@esbuild/linux-arm64@0.17.19:
resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
engines: {node: '>=12'}
@@ -3256,6 +3402,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/linux-arm64@0.24.0:
+ resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@esbuild/linux-arm@0.17.19:
resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
engines: {node: '>=12'}
@@ -3280,6 +3434,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/linux-arm@0.24.0:
+ resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@esbuild/linux-ia32@0.17.19:
resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
engines: {node: '>=12'}
@@ -3304,6 +3466,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/linux-ia32@0.24.0:
+ resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@esbuild/linux-loong64@0.17.19:
resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
engines: {node: '>=12'}
@@ -3328,6 +3498,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/linux-loong64@0.24.0:
+ resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@esbuild/linux-mips64el@0.17.19:
resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
engines: {node: '>=12'}
@@ -3352,6 +3530,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/linux-mips64el@0.24.0:
+ resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@esbuild/linux-ppc64@0.17.19:
resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
engines: {node: '>=12'}
@@ -3376,6 +3562,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/linux-ppc64@0.24.0:
+ resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@esbuild/linux-riscv64@0.17.19:
resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
engines: {node: '>=12'}
@@ -3400,6 +3594,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/linux-riscv64@0.24.0:
+ resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@esbuild/linux-s390x@0.17.19:
resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
engines: {node: '>=12'}
@@ -3424,6 +3626,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/linux-s390x@0.24.0:
+ resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@esbuild/linux-x64@0.17.19:
resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
engines: {node: '>=12'}
@@ -3448,6 +3658,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/linux-x64@0.24.0:
+ resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@esbuild/netbsd-x64@0.17.19:
resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
engines: {node: '>=12'}
@@ -3472,6 +3690,22 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/netbsd-x64@0.24.0:
+ resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ optional: true
+
+ /@esbuild/openbsd-arm64@0.24.0:
+ resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+ requiresBuild: true
+ optional: true
+
/@esbuild/openbsd-x64@0.17.19:
resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
engines: {node: '>=12'}
@@ -3496,6 +3730,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/openbsd-x64@0.24.0:
+ resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ optional: true
+
/@esbuild/sunos-x64@0.17.19:
resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
engines: {node: '>=12'}
@@ -3520,6 +3762,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/sunos-x64@0.24.0:
+ resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ optional: true
+
/@esbuild/win32-arm64@0.17.19:
resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
engines: {node: '>=12'}
@@ -3544,6 +3794,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/win32-arm64@0.24.0:
+ resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ optional: true
+
/@esbuild/win32-ia32@0.17.19:
resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
engines: {node: '>=12'}
@@ -3568,6 +3826,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/win32-ia32@0.24.0:
+ resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ optional: true
+
/@esbuild/win32-x64@0.17.19:
resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
engines: {node: '>=12'}
@@ -3592,6 +3858,14 @@ packages:
requiresBuild: true
optional: true
+ /@esbuild/win32-x64@0.24.0:
+ resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ optional: true
+
/@eslint-community/eslint-utils@4.4.0(eslint@8.56.0):
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -4248,12 +4522,12 @@ packages:
requiresBuild: true
optional: true
- /@playwright/test@1.41.2:
- resolution: {integrity: sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==}
- engines: {node: '>=16'}
+ /@playwright/test@1.49.1:
+ resolution: {integrity: sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==}
+ engines: {node: '>=18'}
hasBin: true
dependencies:
- playwright: 1.41.2
+ playwright: 1.49.1
dev: false
/@remix-run/changelog-github@0.0.5:
@@ -4413,6 +4687,13 @@ packages:
rollup: 2.79.2
dev: false
+ /@rollup/rollup-android-arm-eabi@4.28.1:
+ resolution: {integrity: sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-android-arm-eabi@4.4.1:
resolution: {integrity: sha512-Ss4suS/sd+6xLRu+MLCkED2mUrAyqHmmvZB+zpzZ9Znn9S8wCkTQCJaQ8P8aHofnvG5L16u9MVnJjCqioPErwQ==}
cpu: [arm]
@@ -4420,6 +4701,13 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-android-arm64@4.28.1:
+ resolution: {integrity: sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-android-arm64@4.4.1:
resolution: {integrity: sha512-sRSkGTvGsARwWd7TzC8LKRf8FiPn7257vd/edzmvG4RIr9x68KBN0/Ek48CkuUJ5Pj/Dp9vKWv6PEupjKWjTYA==}
cpu: [arm64]
@@ -4427,6 +4715,13 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-darwin-arm64@4.28.1:
+ resolution: {integrity: sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-darwin-arm64@4.4.1:
resolution: {integrity: sha512-nz0AiGrrXyaWpsmBXUGOBiRDU0wyfSXbFuF98pPvIO8O6auQsPG6riWsfQqmCCC5FNd8zKQ4JhgugRNAkBJ8mQ==}
cpu: [arm64]
@@ -4434,6 +4729,13 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-darwin-x64@4.28.1:
+ resolution: {integrity: sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-darwin-x64@4.4.1:
resolution: {integrity: sha512-Ogqvf4/Ve/faMaiPRvzsJEqajbqs00LO+8vtrPBVvLgdw4wBg6ZDXdkDAZO+4MLnrc8mhGV6VJAzYScZdPLtJg==}
cpu: [x64]
@@ -4441,6 +4743,27 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-freebsd-arm64@4.28.1:
+ resolution: {integrity: sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ optional: true
+
+ /@rollup/rollup-freebsd-x64@4.28.1:
+ resolution: {integrity: sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ optional: true
+
+ /@rollup/rollup-linux-arm-gnueabihf@4.28.1:
+ resolution: {integrity: sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-linux-arm-gnueabihf@4.4.1:
resolution: {integrity: sha512-9zc2tqlr6HfO+hx9+wktUlWTRdje7Ub15iJqKcqg5uJZ+iKqmd2CMxlgPpXi7+bU7bjfDIuvCvnGk7wewFEhCg==}
cpu: [arm]
@@ -4448,6 +4771,20 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-linux-arm-musleabihf@4.28.1:
+ resolution: {integrity: sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-gnu@4.28.1:
+ resolution: {integrity: sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-linux-arm64-gnu@4.4.1:
resolution: {integrity: sha512-phLb1fN3rq2o1j1v+nKxXUTSJnAhzhU0hLrl7Qzb0fLpwkGMHDem+o6d+ZI8+/BlTXfMU4kVWGvy6g9k/B8L6Q==}
cpu: [arm64]
@@ -4455,6 +4792,13 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-linux-arm64-musl@4.28.1:
+ resolution: {integrity: sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-linux-arm64-musl@4.4.1:
resolution: {integrity: sha512-M2sDtw4tf57VPSjbTAN/lz1doWUqO2CbQuX3L9K6GWIR5uw9j+ROKCvvUNBY8WUbMxwaoc8mH9HmmBKsLht7+w==}
cpu: [arm64]
@@ -4462,6 +4806,41 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-linux-loongarch64-gnu@4.28.1:
+ resolution: {integrity: sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
+ /@rollup/rollup-linux-powerpc64le-gnu@4.28.1:
+ resolution: {integrity: sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
+ /@rollup/rollup-linux-riscv64-gnu@4.28.1:
+ resolution: {integrity: sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
+ /@rollup/rollup-linux-s390x-gnu@4.28.1:
+ resolution: {integrity: sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-gnu@4.28.1:
+ resolution: {integrity: sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-linux-x64-gnu@4.4.1:
resolution: {integrity: sha512-mHIlRLX+hx+30cD6c4BaBOsSqdnCE4ok7/KDvjHYAHoSuveoMMxIisZFvcLhUnyZcPBXDGZTuBoalcuh43UfQQ==}
cpu: [x64]
@@ -4469,6 +4848,13 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-linux-x64-musl@4.28.1:
+ resolution: {integrity: sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-linux-x64-musl@4.4.1:
resolution: {integrity: sha512-tB+RZuDi3zxFx7vDrjTNGVLu2KNyzYv+UY8jz7e4TMEoAj7iEt8Qk6xVu6mo3pgjnsHj6jnq3uuRsHp97DLwOA==}
cpu: [x64]
@@ -4476,6 +4862,13 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-win32-arm64-msvc@4.28.1:
+ resolution: {integrity: sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-win32-arm64-msvc@4.4.1:
resolution: {integrity: sha512-Hdn39PzOQowK/HZzYpCuZdJC91PE6EaGbTe2VCA9oq2u18evkisQfws0Smh9QQGNNRa/T7MOuGNQoLeXhhE3PQ==}
cpu: [arm64]
@@ -4483,6 +4876,13 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-win32-ia32-msvc@4.28.1:
+ resolution: {integrity: sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-win32-ia32-msvc@4.4.1:
resolution: {integrity: sha512-tLpKb1Elm9fM8c5w3nl4N1eLTP4bCqTYw9tqUBxX8/hsxqHO3dxc2qPbZ9PNkdK4tg4iLEYn0pOUnVByRd2CbA==}
cpu: [ia32]
@@ -4490,6 +4890,13 @@ packages:
requiresBuild: true
optional: true
+ /@rollup/rollup-win32-x64-msvc@4.28.1:
+ resolution: {integrity: sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ optional: true
+
/@rollup/rollup-win32-x64-msvc@4.4.1:
resolution: {integrity: sha512-eAhItDX9yQtZVM3yvXS/VR3qPqcnXvnLyx1pLXl4JzyNMBNO3KC986t/iAg2zcMzpAp9JSvxB5VZGnBiNoA98w==}
cpu: [x64]
@@ -4756,6 +5163,9 @@ packages:
/@types/estree@1.0.0:
resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==}
+ /@types/estree@1.0.6:
+ resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
+
/@types/express-serve-static-core@4.17.43:
resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==}
dependencies:
@@ -5342,6 +5752,28 @@ packages:
- terser
- ts-node
+ /@vanilla-extract/vite-plugin@3.9.5(vite@6.0.3):
+ resolution: {integrity: sha512-CWI/CtrVW6i3HKccI6T7uGQkTJ8bd8Xl2UMBg3Pkr7dwWMmavXTeucV0I9KSbmXaYXSbEj+Q8c9y0xAZwtmTig==}
+ peerDependencies:
+ vite: ^2.2.3 || ^3.0.0 || ^4.0.3 || ^5.0.0
+ dependencies:
+ '@vanilla-extract/integration': 6.5.0(@types/node@18.17.1)
+ outdent: 0.8.0
+ postcss: 8.4.35
+ postcss-load-config: 4.0.2(postcss@8.4.35)
+ vite: 6.0.3(@types/node@18.17.1)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - ts-node
+ dev: false
+
/@web3-storage/multipart-parser@1.0.0:
resolution: {integrity: sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==}
dev: false
@@ -6915,6 +7347,18 @@ packages:
ms: 2.1.2
supports-color: 8.1.1
+ /debug@4.4.0:
+ resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.3
+ dev: false
+
/decamelize-keys@1.1.0:
resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==}
engines: {node: '>=0.10.0'}
@@ -7353,6 +7797,10 @@ packages:
resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==}
dev: false
+ /es-module-lexer@1.5.4:
+ resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
+ dev: false
+
/es-set-tostringtag@2.0.2:
resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==}
engines: {node: '>= 0.4'}
@@ -7488,6 +7936,37 @@ packages:
'@esbuild/win32-ia32': 0.19.12
'@esbuild/win32-x64': 0.19.12
+ /esbuild@0.24.0:
+ resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
+ engines: {node: '>=18'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.24.0
+ '@esbuild/android-arm': 0.24.0
+ '@esbuild/android-arm64': 0.24.0
+ '@esbuild/android-x64': 0.24.0
+ '@esbuild/darwin-arm64': 0.24.0
+ '@esbuild/darwin-x64': 0.24.0
+ '@esbuild/freebsd-arm64': 0.24.0
+ '@esbuild/freebsd-x64': 0.24.0
+ '@esbuild/linux-arm': 0.24.0
+ '@esbuild/linux-arm64': 0.24.0
+ '@esbuild/linux-ia32': 0.24.0
+ '@esbuild/linux-loong64': 0.24.0
+ '@esbuild/linux-mips64el': 0.24.0
+ '@esbuild/linux-ppc64': 0.24.0
+ '@esbuild/linux-riscv64': 0.24.0
+ '@esbuild/linux-s390x': 0.24.0
+ '@esbuild/linux-x64': 0.24.0
+ '@esbuild/netbsd-x64': 0.24.0
+ '@esbuild/openbsd-arm64': 0.24.0
+ '@esbuild/openbsd-x64': 0.24.0
+ '@esbuild/sunos-x64': 0.24.0
+ '@esbuild/win32-arm64': 0.24.0
+ '@esbuild/win32-ia32': 0.24.0
+ '@esbuild/win32-x64': 0.24.0
+
/escalade@3.1.1:
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
engines: {node: '>=6'}
@@ -12325,6 +12804,9 @@ packages:
/picocolors@1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+ /picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
/picomatch@2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
@@ -12372,18 +12854,18 @@ packages:
mlly: 1.5.0
pathe: 1.1.2
- /playwright-core@1.41.2:
- resolution: {integrity: sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==}
- engines: {node: '>=16'}
+ /playwright-core@1.49.1:
+ resolution: {integrity: sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==}
+ engines: {node: '>=18'}
hasBin: true
dev: false
- /playwright@1.41.2:
- resolution: {integrity: sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==}
- engines: {node: '>=16'}
+ /playwright@1.49.1:
+ resolution: {integrity: sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==}
+ engines: {node: '>=18'}
hasBin: true
dependencies:
- playwright-core: 1.41.2
+ playwright-core: 1.49.1
optionalDependencies:
fsevents: 2.3.2
dev: false
@@ -12413,6 +12895,18 @@ packages:
read-cache: 1.0.0
resolve: 1.22.8
+ /postcss-import@15.1.0(postcss@8.4.49):
+ resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+ dependencies:
+ postcss: 8.4.49
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.8
+ dev: true
+
/postcss-js@4.0.1(postcss@8.4.35):
resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
engines: {node: ^12 || ^14 || >= 16}
@@ -12522,6 +13016,14 @@ packages:
picocolors: 1.0.0
source-map-js: 1.0.2
+ /postcss@8.4.49:
+ resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
/preferred-pm@3.0.3:
resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==}
engines: {node: '>=10'}
@@ -13309,6 +13811,34 @@ packages:
fsevents: 2.3.3
dev: false
+ /rollup@4.28.1:
+ resolution: {integrity: sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+ dependencies:
+ '@types/estree': 1.0.6
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.28.1
+ '@rollup/rollup-android-arm64': 4.28.1
+ '@rollup/rollup-darwin-arm64': 4.28.1
+ '@rollup/rollup-darwin-x64': 4.28.1
+ '@rollup/rollup-freebsd-arm64': 4.28.1
+ '@rollup/rollup-freebsd-x64': 4.28.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.28.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.28.1
+ '@rollup/rollup-linux-arm64-gnu': 4.28.1
+ '@rollup/rollup-linux-arm64-musl': 4.28.1
+ '@rollup/rollup-linux-loongarch64-gnu': 4.28.1
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.28.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.28.1
+ '@rollup/rollup-linux-s390x-gnu': 4.28.1
+ '@rollup/rollup-linux-x64-gnu': 4.28.1
+ '@rollup/rollup-linux-x64-musl': 4.28.1
+ '@rollup/rollup-win32-arm64-msvc': 4.28.1
+ '@rollup/rollup-win32-ia32-msvc': 4.28.1
+ '@rollup/rollup-win32-x64-msvc': 4.28.1
+ fsevents: 2.3.3
+
/rollup@4.4.1:
resolution: {integrity: sha512-idZzrUpWSblPJX66i+GzrpjKE3vbYrlWirUHteoAbjKReZwa0cohAErOYA5efoMmNCdvG9yrJS+w9Kl6csaH4w==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -13682,6 +14212,10 @@ packages:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'}
+ /source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
/source-map-support@0.5.13:
resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==}
dependencies:
@@ -14902,6 +15436,31 @@ packages:
- supports-color
- terser
+ /vite-node@3.0.0-beta.2(@types/node@18.17.1):
+ resolution: {integrity: sha512-ofTf6cfRdL30Wbl9n/BX81EyIR5s4PReLmSurrxQ+koLaWUNOEo8E0lCM53OJkb8vpa2URM2nSrxZsIFyvY1rg==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.0
+ es-module-lexer: 1.5.4
+ pathe: 1.1.2
+ vite: 6.0.3(@types/node@18.17.1)
+ transitivePeerDependencies:
+ - '@types/node'
+ - jiti
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+ dev: false
+
/vite-tsconfig-paths@4.3.1(typescript@5.1.6)(vite@5.1.8):
resolution: {integrity: sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw==}
peerDependencies:
@@ -14918,6 +15477,22 @@ packages:
- supports-color
- typescript
+ /vite-tsconfig-paths@4.3.1(typescript@5.1.6)(vite@6.0.3):
+ resolution: {integrity: sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw==}
+ peerDependencies:
+ vite: '*'
+ peerDependenciesMeta:
+ vite:
+ optional: true
+ dependencies:
+ debug: 4.3.4(supports-color@8.1.1)
+ globrex: 0.1.2
+ tsconfck: 3.0.2(typescript@5.1.6)
+ vite: 6.0.3(@types/node@18.17.1)
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
/vite@5.1.8(@types/node@18.17.1):
resolution: {integrity: sha512-mB8ToUuSmzODSpENgvpFk2fTiU/YQ1tmcVJJ4WZbq4fPdGJkFNVcmVL5k7iDug6xzWjjuGDKAuSievIsD6H7Xw==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -14953,6 +15528,53 @@ packages:
optionalDependencies:
fsevents: 2.3.3
+ /vite@6.0.3(@types/node@18.17.1):
+ resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+ dependencies:
+ '@types/node': 18.17.1
+ esbuild: 0.24.0
+ postcss: 8.4.49
+ rollup: 4.28.1
+ optionalDependencies:
+ fsevents: 2.3.3
+
/w3c-xmlserializer@4.0.0:
resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==}
engines: {node: '>=14'}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index e8c91c3e82c..cae0a89b7ea 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,26 +1,4 @@
packages:
- "integration"
- - "integration/helpers/node-template"
- - "integration/helpers/cf-template"
- - "integration/helpers/deno-template"
- - "integration/helpers/vite-cloudflare-template"
- - "integration/helpers/vite-template"
- - "packages/create-remix"
- - "packages/remix"
- - "packages/remix-architect"
- - "packages/remix-cloudflare"
- - "packages/remix-cloudflare-pages"
- - "packages/remix-cloudflare-workers"
- - "packages/remix-css-bundle"
- - "packages/remix-deno"
- - "packages/remix-dev"
- - "packages/remix-eslint-config"
- - "packages/remix-express"
- - "packages/remix-fs-routes"
- - "packages/remix-node"
- - "packages/remix-react"
- - "packages/remix-route-config"
- - "packages/remix-routes-option-adapter"
- - "packages/remix-serve"
- - "packages/remix-server-runtime"
- - "packages/remix-testing"
+ - "integration/helpers/*"
+ - "packages/*"
diff --git a/templates/cloudflare-workers/package.json b/templates/cloudflare-workers/package.json
index 05f8a969ee8..d84d92f8ba5 100644
--- a/templates/cloudflare-workers/package.json
+++ b/templates/cloudflare-workers/package.json
@@ -36,7 +36,7 @@
"postcss": "^8.4.38",
"tailwindcss": "^3.4.4",
"typescript": "^5.1.6",
- "vite": "^5.1.0",
+ "vite": "^6.0.0",
"vite-tsconfig-paths": "^4.2.1",
"wrangler": "3.84.0"
},
diff --git a/templates/cloudflare/package.json b/templates/cloudflare/package.json
index a5e4ad758f9..143b49d5704 100644
--- a/templates/cloudflare/package.json
+++ b/templates/cloudflare/package.json
@@ -36,7 +36,7 @@
"postcss": "^8.4.38",
"tailwindcss": "^3.4.4",
"typescript": "^5.1.6",
- "vite": "^5.1.0",
+ "vite": "^6.0.0",
"vite-tsconfig-paths": "^4.2.1",
"wrangler": "3.57.1"
},
diff --git a/templates/express/package.json b/templates/express/package.json
index 76cfea70840..46cfef75153 100644
--- a/templates/express/package.json
+++ b/templates/express/package.json
@@ -40,7 +40,7 @@
"postcss": "^8.4.38",
"tailwindcss": "^3.4.4",
"typescript": "^5.1.6",
- "vite": "^5.1.0",
+ "vite": "^6.0.0",
"vite-tsconfig-paths": "^4.2.1"
},
"engines": {
diff --git a/templates/remix-javascript/package.json b/templates/remix-javascript/package.json
index 37ef4a0149f..da45a9f8994 100644
--- a/templates/remix-javascript/package.json
+++ b/templates/remix-javascript/package.json
@@ -26,7 +26,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.4",
- "vite": "^5.1.0"
+ "vite": "^6.0.0"
},
"engines": {
"node": ">=20.0.0"
diff --git a/templates/remix-tutorial/package.json b/templates/remix-tutorial/package.json
index 33f36e251e7..b097107debd 100644
--- a/templates/remix-tutorial/package.json
+++ b/templates/remix-tutorial/package.json
@@ -33,7 +33,7 @@
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"typescript": "^5.1.6",
- "vite": "^5.1.4",
+ "vite": "^6.0.0",
"vite-tsconfig-paths": "^4.3.1"
},
"engines": {
diff --git a/templates/remix/package.json b/templates/remix/package.json
index 439b4d75a6a..a67dfacc2ce 100644
--- a/templates/remix/package.json
+++ b/templates/remix/package.json
@@ -33,7 +33,7 @@
"postcss": "^8.4.38",
"tailwindcss": "^3.4.4",
"typescript": "^5.1.6",
- "vite": "^5.1.0",
+ "vite": "^6.0.0",
"vite-tsconfig-paths": "^4.2.1"
},
"engines": {
diff --git a/templates/spa/package.json b/templates/spa/package.json
index 29f994629d9..3c9ca2040d4 100644
--- a/templates/spa/package.json
+++ b/templates/spa/package.json
@@ -31,7 +31,7 @@
"postcss": "^8.4.38",
"tailwindcss": "^3.4.4",
"typescript": "^5.1.6",
- "vite": "^5.1.0",
+ "vite": "^6.0.0",
"vite-tsconfig-paths": "^4.2.1"
},
"engines": {