
React Static 配置完全指南深入static.config.js的每一项参数【免费下载链接】react-static⚛️ A progressive static site generator for React.项目地址: https://gitcode.com/gh_mirrors/re/react-staticstatic.config.js是 React Static一个渐进式 React 静态站点生成器的核心配置文件掌控着路由构建、站点元数据、资源路径、构建性能与 HTML 文档骨架等全部关键行为。本指南以 docs/config.md 为主体结合 packages/react-static 内的源码实现逐项拆解每一个配置项帮助你理解每个参数背后的运行机制并能在自己的项目中准确、安全地配置它们。认识static.config.js文件位置与加载机制static.config.js位于项目根目录是一个可选但强烈推荐的文件。如果不提供它React Static 会以一组内置默认值运行提供后它必须default export一个对象对象中可以包含下文中任意属性的子集。从源码 getConfig.js 可以看到默认约定const DEFAULT_NAME_FOR_STATIC_CONFIG_FILE static.config.js const DEFAULT_ROUTES [{ path: / }] const DEFAULT_ENTRY index.js const DEFAULT_EXTENSIONS [.js, .jsx]也就是说即使完全没有配置文件React Static 也会默认生成一条指向/的路由、使用index.js作为入口并支持.js/.jsx扩展名。加载逻辑还支持两种额外的配置来源getConfig.js通过state.configPath显式指定的路径package.json中的config字段指定的路径以上都未提供时回退到根目录下的static.config.js。开发模式下的热重载该文件在开发模式下会被chokidar监听getConfig.js一旦你保存了static.config.jsReact Static 会自动重新执行getRoutes路由或路由数据的变更会即时热更新到浏览器无需手动重启 dev server。如果不想反复编辑保存配置文件文档还推荐直接调用rebuildRoutesAPI 来触发同样的重建流程——该 API 在 getRoutes.js 中被实现为一个可被覆盖的引用rebuildRoutes.current。路由体系getRoutes与routegetRoutes异步生成全部路由getRoutes是一个异步函数应 resolve 出一个由 route 对象组成的数组。它通常在构建开始时被调用用来拉取构建所有路由所需的动态数据。它接收一个参数对象其中包含布尔值dev用于区分当前是生产构建还是开发环境// static.config.js export default { getRoutes: async ({ dev }) [...routes], }从源码角度看实际的路由来源不止用户配置这一处。在 getRoutes.js 中路由最终由「插件贡献的路由」与「用户getRoutes返回的路由」合并而成const pluginRoutes await plugins.getRoutes([], state) const userRoutes await state.config.getRoutes(state) const routes [...pluginRoutes, ...userRoutes]合并后还会经过normalizeAllRoutes的递归扁平化处理。这里有两个值得注意的强制约束getRoutes.js必须存在 index 路由若构建结果中没有path /的路由构建会直接报错404 路由自动兜底若没有任何 404 路由React Static 会自动插入内置的 Default404 组件作为 404 页面。route对象结构路由对象代表站点中的一个唯一位置是整个 React Static 站点的骨架。它支持以下属性属性类型说明pathString该路由要匹配的 URL 路径不含搜索参数与 hash 片段相对于siteRoot basePath若是子路由则再相对于父路由的 pathtemplateString渲染该路由所用组件的路径相对于项目根目录或使用绝对路径getDataasync Function异步函数resolve 出该路由渲染所需的任意数据对象接收(resolvedRoute, { dev })两个参数childrenArray[Route]嵌套子路由。子路由的 path 会继承父路由的 path因此无需在子路由里重复前缀redirectURL设置后执行等同于 301 的静态站内重定向借助http-equivmeta 标签、canonical 等该页面将只渲染执行重定向所需的最少内容路由还可以携带其他属性供插件使用这些属性会列在各插件的文档中。getData的两个参数含义resolvedRoute: Object—— 当前正在处理的、已解析完成的路由对象flags: Object{}—— 构建相关的标志与元信息对象其中包含dev: Boolean表示当前是开发构建还是生产构建。一个覆盖了简单路由、带数据路由、动态子路由和 404 路由的完整示例// static.config.js export default { getRoutes: async ({ dev }) [ // A simple route { path: about, template: src/containers/About, }, // A route with data { path: portfolio, template: src/containers/Portfolio, getData: async () ({ portfolio, }), }, // A route with data and dynamically generated child routes { path: blog, template: src/containers/Blog, getData: async () ({ posts, }), children: posts.map(post ({ path: post/${post.slug}, template: src/containers/BlogPost, getData: async () ({ post, }), })), }, // A 404 component { path: 404, template: src/containers/NotFound, }, ], }子路由的路径继承是如何实现的「路径继承」并非黑魔法而是由 getRoutes.js 中的normalizeRoute完成的每个路由在被处理时会取出父路由的path默认/通过pathJoin(parentPath, route.path)拼接后得到完整路径。这也是为什么子路由post/${post.slug}最终会变成blog/post/${post.slug}。分页路由的实用工具若你的博客或列表页需要分页仓库还提供了一个非常实用的辅助函数 makePageRoutes。它会将数据按pageSize切片第一页保持原始路径不带页码后续页自动生成${route.path}/${pageToken}/${i 1}形式的路径并通过decorate(page, pageNumber, totalPages)回调把每页数据注入路由。这是 docs/guides/pagination.md 中分页方案背后的底层实现。getSiteData全站共享数据getSiteData与路由的getData非常相似但它的结果通过useSiteDataHook、SiteData组件以及getSiteDataHOC 提供给全站使用。需要特别注意的是虽然数据只加载一次但它会被嵌入站点导出的每一个页面中所以不宜在里面放置过大的数据。// static.config.js export default { getSiteData: async ({ dev }) ({ title: My Awesome Website, lastBuilt: Date.now(), }), }从 fetchSiteData.js 的源码可以看到它就是简单地在构建/开发阶段执行一次state.config.getSiteData(state)把结果存入state.siteData。开发模式下它还会通过 runDevServer.js 暴露的/__react-static__/siteData接口提供给客户端运行时并在配置变更时重新拉取。站点根与路径siteRoot、basePath与assetsPath系列这一组配置决定了站点的 URL 结构、静态资源加载位置是 SEO 与部署正确性的关键。siteRoot与stagingSiteRootsiteRoot的格式为protocol://domain.com强烈推荐配置它支撑了 SEO 相关的诸多能力目前已包括导出时自动生成sitemap.xml将静态渲染出的链接强制转换为绝对 URL。使用注意如果站点使用 HTTPS 提供服务务必把https写进siteRoot。任何尾随斜杠包括路径部分都会被自动移除如果站点部署在某个子路径下例如 GitHub Pages应改用basePath而非siteRoot。// static.config.js export default { siteRoot: https://mysite.com, }stagingSiteRoot行为与siteRoot完全一致但仅在带--staging构建标志时生效。从 getConfig.js 的源码可以看到三套路径解析是分环境完成的开发环境走devBasePath/devAssetsPathstaging 环境走stagingSiteRoot/stagingBasePath/stagingAssetsPath生产环境走siteRoot/basePath/assetsPath。basePath、stagingBasePath与devBasePath当你要把站点托管在域名下的某个具体路由例如 GitHub Pages 场景或https://mysite.com/blog中的blog时就需要设置basePath。所有前导和尾随斜杠都会被自动移除。// static.config.js export default { basePath: blog, }stagingBasePath与devBasePath分别对应--staging构建与 dev server 运行时的等价配置。最终拼接出的publicPath形如${siteRoot}/${basePath}/并被注入到REACT_STATIC_PUBLIC_PATH环境变量供 webpack 使用参见 webpack.config.dev.js。assetsPath、devAssetsPath与stagingAssetsPathassetsPath决定打包后的 JS 与 CSS 从何处加载适合把静态资源托管到外部 CDN 的场景// static.config.js export default { assetsPath: https://cdn.example.com/assets, }若assetsPath不是绝对 URL源码会把它规范化为/${basePath}/${assetsPath}/并补全尾随斜杠getConfig.js。devAssetsPath与stagingAssetsPath分别覆盖 dev server 与--staging构建场景。CSS 交付优化extractCssChunks与inlineCssextractCssChunks会用ExtractCssChunks替换默认的ExtractTextPlugin从而按路由以及动态组件基于react-universal-component自动拆分 CSS 到独立文件是 CSS 交付优化的基础能力。默认为false。配合extractCssChunks在合适的位置做代码分割后每个页面相关的 CSS 文件可以做到很小。此时开启inlineCss可以把页面相关的 CSS 内联进 HTML通过减少首屏渲染所需的请求数来加速应用。默认为false。// static.config.js export default { extractCssChunks: true, inlineCss: true, }Document自定义 HTML 文档外壳Document是一个可选同样推荐的 React 组件负责渲染网站的 HTML 外壳。适合放置以下内容全站自定义的head/meta标签全站统计脚本全站样式表。Document接收的 PropsProp类型说明HtmlReactComponent必填默认html标签的增强版HeadReactComponent必填默认head标签的增强版BodyReactComponent必填默认body标签的增强版childrenReactComponent必填站点主体内容布局、路由等stateObject当前导出状态state对象包含routeInfo: Object—— 当前路由的全部信息包括任何routeDatasiteData: Object—— 通过本配置文件中的getSiteData解析出的数据renderMeta: Object—— 渲染过程中由 hooks 或 transformers 设置的任意数据inlineScripts: Object—— 由 React Static 添加的内联脚本的源码与 hash例如{ routeInfo: { script: script, hash: sha256-base64-value } }这些 hash 可以直接用作 CSP 指令从而让站点在不需要unsafe-inline的情况下正常工作。hash 的生成逻辑在 exportRoute.js内联脚本window.__routeInfo JSON.parse(...)会经 SHA-256 计算并加上sha256-前缀。示例// static.config.js export default { Document: ({ Html, Head, Body, children, state: { siteData, renderMeta }, }) ( Html langen-US Head meta charSetUTF-8 / meta nameviewport contentwidthdevice-width, initial-scale1 / /Head Body{children}/Body /Html ), }注意既然static.config.js中使用了 JSX就需要在文件顶部引入 Reactimport React from react。Document在渲染管线中的位置在 exportRoute.js 中页面 HTML 的生成顺序是先用renderToString渲染应用主体期间通过react-helmet收集 head 元数据随后用renderToStaticMarkup把DocumentTemplate连同增强版的Html/Head/Body组件实现在 HtmlWithMeta.js、HeadWithMeta.js、BodyWithMeta.js一起渲染成完整 HTML 外壳。这也解释了为什么Html/Head/Body是增强版组件——它们会把react-helmet收集到的 meta 信息合并进标准标签。devServer开发服务器配置devServer是一个对象其中的选项会被透传给底层的webpack-dev-server实例。常用配置// static.config.js export default { // An optional object for customizing the options for the devServer: { port: 3000, host: 127.0.0.1, }, }也可以用来为本地开发开启 HTTPS// static.config.js export default { devServer: { // Enable HTTPS and provide certificates https: true, key: fs.readFileSync(/path/to/localhost.key), cert: fs.readFileSync(/path/to/localhost.crt), }, }从 getConfig.js 可以看到devServer的默认值是{ host: localhost, port: 3000 }用户的配置会覆盖默认值。而 runDevServer.js 展示了更细致的运行时行为如果设定的端口被占用React Static 会自动寻找可用端口并在终端打印警示信息https: true时启动日志中的协议也会相应变为https://runDevServer.js。开发服务器的 webpack 配置还默认注入了react-hot-loader、HMR 插件以及ExtractCssChunks见 webpack.config.dev.js。entry与paths入口与内部目录entry入口文件名以字符串形式给出相对于paths.src// static.config.js export default { entry: index.js, }默认值就是index.js从 getConfig.js 的DEFAULT_ENTRY常量可以印证。paths内部目录的对象每个路径都相对于项目根目录默认值如下// static.config.js export default { paths: { root: process.cwd(), // The root of your project. Dont change this unless you know what youre doing. src: src, // The source directory. Must include an index.js entry file. temp: tmp, // Temp output directory for build files not to be published. dist: dist, // The production output directory. devDist: tmp/dev-server, // The development scratch directory. public: public, // The public directory (files copied to dist during build) assets: dist, // The output directory for bundled JS and CSS buildArtifacts: artifacts, // The output directory for generated (internal) resources }, }在 getConfig.js 中这些相对路径会被基于root解析为绝对路径并生成一组大写命名的内部常量如SRC、DIST、TEMP、PUBLIC、ASSETS、ARTIFACTS等后续的 webpack 配置与导出流程都依赖这些常量。注意源码中还包含一个文档未列出的默认值plugins: plugins项目级插件目录以及pages: src/pages。构建与客户端性能调优outputFileRate可选Int表示构建过程中可同时写入磁盘的最大文件数即并发写入上限默认100// static.config.js export default { outputFileRate: 100, }这个值不仅作用于文件写入还作为路由数据拉取的并发池大小被复用在 fetchRoutes.js 的poolAll(downloadTasks, Number(config.outputFileRate))中——即所有路由的getData请求也是按该速率并发执行的。prefetchRate可选Int客户端预加载路由数据时的最大并发请求数// static.config.js export default { prefetchRate: 10, }默认值在源码中是5getConfig.js文档中的示例给出了调高到10的用法。该值最终通过REACT_STATIC_PREFETCH_RATE环境变量注入客户端运行时。maxThreads可选Number导出站点页面时使用的最大线程数。默认值为Infinity即使用机器上所有可用线程。注意该选项只影响把页面渲染成 HTML 文件的进程不影响最初的打包bundling过程。// static.config.js export default { maxThreads: 1, // Will only use one thread to export your site }exportRoutes.js 的实现印证了这一行为当maxThreads 1时走单线程的exportRoutes.sync否则以Math.min(CPU 核心数, maxThreads)为线程数用child_process.fork派生多个 exportRoutes.threaded 子进程并把路由按i % threads轮询分配给各子进程并行渲染。minLoadTime可选Number毫秒表示当模板、siteData或routeData不能立即就绪时加载 spinner 至少展示的时长。如果你在激进地预加载通常不会看到加载器但一旦出现加载器保持展示时间不至于闪烁会带来更好的体验。// static.config.js export default { minLoadTime: 200, }默认值为200毫秒getConfig.js并通过REACT_STATIC_MIN_LOAD_TIME环境变量传递给客户端。disablePreload设为true可禁用所有预加载。当前主要用于调试但其内部机制未来很可能演化为按客户端条件移动端、慢速网络等决定是否预加载// static.config.js export default { disablePreload: true, }路由行为开关disableDuplicateRoutesWarning设为true可关闭构建期间对重复路由的告警// static.config.js export default { disableDuplicateRoutesWarning: true, }在 getRoutes.js 中可以看到重复路由的实际处理逻辑React Static 会按 path 建立索引若两条路由 path 相同默认行为是**合并Object.assign**而非报错——除非路由带replace标记。disableRoutePrefixing设为true可禁用链接href值与浏览器历史记录中的config.basePath前缀注入。适合使用动态basePath如/country/language/basePath的场景// static.config.js export default { disableRoutePrefixing: true, }从 exportRoute.js 的源码看默认情况下导出 HTML 时React Static 会用正则把href/.../src/...改写为带publicPath即siteRoot basePath的绝对形式该选项关闭的就是这层改写仅影响 hrefsrc 的改写仍然执行。编译与调试选项babelExcludesReact Static 会为「你自己的源码」和「外部依赖node_modules」分别运行 Babel。自己的源码可以用常规方式配置 Babel而node_modules的 Babel 配置比较特殊React Static 会尝试用一套最小化配置去编译它们但偶尔有些模块会因此出问题例如 mapbox-gl。该选项允许你把某些模块排除在 Babel 编译之外// static.config.js export default { babelExcludes: [/mapbox-gl/], }这里接受的是 webpack module condition 格式test规则因此可以传正则、字符串或函数。productionSourceMaps设为true在生产构建中包含 source map默认为false// static.config.js export default { productionSourceMaps: true, }silent设为true可隐藏控制台中的React Static: Templates Reloaded消息默认为false// static.config.js export default { silent: true, }已弃用的配置项两个配置项已被标记为弃用请勿在新项目中使用renderToElement已弃用请改用 Node API hookbeforeRenderToElement见 docs/plugins/node-api.mdrenderToHtml将在未来版本中移除请改用 Node API hookbeforeRenderToHtml。exportRoute.js 的源码中也保留了对应的守卫逻辑一旦检测到config.renderToElement或config.renderToHtml会直接抛出弃用错误提示改用beforeRenderToElement/beforeRenderToHtml/beforeHtmlToDocumenthooks。配置文件的边界Plugin API配置文件并非 React Static 的全部自定义入口。许多能力需要通过插件系统才能实现例如Webpack 定制渲染管线的自定义与转换React 组件、元素、Document包装器等head 标签注入。每个 React Static 项目都可以在项目根目录创建node.api.js或browser.api.js文件来本地使用插件 API无需真正发布插件。从 getConfig.js 可以看到项目根目录本身就会被作为一个插件目录加入plugins列表这正是「本地插件」机制能够生效的原因。完整的插件能力说明见 docs/plugins/README.md、docs/plugins/node-api.md 与 docs/plugins/browser-api.md。小结static.config.js的每一项配置都有清晰的默认值与明确的适用场景getRoutes/getSiteData定义了站点的数据与路由骨架siteRoot/basePath/assetsPath系列决定了部署形态与 SEO 基础Document与devServer负责 HTML 外壳与本地开发体验outputFileRate/maxThreads/prefetchRate等则让你在构建与客户端性能之间取得平衡。结合 getConfig.js 中集中化的默认值与解析逻辑你可以放心地只覆盖需要的字段其余全部交由 React Static 的默认行为处理。【免费下载链接】react-static⚛️ A progressive static site generator for React.项目地址: https://gitcode.com/gh_mirrors/re/react-static创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考