From d284e52879e133046d776215102ed4203230a57d Mon Sep 17 00:00:00 2001 From: Chad Date: Tue, 13 Feb 2024 16:32:50 -0600 Subject: [PATCH] Fix Vite client route requests with pre-processed search params (#8740) Co-authored-by: Mark Dalgleish --- .changeset/vite-whatwg-querystring.md | 5 +++++ contributors.yml | 1 + packages/remix-dev/vite/plugin.ts | 17 ++++++++++++++--- 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 .changeset/vite-whatwg-querystring.md diff --git a/.changeset/vite-whatwg-querystring.md b/.changeset/vite-whatwg-querystring.md new file mode 100644 index 00000000000..4a06ebf33b2 --- /dev/null +++ b/.changeset/vite-whatwg-querystring.md @@ -0,0 +1,5 @@ +--- +"@remix-run/dev": minor +--- + +Vite: Fix issue where client route file requests fail if search params have been parsed and serialized before reaching the Remix Vite plugin diff --git a/contributors.yml b/contributors.yml index c0c75c574c6..be73746ec93 100644 --- a/contributors.yml +++ b/contributors.yml @@ -114,6 +114,7 @@ - crismali - CSFlorin - cysp +- cythrawll - d4vsanchez - dabdine - daganomri diff --git a/packages/remix-dev/vite/plugin.ts b/packages/remix-dev/vite/plugin.ts index 28f2ad29276..bbaa19bddb0 100644 --- a/packages/remix-dev/vite/plugin.ts +++ b/packages/remix-dev/vite/plugin.ts @@ -248,6 +248,13 @@ const getHash = (source: BinaryLike, maxLength?: number): string => { return typeof maxLength === "number" ? hash.slice(0, maxLength) : hash; }; +const isClientRoute = (id: string): boolean => { + return ( + id.endsWith(CLIENT_ROUTE_QUERY_STRING) || + id.endsWith(`${CLIENT_ROUTE_QUERY_STRING}=`) // Needed in case url gets preprocessed by any WHATWG searchParam serializer + ); +}; + const resolveChunk = ( ctx: RemixPluginContext, viteManifest: Vite.Manifest, @@ -1090,8 +1097,12 @@ export const remixVitePlugin: RemixVitePlugin = (remixUserConfig = {}) => { cssModulesManifest[id] = code; } - if (id.endsWith(CLIENT_ROUTE_QUERY_STRING)) { + if (isClientRoute(id)) { let routeModuleId = id.replace(CLIENT_ROUTE_QUERY_STRING, ""); + routeModuleId = routeModuleId.replace( + `${CLIENT_ROUTE_QUERY_STRING}=`, + "" + ); let sourceExports = await getRouteModuleExports( viteChildCompiler, ctx, @@ -1520,7 +1531,7 @@ export const remixVitePlugin: RemixVitePlugin = (remixUserConfig = {}) => { let useFastRefresh = !ssr && (isJSX || code.includes(devRuntime)); if (!useFastRefresh) return; - if (id.endsWith(CLIENT_ROUTE_QUERY_STRING)) { + if (isClientRoute(id)) { return { code: addRefreshWrapper(ctx.remixConfig, code, id) }; } @@ -1607,7 +1618,7 @@ function addRefreshWrapper( ): string { let route = getRoute(remixConfig, id); let acceptExports = - route || id.endsWith(CLIENT_ROUTE_QUERY_STRING) + route || isClientRoute(id) ? [ "clientAction", "clientLoader",