Static site generation (SSG)
In architecture, 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. You can see this as a "headless browser", where there is no
window
ordocument
, only React. SSR produces static HTML pages. - During client-side rendering, the theme is compiled to JavaScript that gets eventually executed in the browser, so it has access to browser variables.
Server-side rendering and static site generation can be different concepts, but we use them interchangeably.
Strictly speaking, Docusaurus is a static site generator, because there's no server-side runtime—we statically render to HTML files that are deployed on a CDN, instead of dynamically pre-rendering on each request. This differs from the working model of Next.js.
Therefore, while you probably know not to access Node globals like process
(or can we?) or the 'fs'
module, you can't freely access browser globals either.
import React from 'react';
export default function WhereAmI() {
return <span>{window.location.href}</span>;
}
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:
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:
- Development
- Production
import React from 'react';
export default function expensiveComp() {
if ('development' === 'development') {
+ return <>This component is not shown in development</>;
}
- const res = someExpensiveOperationThatLastsALongTime();
- return <>{res}</>;
}
import React from 'react';
export default function expensiveComp() {
- if ('production' === 'development') {
- return <>This component is not shown in development</>;
- }
+ const res = someExpensiveOperationThatLastsALongTime();
+ return <>{res}</>;
}