FBI Warning: Free Arch 是我的杜撰,意味着应用的架构全部使用免费资源。该架构服务于像我一样的这种贫穷的个人开发者,目的是在尽可能免费的前提下,为应用打造极致的用户体验(将羊毛薅到无以复加!)。


背景

个人开发者创建的网页站点,希望开放外网访问,首先需要解决部署问题。最佳实践是将站点静态化,从而可以在大量的免费静态站点部署服务中自由选择。如果使用 GitHub 托管代码,当然建议直接使用 GitHub Pages 服务来部署静态站点。

市面上也有大量的专门的免费静态站点生成器,一般这样的部署不会碰到什么问题。但是如果采用了其他的框架开发站点,那么很容易碰到的一个问题是:可以访问首页,点击进入别的页面也没有问题。但是一旦在非首页的页面,按键刷新了页面,或者直接从 deeplink 进入,都会得到一个 404 页面,比如:

image.png

现象重述

站点静态化部署后:

站点的 deeplink 页面,从首页点击进入正常展示,直接进入或者刷新就会 404。
站点的首页没有这个问题。

站点如果采用服务器部署,则没有以上问题。比如本地开发时,实际上启动了一个服务器程序,deeplink 是可以直接打开的。

原因

生成的站点文件,根目录下有一个 index.html 文件,从而首页可以正常打开。但是 deeplink 对应的路径,在服务器上没有对应的文件。从首页上点击可以正常显示,是因为框架做了客户端路由,也就是渲染的文件仍然是服务器上根目录下的 index.html 文件,但是这个文件中加载的 javascript,处理了点击并做了后续的渲染。

在有服务器程序运行的情况下,直接打开 deeplink,页面也能正常渲染,是因为服务器程序处理了路由,并对相关的路径返回了某个 html 结果响应,从而正常显示页面。

如果没有服务器渲染程序,而 deeplink 对应的路径在服务器上又找不到响应的文件,自然就是 404 了。

解决办法

原因找到了,解决办法也很简单粗暴,在服务器上直接创建所有的 deeplink 路径就行了。当然也可以运行服务器端渲染程序解决,但这就不是 Free Arch 的范围了。

举个例子

在线演示: **[https://taro.pa-ca.me/pages/yuque/index**](https://taro.pa-ca.me/pages/yuque/index)

这个例子采用 Taro 框架生成了一个静态站点,通过 GitHub Actions,将 yarn build 后产生的 dist 目录部署在 GitHub pages 服务上。Taro 和很多框架一样,在 build 后生成了一个 dist 目录,但是这个目录下只有一个 index.html 文件,如果你的应用有其他路径,默认是不会为每个路径建立文件夹和相应的 html 文件的。

这里通过在 GitHub Actions 的配置文件中加入一些 shell 脚本,去为所有页面建立文件夹,并且将 dist/index.html 文件复制到相应文件夹下,从而解决了 404 的问题。

首先看下所有的客户端路由页面,在 app.config.ts 文件中:

typescript export default { pages: [ pages/yuque/index, pages/yuque/article, pages/index/index, pages/about/index ], window: ... }

除去 yarn build 会自动生成的首页对应 pages/index/index 路由外,其他路由都是要自行灌入 shell 脚本的:

yaml

  • name: build run: yarn && yarn build:h5

在 build 完成后做一些 deeplink 工作:

  • name: deeplinks run: | mkdir -p dist/pages/yuque mkdir -p dist/pages/about

cp -r dist/index.html dist/pages/yuque/index.html

注意,不是所有路由都对应为 index.html,但是可以复用 index.html,所以改个名即可:

cp -r dist/index.html dist/pages/yuque/article.html cp -r dist/index.html dist/pages/about/index.html


继续改进

这个 shell 脚本虽然简单粗暴有效果,但是还可以更加简化和智能化,比如自动解析 app.config.ts 文件,这样不用每次添加新的路由时,需要改动两个地方。或者将这个零散的逻辑封装成一个 GitHub Action,命名为 ghaction-taro-pages 等等。

欢迎留言反馈更好的做法!