⚠️ 1. Use noExternal
for SSR Dependencies
By default, Vite externalizes dependencies, meaning they are not bundled. However, some packages (like React) must be bundled for SSR to work.
✅ Solution:
In vite.config.ts
, ensure that react
and react-dom
are included in noExternal
:
ssr: {
noExternal: ['react', 'react-dom'],
}
⚠️ 2. Avoid Using window
or document
in Server Code
React SSR runs on the server, where window
and document
do not exist. If you use them, it will cause an error.
✅ Solution:
Wrap client-only logic inside a check:
if (typeof window !== 'undefined') {
console.log('This runs only on the client');
}
⚠️ 3. Avoid Using useEffect
for Server-Side Data Fetching
useEffect
only runs on the client, so it won’t work for SSR pre-fetching.
✅ Solution:
Use data fetching inside entry-server.tsx
and pass it as props to components:
export async function render(url: string) {
const data = await fetchData(); // Fetch data before rendering
return renderToString(<App initialData={data} />);
}
⚠️ 4. Avoid CSS-in-JS That Requires window
Libraries like styled-components
work differently in SSR. If you use them, make sure to collect styles on the server.
✅ Solution:
Use ServerStyleSheet
from styled-components
:
import { ServerStyleSheet } from 'styled-components';
export function render(url: string) {
const sheet = new ServerStyleSheet();
const appHtml = renderToString(sheet.collectStyles(<App />));
const styleTags = sheet.getStyleTags();
return `${styleTags}${appHtml}`;
}
⚠️ 5. Proxy API Calls to Avoid CORS Issues
When SSR fetches data from an API, CORS restrictions may block requests.
✅ Solution:
Use Vite’s server proxy to bypass CORS:
server: {
proxy: {
'/api': 'http://localhost:5000',
},
}
⚠️ 6. Ensure Your Backend Supports SSR Routes
SSR apps need proper backend routing. If your backend only serves index.html
, SSR won’t work for dynamic routes.
✅ Solution:
Use Express/Fastify to serve all routes properly:
app.use('*', async (req, res) => {
const url = req.originalUrl;
const html = await renderSSR(url);
res.send(html);
});
⚠️ 7. Enable Hydration to Avoid UI Mismatches
If the SSR-rendered HTML does not match what React renders on the client, you’ll get a hydration error.
✅ Solution:
Ensure the same data is used on both client and server:
const [data, setData] = useState(props.initialData ?? null);