---
sidebar_label: Static site generation
description: Docusaurus statically renders your React code into HTML, allowing faster load speed and better SEO.
---
# Static site generation (SSG)
In [architecture](architecture.md), we mentioned that the theme is run in Webpack. But beware: that doesn't mean it always has access to browser globals! The theme is built twice:
- During **server-side rendering**, the theme is compiled in a sandbox called [React DOM Server](https://reactjs.org/docs/react-dom-server.html). You can see this as a "headless browser", where there is no `window` or `document`, only React. SSR produces static HTML pages.
- During **client-side rendering**, the theme is compiled with standard React DOM, and has access to browser variables. CSR produces dynamic JavaScript.
:::info SSR or SSG?
_Server-side rendering_ and _static site generation_ can be different concepts, but we use them interchangeably.
:::
Therefore, while you probably know not to access Node globals like `process` ([or can we?](#node-env)) or the `'fs'` module, you can't freely access browser globals either.
```jsx
import React from 'react';
export default function WhereAmI() {
return {window.location.href};
}
```
This looks like idiomatic React, but if you run `docusaurus build`, you will get an error:
```
ReferenceError: window is not defined
```
This is because during server-side rendering, the Docusaurus app isn't actually run in browser, and it doesn't know what `window` is.
What about process.env.NODE_ENV
?
One exception to the "no Node globals" rule is `process.env.NODE_ENV`. In fact, you can use it in React, because Webpack injects this variable as a global:
```jsx
import React from 'react';
export default function expensiveComp() {
if (process.env.NODE_ENV === 'development') {
return <>This component is not shown in development>;
}
const res = someExpensiveOperationThatLastsALongTime();
return <>{res}>;
}
```
During Webpack build, the `process.env.NODE_ENV` will be replaced with the value, either `'development'` or `'production'`. You will then get different build results after dead code elimination:
import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
```diff
import React from 'react';
export default function expensiveComp() {
// highlight-next-line
if ('development' === 'development') {
+ return <>This component is not shown in development>;
}
- const res = someExpensiveOperationThatLastsALongTime();
- return <>{res}>;
}
```
```diff
import React from 'react';
export default function expensiveComp() {
// highlight-next-line
- if ('production' === 'development') {
- return <>This component is not shown in development>;
- }
+ const res = someExpensiveOperationThatLastsALongTime();
+ return <>{res}>;
}
```
## Understanding SSR {#understanding-ssr}
React is not just a dynamic UI runtime—it's also a templating engine. Because Docusaurus sites mostly contain static contents, it should be able to work without any JavaScript (which React runs in), but only plain HTML/CSS. And that's what server-side rendering offers: statically rendering your React code into HTML, without any dynamic content. An HTML file has no concept of client state (it's purely markup), hence it shouldn't rely on browser APIs.
These HTML files are the first to arrive at the user's browser screen when a URL is visited (see [routing](routing.md)). Afterwards, the browser fetches and runs other JS code to provide the "dynamic" parts of your site—anything implemented with JavaScript. However, before that, the main content of your page is already visible, allowing faster loading.
In CSR-only apps, all DOM elements are generated on client side with React, and the HTML file only ever contains one root element for React to mount DOM to; in SSR, React is already facing a fully built HTML page, and it only needs to correlate the DOM elements with the virtual DOM in its model. This step is called "hydration". After React has hydrated the static markup, the app starts to work as any normal React app.
Note that Docusaurus is ultimately a single-page application, so static site generation is only an optimization (_progressive enhancement_, as it's called), but our functionality does not fully depend on those HTML files. This is contrary to site generators like [Jekyll](https://jekyllrb.com/) and [Docusaurus v1](https://v1.docusaurus.io/), where all files are statically transformed to markup, and interactiveness is added through external JavaScript linked with `