Build and preview differ from development mode for SPA #2601
-
DescriptionI am trying to connect Vike instead of Vite to an existing React SPA application (version 17.0.2) to add several SSR pages. What I did:
export default function route({ urlPathname }: { urlPathname: string }) {
// Here I skip SPA routing for specific paths
if (urlPathname.startsWith('/companies/')) {
console.log(urlPathname, ' Route matched');
return false;
}
// Otherwise, match this route => Vike uses `pages/+Page.tsx`
return { match: true };
}
// import vikeReact from 'vike-react/config';
export default {
// extends: [vikeReact],
meta: {
dataEndpointUrl: {
env: {
server: true,
// Load the value of /pages/**/+dataEndpointUrl.js only on the server
client: false,
},
},
},
};
export default 'SPA';
export default {
meta: {
dataEndpointUrl: {
env: {
server: true,
// Load the value of /pages/**/+dataEndpointUrl.js only on the server
client: false,
},
},
},
};
export default 'SSR';
// import vikeReact from 'vike-react/config';
import type { Config, ConfigEnv } from 'vike/types';
// https://vike.dev/config
export default {
// extends: [vikeReact],
clientRouting: true,
hydrationCanBeAborted: true,
passToClient: ['pageProps'],
// https://vike.dev/meta
meta: {
renderMode: {
env: { config: true },
effect({ configDefinedAt, configValue }) {
let env: ConfigEnv | undefined;
if (configValue == 'HTML') env = { server: true };
if (configValue == 'SPA') env = { client: true };
if (configValue == 'SSR') env = { server: true, client: true };
if (!env)
throw new Error(
`${configDefinedAt} should be 'SSR', 'SPA', or 'HTML'`
);
return {
meta: {
Page: { env },
},
};
},
},
},
} satisfies Config;
import * as ReactDOM from 'react-dom';
export { onRenderClient };
let root;
async function onRenderClient(pageContext) {
const { Page, pageProps, config } = pageContext;
const root = document.getElementById('root');
const pageElement = <Page {...pageProps} />;
if (
// We detect SPAs by using the fact that `innerHTML === ''` for the first render of an SPA
root.innerHTML === '' ||
// Upon Client Routing page navigation, Vike sets `pageContext.isHydration`
// to `false`.
!pageContext.isHydration
) {
// For SPA pages or client-side navigation
console.log('[SPA] or client-side navigation');
ReactDOM.render(<Page />, root);
} else {
// For SSR pages on first load, hydrate
console.log('[Server Side Rendering] hydrate the page');
ReactDOM.hydrate(pageElement, root);
}
}
import * as React from 'react';
import { renderToString } from 'react-dom/server';
import { escapeInject, dangerouslySkipEscape } from 'vike/server';
export default async function onRenderHtml(pageContext) {
const { Page } = pageContext || {};
const isSPA = !Page || pageContext.pageId === '/pages/index';
let pageHtml = '';
if (!isSPA) {
console.log(
'[Server Side Rendering] onRenderHtml > renderToString',
pageContext.pageId
);
// SSR / HTML-only
const { Page, pageProps } = pageContext || {};
pageHtml = renderToString(
<Page key={pageContext?.pageId as string} {...pageProps} />
);
}
return escapeInject`<!DOCTYPE html> <html lang="en" dir="ltr"> .......
<div id="root">${isSPA ? '' : dangerouslySkipEscape(pageHtml)}</div> .....
</html>`;
}
<script type="module" src="/src/index.tsx"></script>
{
"scripts": {
"dev": "vike dev",
"build": "rm -rf dist && NODE_ENV=production vike build",
"preview": "vike preview"
}
}
import dotenv from 'dotenv';
import vike from 'vike/plugin';
import { defineConfig } from 'vite';
import million from 'million/compiler';
import { fileURLToPath } from 'node:url';
import react from '@vitejs/plugin-react';
import svgrPlugin from 'vite-plugin-svgr';
import viteTsconfigPaths from 'vite-tsconfig-paths';
dotenv.config();
// https://vitejs.dev/config/
export default defineConfig({
server: {
host: '0.0.0.0',
port: 4200,
},
preview: {
host: '0.0.0.0',
port: 4200,
},
define: {
'process.env': {
...global.process.env,
},
},
envPrefix: 'REACT_APP_',
plugins: [
million.vite({ auto: true }),
react(),
svgrPlugin(),
viteTsconfigPaths(),
vike(),
],
}); As result of |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
Hm. It's probably a user-land issue. Did you manage to make it work? If you believe it's a Vike issue, then minimal reproduction welcome. And feel free to let us know if you believe the docs can be improved. |
Beta Was this translation helpful? Give feedback.
-
I fixed it. |
Beta Was this translation helpful? Give feedback.
I fixed it.
I deleted my old
public/index.html
so that Vike could generate it itself indist/client
.