From 07b80f16bbd2e27d00bce26a3c4460a8806f989b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Marohni=C4=87?= Date: Thu, 26 Dec 2024 17:08:48 +0100 Subject: [PATCH 01/11] Make resolve.conditions work with Vite v6 The default value for resolve.conditions in Vite v6 has changed: https://vite.dev/guide/migration.html#default-value-for-resolve-conditions This means that configuring them no longer adds the values to default values, it replaces them. This was causing problems with resolving packages like @prisma/client during SSR. This change maintains compatibility with Vite v5. --- .../vite/cloudflare-dev-proxy.ts | 23 ++++++++++++----- packages/react-router-dev/vite/plugin.ts | 25 ++++++++++++++++--- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts index 6648590e5a..60cdfad246 100644 --- a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts +++ b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts @@ -4,6 +4,7 @@ import { type Plugin } from "vite"; import { type GetPlatformProxyOptions, type PlatformProxy } from "wrangler"; import { fromNodeRequest, toNodeRequest } from "./node-adapter"; +import { preloadViteEsm, importViteEsmSync } from "./import-vite-esm-sync"; let serverBuildId = "virtual:react-router/server-build"; @@ -43,13 +44,23 @@ export const cloudflareDevProxyVitePlugin = ( return { name: PLUGIN_NAME, - config: () => ({ - ssr: { - resolve: { - externalConditions: ["workerd", "worker"], + config: async (userConfig) => { + await preloadViteEsm(); + const vite = importViteEsmSync(); + const serverConditions = + userConfig.ssr?.resolve?.externalConditions ?? + "defaultServerConditions" in vite + ? vite.defaultServerConditions + : []; + + return { + ssr: { + resolve: { + externalConditions: ["workerd", "worker", ...serverConditions], + }, }, - }, - }), + }; + }, configResolved: (viteConfig) => { let pluginIndex = (name: string) => viteConfig.plugins.findIndex((plugin) => plugin.name === name); diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index fb1fd86e10..2f1e66115f 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -738,6 +738,17 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { viteConfigEnv = _viteConfigEnv; viteCommand = viteConfigEnv.command; + let viteClientConditions: string[] = + viteUserConfig.resolve?.conditions ?? + "defaultClientConditions" in vite + ? Array.from(vite.defaultClientConditions) + : []; + let viteServerConditions: string[] = + viteUserConfig.ssr?.resolve?.conditions ?? + "defaultServerConditions" in vite + ? Array.from(vite.defaultServerConditions) + : []; + logger = vite.createLogger(viteUserConfig.logLevel, { prefix: "[react-router]", }); @@ -804,9 +815,14 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { ssr: { external: ssrExternals, resolve: { - conditions: viteCommand === "build" ? [] : ["development"], + conditions: + viteCommand === "build" + ? viteServerConditions + : ["development", ...viteServerConditions], externalConditions: - viteCommand === "build" ? [] : ["development"], + viteCommand === "build" + ? viteServerConditions + : ["development", ...viteServerConditions], }, }, optimizeDeps: { @@ -853,7 +869,10 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { "react-router/dom", "react-router-dom", ], - conditions: viteCommand === "build" ? [] : ["development"], + conditions: + viteCommand === "build" + ? viteClientConditions + : ["development", ...viteClientConditions], }, base: viteUserConfig.base, From 7515fc7c4e8e30682ebbd001ede3a8bcd27a1652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Marohni=C4=87?= Date: Thu, 26 Dec 2024 18:03:24 +0100 Subject: [PATCH 02/11] Sign the CLA --- contributors.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/contributors.yml b/contributors.yml index 0f95005269..9ecfd88942 100644 --- a/contributors.yml +++ b/contributors.yml @@ -330,3 +330,4 @@ - yuleicul - zeromask1337 - zheng-chuang +- silvenon From cae0eb9ed4a9af1be0c0ea489ffcac77e8e8ab62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Marohni=C4=87?= Date: Sat, 4 Jan 2025 19:24:26 +0100 Subject: [PATCH 03/11] Explain the compatibility layer --- packages/react-router-dev/vite/plugin.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index 2f1e66115f..40410f7115 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -738,6 +738,10 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { viteConfigEnv = _viteConfigEnv; viteCommand = viteConfigEnv.command; + // a compatibility layer from Vite v6+ and below because + // Vite v6 overrides the default resolve.conditions, so we have to import them + // and if the export doesn't exist, it means that we're in Vite v5, so an empty array should be used + // https://vite.dev/guide/migration.html#default-value-for-resolve-conditions let viteClientConditions: string[] = viteUserConfig.resolve?.conditions ?? "defaultClientConditions" in vite From 18d9037e040873d1324a2651632ab2510cb11318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Marohni=C4=87?= Date: Sat, 4 Jan 2025 19:28:58 +0100 Subject: [PATCH 04/11] Explain the compat layer in Cloudflare plugin --- packages/react-router-dev/vite/cloudflare-dev-proxy.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts index 60cdfad246..6ea1a5d9e6 100644 --- a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts +++ b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts @@ -47,6 +47,10 @@ export const cloudflareDevProxyVitePlugin = ( config: async (userConfig) => { await preloadViteEsm(); const vite = importViteEsmSync(); + // a compatibility layer from Vite v6+ and below because + // Vite v6 overrides the default resolve.conditions, so we have to import them + // and if the export doesn't exist, it means that we're in Vite v5, so an empty array should be used + // https://vite.dev/guide/migration.html#default-value-for-resolve-conditions const serverConditions = userConfig.ssr?.resolve?.externalConditions ?? "defaultServerConditions" in vite From da3a4ecc6b98a438fd3c1a1bb999253d595c975d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Marohni=C4=87?= Date: Sun, 5 Jan 2025 23:30:20 +0100 Subject: [PATCH 05/11] Don't merge conditions with user config This is new behavior that didn't exist before, so if this should be done it should be done separately. --- packages/react-router-dev/vite/cloudflare-dev-proxy.ts | 5 +---- packages/react-router-dev/vite/plugin.ts | 2 -- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts index 6ea1a5d9e6..90239af9e5 100644 --- a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts +++ b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts @@ -52,10 +52,7 @@ export const cloudflareDevProxyVitePlugin = ( // and if the export doesn't exist, it means that we're in Vite v5, so an empty array should be used // https://vite.dev/guide/migration.html#default-value-for-resolve-conditions const serverConditions = - userConfig.ssr?.resolve?.externalConditions ?? - "defaultServerConditions" in vite - ? vite.defaultServerConditions - : []; + "defaultServerConditions" in vite ? vite.defaultServerConditions : []; return { ssr: { diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index 40410f7115..caf989f416 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -743,12 +743,10 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { // and if the export doesn't exist, it means that we're in Vite v5, so an empty array should be used // https://vite.dev/guide/migration.html#default-value-for-resolve-conditions let viteClientConditions: string[] = - viteUserConfig.resolve?.conditions ?? "defaultClientConditions" in vite ? Array.from(vite.defaultClientConditions) : []; let viteServerConditions: string[] = - viteUserConfig.ssr?.resolve?.conditions ?? "defaultServerConditions" in vite ? Array.from(vite.defaultServerConditions) : []; From d487ae099acab3af741e99b1cc10a08bfb33e29c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Marohni=C4=87?= Date: Mon, 6 Jan 2025 01:05:55 +0100 Subject: [PATCH 06/11] Update importing Vite in Cloudflare plugin --- packages/react-router-dev/vite/cloudflare-dev-proxy.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts index 90239af9e5..66664db97b 100644 --- a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts +++ b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts @@ -4,7 +4,7 @@ import { type Plugin } from "vite"; import { type GetPlatformProxyOptions, type PlatformProxy } from "wrangler"; import { fromNodeRequest, toNodeRequest } from "./node-adapter"; -import { preloadViteEsm, importViteEsmSync } from "./import-vite-esm-sync"; +import { preloadVite, getVite } from "./vite"; let serverBuildId = "virtual:react-router/server-build"; @@ -44,9 +44,9 @@ export const cloudflareDevProxyVitePlugin = ( return { name: PLUGIN_NAME, - config: async (userConfig) => { - await preloadViteEsm(); - const vite = importViteEsmSync(); + config: async () => { + await preloadVite(); + const vite = getVite(); // a compatibility layer from Vite v6+ and below because // Vite v6 overrides the default resolve.conditions, so we have to import them // and if the export doesn't exist, it means that we're in Vite v5, so an empty array should be used From 80b5f1533c7c97e419980ff36df88e2905846e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Marohni=C4=87?= Date: Mon, 6 Jan 2025 01:07:13 +0100 Subject: [PATCH 07/11] Use a compact way to convert to a mutable array --- packages/react-router-dev/vite/cloudflare-dev-proxy.ts | 6 ++++-- packages/react-router-dev/vite/plugin.ts | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts index 66664db97b..44c790c590 100644 --- a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts +++ b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts @@ -51,8 +51,10 @@ export const cloudflareDevProxyVitePlugin = ( // Vite v6 overrides the default resolve.conditions, so we have to import them // and if the export doesn't exist, it means that we're in Vite v5, so an empty array should be used // https://vite.dev/guide/migration.html#default-value-for-resolve-conditions - const serverConditions = - "defaultServerConditions" in vite ? vite.defaultServerConditions : []; + const serverConditions: string[] = + "defaultServerConditions" in vite + ? [...vite.defaultServerConditions] + : []; return { ssr: { diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index caf989f416..f7972af8f6 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -744,11 +744,11 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { // https://vite.dev/guide/migration.html#default-value-for-resolve-conditions let viteClientConditions: string[] = "defaultClientConditions" in vite - ? Array.from(vite.defaultClientConditions) + ? [...vite.defaultClientConditions] : []; let viteServerConditions: string[] = "defaultServerConditions" in vite - ? Array.from(vite.defaultServerConditions) + ? [...vite.defaultServerConditions] : []; logger = vite.createLogger(viteUserConfig.logLevel, { From b0f32bafe17f026ab68359de54c82be5b2744b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Marohni=C4=87?= Date: Mon, 6 Jan 2025 01:24:55 +0100 Subject: [PATCH 08/11] Shorten resolve conditions with nullish coalescing --- .../react-router-dev/vite/cloudflare-dev-proxy.ts | 7 +++---- packages/react-router-dev/vite/plugin.ts | 14 ++++++-------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts index 44c790c590..fe4b49d467 100644 --- a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts +++ b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts @@ -51,10 +51,9 @@ export const cloudflareDevProxyVitePlugin = ( // Vite v6 overrides the default resolve.conditions, so we have to import them // and if the export doesn't exist, it means that we're in Vite v5, so an empty array should be used // https://vite.dev/guide/migration.html#default-value-for-resolve-conditions - const serverConditions: string[] = - "defaultServerConditions" in vite - ? [...vite.defaultServerConditions] - : []; + const serverConditions: string[] = [ + ...(vite.defaultServerConditions ?? []), + ]; return { ssr: { diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index f7972af8f6..c2129528db 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -742,14 +742,12 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { // Vite v6 overrides the default resolve.conditions, so we have to import them // and if the export doesn't exist, it means that we're in Vite v5, so an empty array should be used // https://vite.dev/guide/migration.html#default-value-for-resolve-conditions - let viteClientConditions: string[] = - "defaultClientConditions" in vite - ? [...vite.defaultClientConditions] - : []; - let viteServerConditions: string[] = - "defaultServerConditions" in vite - ? [...vite.defaultServerConditions] - : []; + let viteClientConditions: string[] = [ + ...(vite.defaultClientConditions ?? []), + ]; + let viteServerConditions: string[] = [ + ...(vite.defaultServerConditions ?? []), + ]; logger = vite.createLogger(viteUserConfig.logLevel, { prefix: "[react-router]", From 44f23a43f3a7fbbaf4150754b7d74bd8d50de224 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Mon, 6 Jan 2025 11:35:05 +1100 Subject: [PATCH 09/11] Add changeset --- .changeset/afraid-jeans-drive.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/afraid-jeans-drive.md diff --git a/.changeset/afraid-jeans-drive.md b/.changeset/afraid-jeans-drive.md new file mode 100644 index 0000000000..6c4b2664ac --- /dev/null +++ b/.changeset/afraid-jeans-drive.md @@ -0,0 +1,5 @@ +--- +"@react-router/dev": patch +--- + +Fix default external conditions in Vite v6. This fixes resolution issues with certain npm packages. From 904458d2be9430a28245f8b4b0a1e903d3c7390f Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Mon, 6 Jan 2025 11:40:34 +1100 Subject: [PATCH 10/11] Sort contributors.yml --- contributors.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributors.yml b/contributors.yml index 9ecfd88942..edb8420ec3 100644 --- a/contributors.yml +++ b/contributors.yml @@ -268,6 +268,7 @@ - shamsup - shihanng - shivamsinghchahar +- silvenon - SimenB - SkayuX - skratchdot @@ -330,4 +331,3 @@ - yuleicul - zeromask1337 - zheng-chuang -- silvenon From e7fa7e230f2f75c727aabd974ac4e27011617d9f Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Mon, 6 Jan 2025 11:51:33 +1100 Subject: [PATCH 11/11] Tweak comments --- packages/react-router-dev/vite/cloudflare-dev-proxy.ts | 10 +++++++--- packages/react-router-dev/vite/plugin.ts | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts index fe4b49d467..9b0afe67ab 100644 --- a/packages/react-router-dev/vite/cloudflare-dev-proxy.ts +++ b/packages/react-router-dev/vite/cloudflare-dev-proxy.ts @@ -47,9 +47,13 @@ export const cloudflareDevProxyVitePlugin = ( config: async () => { await preloadVite(); const vite = getVite(); - // a compatibility layer from Vite v6+ and below because - // Vite v6 overrides the default resolve.conditions, so we have to import them - // and if the export doesn't exist, it means that we're in Vite v5, so an empty array should be used + // This is a compatibility layer for Vite 5. Default conditions were + // automatically added to any custom conditions in Vite 5, but Vite 6 + // removed this behavior. Instead, the default conditions are overridden + // by any custom conditions. If we wish to retain the default + // conditions, we need to manually merge them using the provided default + // conditions arrays exported from Vite. In Vite 5, these default + // conditions arrays do not exist. // https://vite.dev/guide/migration.html#default-value-for-resolve-conditions const serverConditions: string[] = [ ...(vite.defaultServerConditions ?? []), diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index c2129528db..bca1dac6cf 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -738,9 +738,13 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { viteConfigEnv = _viteConfigEnv; viteCommand = viteConfigEnv.command; - // a compatibility layer from Vite v6+ and below because - // Vite v6 overrides the default resolve.conditions, so we have to import them - // and if the export doesn't exist, it means that we're in Vite v5, so an empty array should be used + // This is a compatibility layer for Vite 5. Default conditions were + // automatically added to any custom conditions in Vite 5, but Vite 6 + // removed this behavior. Instead, the default conditions are overridden + // by any custom conditions. If we wish to retain the default + // conditions, we need to manually merge them using the provided default + // conditions arrays exported from Vite. In Vite 5, these default + // conditions arrays do not exist. // https://vite.dev/guide/migration.html#default-value-for-resolve-conditions let viteClientConditions: string[] = [ ...(vite.defaultClientConditions ?? []),