Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SPA Mode issue when using a basename #8720

Merged
merged 1 commit into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/eighty-years-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/dev": patch
---

Fix build issue in SPA mode when using a `basename`
2 changes: 1 addition & 1 deletion integration/helpers/create-fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export async function createAppFixture(fixture: Fixture, mode?: ServerMode) {
app.use(express.static(path.join(fixture.projectDir, "build/client")));
app.get("*", (_, res, next) =>
res.sendFile(
path.join(process.cwd(), "build/client/index.html"),
path.join(fixture.projectDir, "build/client/index.html"),
next
)
);
Expand Down
82 changes: 82 additions & 0 deletions integration/spa-mode-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,88 @@ test.describe("SPA Mode", () => {
expect(html).toMatch(/^<div>/);
expect(html).not.toMatch(/<!DOCTYPE html>/);
});

test("works when combined with a basename", async ({ page }) => {
fixture = await createFixture({
compiler: "vite",
spaMode: true,
files: {
"vite.config.ts": js`
import { defineConfig } from "vite";
import { unstable_vitePlugin as remix } from "@remix-run/dev";

export default defineConfig({
plugins: [remix({
basename: "/base/",
unstable_ssr: false },
)],
});
`,
"app/root.tsx": js`
import { Outlet, Scripts } from "@remix-run/react";

export default function Root() {
return (
<html lang="en">
<head></head>
<body>
<h1 data-root>Root</h1>
<Outlet />
<Scripts />
</body>
</html>
);
}

export function HydrateFallback() {
return (
<html lang="en">
<head></head>
<body>
<h1 data-loading>Loading SPA...</h1>
<Scripts />
</body>
</html>
);
}
`,
"app/routes/_index.tsx": js`
import * as React from "react";
import { useLoaderData } from "@remix-run/react";

export async function clientLoader({ request }) {
return "Index Loader Data";
}

export default function Component() {
let data = useLoaderData();
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);

return (
<>
<h2 data-route>Index</h2>
<p data-loader-data>{data}</p>
{!mounted ? <h3>Unmounted</h3> : <h3 data-mounted>Mounted</h3>}
</>
);
}
`,
},
});
appFixture = await createAppFixture(fixture);

let app = new PlaywrightFixture(appFixture, page);
await app.goto("/base/");
console.log(await app.getHtml());
await new Promise((r) => setTimeout(r, 1000));
console.log(await app.getHtml());
await page.waitForSelector("[data-mounted]");
expect(await page.locator("[data-route]").textContent()).toBe("Index");
expect(await page.locator("[data-loader-data]").textContent()).toBe(
"Index Loader Data"
);
});
});

test.describe("normal apps", () => {
Expand Down
8 changes: 5 additions & 3 deletions packages/remix-dev/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,8 @@ export const remixVitePlugin: RemixVitePlugin = (remixUserConfig = {}) => {
serverBuildDirectory,
ctx.remixConfig.serverBuildFile,
clientBuildDirectory,
viteConfig
viteConfig,
ctx.remixConfig.basename
);
}
},
Expand Down Expand Up @@ -1721,7 +1722,8 @@ async function handleSpaMode(
serverBuildDirectoryPath: string,
serverBuildFile: string,
clientBuildDirectory: string,
viteConfig: Vite.ResolvedConfig
viteConfig: Vite.ResolvedConfig,
basename: string
) {
// Create a handler and call it for the `/` path - rendering down to the
// proper HydrateFallback ... or not! Maybe they have a static landing page
Expand All @@ -1730,7 +1732,7 @@ async function handleSpaMode(
let build = await import(url.pathToFileURL(serverBuildPath).toString());
let { createRequestHandler: createHandler } = await import("@remix-run/node");
let handler = createHandler(build, viteConfig.mode);
let response = await handler(new Request("http://localhost/"));
let response = await handler(new Request(`http://localhost${basename}`));
let html = await response.text();
if (response.status !== 200) {
throw new Error(
Expand Down
Loading