Skip to content
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/spa-page-api-route.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/start": patch
---

Serve pages in SPA mode (`ssr: false`) when a route file exports both a page and an API handler, such as a `[...404].tsx` with a `GET`. The server treated those routes as API-only, so a `GET` that returned nothing gave a 404 for every URL the route matched.
34 changes: 34 additions & 0 deletions packages/start/src/server/routes.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { describe, expect, it, vi } from "vitest";

const GET = { import: () => Promise.resolve({}) };

// What the server file router produces for `routes/[...404].tsx` exporting
// both a page and `GET`, with and without the page component.
vi.mock("solid-start:routes", () => ({
default: [
{
path: "/*404",
page: true,
$component: { src: "routes/[...404].tsx", import: () => Promise.resolve({}) },
$GET: GET,
},
{ path: "/spa/*404", page: true, $GET: GET },
{ path: "/api/*rest", $GET: GET },
],
}));

const { matchAPIRoute } = await import("./routes.ts");

describe("matchAPIRoute", () => {
it("marks a route with a page and an API handler as a page", () => {
expect(matchAPIRoute("/missing", "GET")?.isPage).toBe(true);
});

it("marks it as a page in SPA builds, where the server routes have no page components", () => {
expect(matchAPIRoute("/spa/missing", "GET")?.isPage).toBe(true);
});

it("does not mark an API-only route as a page", () => {
expect(matchAPIRoute("/api/missing", "GET")?.isPage).toBe(false);
});
});
5 changes: 3 additions & 2 deletions packages/start/src/server/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ export function matchAPIRoute(

if (handler === undefined) return;

// Check if this is a page route
const isPage = route.page === true && route.$component !== undefined;
// Check if this is a page route. SPA builds leave page components out of
// the server routes, so this can't depend on `$component`.
const isPage = route.page === true;

// Return comprehensive route information
return {
Expand Down
Loading