Server Side Rendering
Analog supports server-side rendering during development and building for production.
Transforming Packages for SSR Compatibility
Some dependencies may need additional transforms to work for server-side rendering. If you receive an error during SSR in development, one option is to add the package(s) to the ssr.noExternal array in the Vite config.
You can use glob patterns to include sets of packages or libraries. Some examples are listed below.
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
ssr: {
noExternal: [
'apollo-angular', // npm package import
'apollo-angular/**', // npm package import along with sub-packages
'@spartan-ng/**', // libs under the npmScope inside an Nx workspace
],
},
// ...other config
}));
For more information about externals with SSR, check out the Vite documentation.
Hybrid Rendering with Client-Only Routes
SSR is enabled by default. For a hybrid approach, you can specify some routes to only be rendered client-side, and not be server side rendered. This is done through the routeRules configuration object by specifying an ssr option.
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
// ...other config
plugins: [
analog({
prerender: {
routes: ['/', '/404.html'],
},
nitro: {
routeRules: {
// All admin URLs are only rendered on the client
'/admin/**': { ssr: false },
// Render a 404 page as a fallback page
'/404.html': { ssr: false },
},
},
}),
],
}));
Disabling SSR
You can opt-out of it and generate a client-only build by adding the following option to the analog() plugin in your vite.config.ts:
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
// ...other config
plugins: [
analog({
ssr: false,
prerender: {
routes: [],
},
}),
],
}));
Prerendering routes
With SSR, the "/" route is prerendered by default.
It is a necessary step to return a rendered HTML when the user visits the root of the application. The prerendered routes can be customized, but keep in mind to include the "/" route also.
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
// ...other config
plugins: [
analog({
prerender: {
routes: ['/', '/about'],
},
}),
],
}));
Advanced Code Splitting (Vite 8+ / Rolldown)
When using Vite 8+ with Rolldown as the bundler, you can control how client-side chunks are created by passing codeSplitting through the vite.build.rolldownOptions.output config path. This is useful for further optimizing bundle sizes by grouping vendor or shared modules into separate chunks.
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
// ...other config
plugins: [analog()],
build: {
rolldownOptions: {
output: {
codeSplitting: {
minSize: 10000,
groups: [
{
name: 'vendor',
test: /node_modules/,
priority: 10,
},
],
},
},
},
},
}));
Code Splitting Options
| Option | Type | Description |
|---|---|---|
groups | array | Define custom chunk groups |
minSize | number | Minimum chunk size in bytes before splitting |
maxSize | number | Maximum chunk size in bytes |
Code Splitting Group Options
| Option | Type | Description |
|---|---|---|
name | string | function | Chunk name or function returning a chunk name |
test | RegExp | string | function | Pattern or predicate used to match module IDs for the group |
priority | number | Priority when a module matches multiple groups |
minSize | number | Minimum size for this group's chunks |
maxSize | number | Maximum size for this group's chunks |
minShareCount | number | Minimum number of chunks sharing a module before splitting |
This option only applies when using Rolldown as the bundler (Vite 8+). It has no effect with Rollup-based builds.
You can opt-out of prerendering altogether by passing an empty array of routes.
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
// ...other config
plugins: [
analog({
ssr: true,
prerender: {
routes: async () => {
return [];
},
},
}),
],
}));