diff --git a/packages/react-router/src/Matches.tsx b/packages/react-router/src/Matches.tsx index 5b34093f09..3e8d27bdf4 100644 --- a/packages/react-router/src/Matches.tsx +++ b/packages/react-router/src/Matches.tsx @@ -54,7 +54,7 @@ export function Matches() { const inner = ( - + {!router.isServer && } ) diff --git a/packages/react-router/src/Transitioner.tsx b/packages/react-router/src/Transitioner.tsx index 75b913bb33..04e140acfc 100644 --- a/packages/react-router/src/Transitioner.tsx +++ b/packages/react-router/src/Transitioner.tsx @@ -30,14 +30,12 @@ export function Transitioner() { const isPagePending = isLoading || hasPendingMatches const previousIsPagePending = usePrevious(isPagePending) - if (!router.isServer) { - router.startTransition = (fn: () => void) => { - setIsTransitioning(true) - React.startTransition(() => { - fn() - setIsTransitioning(false) - }) - } + router.startTransition = (fn: () => void) => { + setIsTransitioning(true) + React.startTransition(() => { + fn() + setIsTransitioning(false) + }) } // Subscribe to location changes diff --git a/packages/solid-router/package.json b/packages/solid-router/package.json index 6f39d7b4c3..7e62c34df2 100644 --- a/packages/solid-router/package.json +++ b/packages/solid-router/package.json @@ -33,7 +33,7 @@ "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js -p tsconfig.legacy.json", "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js -p tsconfig.legacy.json", "test:types:ts58": "tsc -p tsconfig.legacy.json", - "test:unit": "vitest", + "test:unit": "vitest && vitest --mode server", "test:unit:dev": "pnpm run test:unit --watch --hideSkippedTests", "test:perf": "vitest bench", "test:perf:dev": "pnpm run test:perf --watch --hideSkippedTests", diff --git a/packages/solid-router/src/Matches.tsx b/packages/solid-router/src/Matches.tsx index 0735f16078..f11814112c 100644 --- a/packages/solid-router/src/Matches.tsx +++ b/packages/solid-router/src/Matches.tsx @@ -50,7 +50,7 @@ export function Matches() { const inner = ( - + {!router.isServer && } ) diff --git a/packages/solid-router/src/Transitioner.tsx b/packages/solid-router/src/Transitioner.tsx index d277a20c5e..2d602a2022 100644 --- a/packages/solid-router/src/Transitioner.tsx +++ b/packages/solid-router/src/Transitioner.tsx @@ -30,12 +30,10 @@ export function Transitioner() { const isPagePending = () => isLoading() || hasPendingMatches() const previousIsPagePending = usePrevious(isPagePending) - if (!router.isServer) { - router.startTransition = async (fn: () => void | Promise) => { - setIsTransitioning(true) - await fn() - setIsTransitioning(false) - } + router.startTransition = async (fn: () => void | Promise) => { + setIsTransitioning(true) + await fn() + setIsTransitioning(false) } // Subscribe to location changes @@ -66,7 +64,6 @@ export function Transitioner() { // Try to load the initial location Solid.createRenderEffect(() => { - if (router.isServer) return Solid.untrack(() => { if ( // if we are hydrating from SSR, loading is triggered in ssr-client @@ -100,6 +97,7 @@ export function Transitioner() { }, ), ) + Solid.createRenderEffect( Solid.on( [isPagePending, previousIsPagePending], diff --git a/packages/solid-router/tests/Transitioner.test.tsx b/packages/solid-router/tests/Transitioner.test.tsx index 5467795e22..ffd3ffb100 100644 --- a/packages/solid-router/tests/Transitioner.test.tsx +++ b/packages/solid-router/tests/Transitioner.test.tsx @@ -10,11 +10,13 @@ import { RouterProvider } from '../src/RouterProvider' describe('Transitioner', () => { it('should call router.load() when Transitioner mounts on the client', async () => { + const loader = vi.fn() const rootRoute = createRootRoute() const indexRoute = createRoute({ getParentRoute: () => rootRoute, path: '/', component: () =>
Index
, + loader, }) const routeTree = rootRoute.addChildren([indexRoute]) @@ -26,43 +28,16 @@ describe('Transitioner', () => { }) // Mock router.load() to verify it gets called - const loadSpy = vi.spyOn(router, 'load').mockResolvedValue(undefined) + const loadSpy = vi.spyOn(router, 'load') - render(() => ) - - // Wait for the createRenderEffect to run and call router.load() - await waitFor(() => { - expect(loadSpy).toHaveBeenCalledTimes(1) - }) - - loadSpy.mockRestore() - }) - - it('should not call router.load() when on the server', async () => { - const rootRoute = createRootRoute() - const indexRoute = createRoute({ - getParentRoute: () => rootRoute, - path: '/', - component: () =>
Index
, - }) - - const routeTree = rootRoute.addChildren([indexRoute]) - const router = createRouter({ - routeTree, - history: createMemoryHistory({ - initialEntries: ['/'], - }), - isServer: true, - }) - - // Mock router.load() to verify it gets called - const loadSpy = vi.spyOn(router, 'load').mockResolvedValue(undefined) + await router.load() render(() => ) // Wait for the createRenderEffect to run and call router.load() await waitFor(() => { - expect(loadSpy).toHaveBeenCalledTimes(0) + expect(loadSpy).toHaveBeenCalledTimes(2) + expect(loader).toHaveBeenCalledTimes(1) }) loadSpy.mockRestore() diff --git a/packages/solid-router/tests/server/Transitioner.test.tsx b/packages/solid-router/tests/server/Transitioner.test.tsx new file mode 100644 index 0000000000..7afdd57058 --- /dev/null +++ b/packages/solid-router/tests/server/Transitioner.test.tsx @@ -0,0 +1,43 @@ +import { describe, expect, it, vi } from 'vitest' +import { renderToStringAsync } from 'solid-js/web' +import { + createMemoryHistory, + createRootRoute, + createRoute, + createRouter, +} from '../../src' +import { RouterProvider } from '../../src/RouterProvider' + +describe('Transitioner (server)', () => { + it('should call router.load() only once when on the server', async () => { + const loader = vi.fn() + const rootRoute = createRootRoute() + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: () =>
Index
, + loader, + }) + + const routeTree = rootRoute.addChildren([indexRoute]) + const router = createRouter({ + routeTree, + history: createMemoryHistory({ + initialEntries: ['/'], + }), + isServer: true, + }) + + // Mock router.load() to verify it gets called + const loadSpy = vi.spyOn(router, 'load') + + await router.load() + + await renderToStringAsync(() => ) + + expect(loadSpy).toHaveBeenCalledTimes(1) + expect(loader).toHaveBeenCalledTimes(1) + + loadSpy.mockRestore() + }) +}) diff --git a/packages/solid-router/vite.config.ts b/packages/solid-router/vite.config.ts index 725568f1c9..0d90e89b74 100644 --- a/packages/solid-router/vite.config.ts +++ b/packages/solid-router/vite.config.ts @@ -4,22 +4,40 @@ import solid from 'vite-plugin-solid' import packageJson from './package.json' import type { ViteUserConfig } from 'vitest/config' -const config = defineConfig({ - plugins: [solid()] as ViteUserConfig['plugins'], - test: { - name: packageJson.name, - dir: './tests', - watch: false, - environment: 'jsdom', - typecheck: { enabled: true }, - setupFiles: ['./tests/setupTests.tsx'], - }, +const config = defineConfig(({ mode }) => { + if (mode === 'server') { + return { + plugins: [solid({ ssr: true })] as ViteUserConfig['plugins'], + test: { + name: `${packageJson.name} (server)`, + dir: './tests/server', + watch: false, + environment: 'node', + typecheck: { enabled: true }, + }, + } + } + + return { + plugins: [solid()] as ViteUserConfig['plugins'], + test: { + name: packageJson.name, + dir: './tests', + exclude: ['server'], + watch: false, + environment: 'jsdom', + typecheck: { enabled: true }, + setupFiles: ['./tests/setupTests.tsx'], + }, + } }) -export default mergeConfig( - config, - tanstackViteConfig({ - entry: ['./src/index.tsx', './src/ssr/client.ts', './src/ssr/server.ts'], - srcDir: './src', - }), +export default defineConfig((env) => + mergeConfig( + config(env), + tanstackViteConfig({ + entry: ['./src/index.tsx', './src/ssr/client.ts', './src/ssr/server.ts'], + srcDir: './src', + }), + ), )