静态网站生成 (SSG)
In architecture, we mentioned that the theme is run in Webpack. 但是要注意,这并不代表它总是可以访问到浏览器的全局变量! 主题会被构建两次:
- 在服务器端渲染中,主题会在一个叫做 React DOM Server 的沙盒中被编译。 你可以把它理解成一个「无头浏览器」,这里没有
window
或者document
,只有 React。 服务端渲染 (SSR) 会生成静态 HTML 页面。 - 在客户端渲染中,主题被编译为 JavaScript,并最终在浏览器中执行,因此它可以访问浏览器变量。
SSR 还是 SSG?
服务端渲染 (SSR) 和_静态网站生成_ (SSG) 可能是不同的概念,但我们此处不作区分。
严格来说,Docusaurus 是一个静态站点生成器,因为我们没有服务器端的运行时——我们静态渲染 HTML 文件,然后部署在 CDN 上,而不是针对每个请求动态预渲染。 这有别于 Next.js 的工作模式。
因此,虽然你可能知道不要用 Node 的全局变量,比如 process
(真的不行吗?)或 'fs'
模块,但实际上你也不能随便访问浏览器的全局变量。
import React from 'react';
export default function WhereAmI() {
return <span>{window.location.href}</span>;
}
这看起来是很典型的 React 代码,但如果你运行 docusaurus build
,你会遇到一个错误:
ReferenceError: window is not defined
这是因为在服务端渲染过程中,Docusaurus 应用并没有真的在浏览器中运行,所以它不知道 window
是什么。
那 process.env.NODE_ENV
呢?
「不能用 Node 全局变量」这个规则的一个特例是 process.env.NODE_ENV
。 实际上,你可以在 React 中使用它,因为 Webpack 会把它作为一个全局变量注入:
import React from 'react';
export default function expensiveComp() {
if (process.env.NODE_ENV === 'development') {
return <>这个组件不会在开发模式渲染</>;
}
const res = someExpensiveOperationThatLastsALongTime();
return <>{res}</>;
}
在 Webpack 构建过程中,process.env.NODE_ENV
会被替换为对应的值——要么是 'development'
,要么是 'production'
。 你会在无用代码消除 (dead code elimination) 后得到不同的构建结果:
- 开发模式
- 生产模式
import React from 'react';
export default function expensiveComp() {
if ('development' === 'development') {
+ return <>这个组件不会在开发模式渲染</>;
}
- const res = someExpensiveOperationThatLastsALongTime();
- return <>{res}</>;
}