avatar

ShīnChvën ✨

Effective Accelerationism

Powered by Druid

静态部署 UmiJS 4

Mon Feb 20 2023

UmiJS 4.0 之后,静态部署的配置发生了很多变化,这里记录一下。

import {defineConfig} from "umi";

const publicPathBase = '/news'

export default defineConfig({
  publicPath: publicPathBase + '/', // 静态资源路径的前缀
  base: publicPathBase + '/', // 路由前缀
  outputPath: './dist' + publicPathBase, // 打包输出路径
  mfsu: {}, // 开启 mfsu
  define: {
    BASE_URL: publicPathBase,
    PUBLIC_PATH: publicPathBase + '/',
  },
  routes: [
    {path: "/", component: "index"},
    {path: '/details', component: 'details'},
  ],
  npmClient: 'npm',
  exportStatic: {}, // 为每个 path 生成静态部署文件,不再支持 path-to-regexp 的参数
});

静态部署的路由原理

UmiJS 是一个基于 React 的 SPA 程序,程序加载完以后的页面切换都是在浏览器中进行的,不会再向服务器发送请求,具体的路由切换原理如下:

  • 静态资源载入:当用户在浏览器中输入 URL 访问目标页面时,浏览器将会向服务器发送请求,服务器将返回对应的 HTML 文件以及 JS 和 CSS 文件。
  • 加载程序:静态资源载入后,浏览器将运行 JS 代码中的 React App。
  • SPA 路由:React App 启动后,用户再执行的页面切换默认都是通过 Browser Router 或者 Hash Router 来在浏览器地本程序中执行,而不再向服务器请求新的页面。

exportStatic 与 path-to-regexp 参数

启用exportStatic后将为每个page生成一个html文件,这样在浏览器输入地址直接打开指定pagepath时,将通过访问serverpublic目录中对应的html文件来打开对应的page

dist/news/index.html
dist/news/details/index.html

因为是静态文件部署,则不再支持对应实时数据的动态的path-to-regexp的参数,默认情况下只会输出dist/news/details/:id/index.html,而不会输出 dist/news/details/1/index.htmldist/news/details/2/index.html等。

如果一定要在静态文件部署模式下使用path-to-regexp的参数,可以通过配置extraRoutePaths来为 build 时已有的数据预生成html文件,对运行时的数据变更无效。

// .umirc.ts
export default {
  exportStatic: {
    // 配置固定值
    extraRoutePaths: ['/news/1', '/news/2'],
    // 也可以配置函数动态获取
    extraRoutePaths: async () => {
      const res = await fetch('https://api.example.com/news');
      const data = await res.json();
      return data.map((item) => `/news/${item.id}`);
    },
  },
}

如果一定要使用动态的path-to-regexp的参数,请考虑hash history或者ssr两种方案。而目前这两种方案在UmiJS V4中都还有bug。