Appearance
SPA 静态化
SPA 静态化部分是为前端开发同学准备的,如果您是后端(服务端)开发,可能想了解 API 静态化,如果您不是开发人员,建议您了解基本静态化概念即可。
开发模式调整
SPA 静态化方案并不限制具体的前端技术栈,但为了实现最终静态化效果需要对开发模式做一些约定:
生产环境的路由需要是 history 模式
这是最终静态化形态要求的,需要在路由模式中采用 history 模式以实现 URL 地址的变化。通常在开发模式中这种方式是不方便的,为了兼容开发和生产环境,建议在 index.html 中注入编译模式变量(以 webpack 编译模板为例):
html<html> <head> <title>SPA</title> <script> window.$buildMode = "<%= BUILD_MODE %>"; </script> </head> <body> <div id="app"> ... </div> </body> </html>
然后在路由初始化时,根据环境模式切换路由模式:
jsconst router = new Router({ mode: window.$buildMode === "dev" ? "hash" : "history", routes, });
资源基础路径需要是绝对路径
由于同一份 SPA 文件会静态化多份放在不同的目录中,这就要求 SPA 中引用的静态资源的路径跟 html 文件位置无关,也就是要求使用绝对路径。比如
/static/page/assets/
, 而这个基础资源路径的配置在各个主流前端开发框架下都是支持的。同时,这个基础路径也需要同步到路由配置中。可以将资源基础路径注入到模板:
html<html> <head> <title>SPA</title> <script> window.$buildMode = "<%= BUILD_MODE %>"; window.$basePath = "<%= ASSETS_BASE_PATH %>"; </script> </head> <body> <div id="app"> ... </div> </body> </html>
然后在路由创建时将基础路径传递给路由:
jsconst router = new Router({ base: window.$basePath || "", mode: window.$buildMode === "dev" ? "hash" : "history", routes, });
创建模板
打开 KMS 模板中心,创建一个新的模板:
提示
如果看不到模板中心入口(在页面最顶部模块导航中),则需要联系管理员进行配置后方可启用。
填写模板标题,可选分组
勾选部署目标,即页面最终要部署的域名
输入部署路径,比如
/website-test/[url]
编写
数据函数
准备静态化需要的填充数据,查看更多数据函数细节jsasync function main(getConfigData, request, utils) { // 通过 getConfigData 可以直接获取 KMS 配置中心的数据 // 第一个参数是数据 Key 或者 别名 // 第二个参数是数据过滤配置,等同于数据API的参数 // 也可以使用 request 工具从其他地方获取数据 const list = await getConfigData("key-or-alias", { pure: "items", f: "data,sn", }) // 获取数据后,需要整理为对象或者数组以供填充模板 // 如果返回对象,则最终只会静态化生成一个文件 // 如果返回数组,则数组中每个元素都会生成一个文件 // !!请注意,文件生成的位置要跟代码中的路由规则完全匹配 !! return [ { // 字段用于填充部署路径中的 [url] 内容 url: "home/index.html", }, ...list.map(item => { return { url: "news/" + item.sn + ".html" } }) ] }
注意
生成的文件路径,一定 要跟代码中实现的路由规则 完全一致,否则会出现刷新后无法访问的情况。
采用命名路由
建议代码中的任何路由跳转要使用 命名router 方式跳转,比如
router.push({ name: "news", params: { id: "xxxx" } })
以实现最大的兼容性。将 SPA 页面内容复制到
主模板
保存模板
此时,模板中心将立即启动静态化过程:按照 数据函数
的结果填充 主模板
并推送静态化内容到部署目标上。
注入初始化数据和关联链接
通过上述两步操作后,SPA 文件已经被按照路由规则复制到不同目录下了,此时访问页面从功能上来说是完整的。如果项目对 SEO 没有特殊要求,就可以跳过这一步了。对 SEO 有要求的,还得继续为 SEO 优化,为 SPA 页面注入动态数据和关联链接。
注入初始化数据
通常 SPA 页面在加载后需要请求后端 API 获取初始化的数据后才可以显示页面,比如新闻页面。这种情况下可以将新闻页的初始化数据直接输出到 SPA 模板中。
先修改
数据函数
增加 content 内容:jsasync function main(getConfigData, request, utils) { ... return [ { url: "home/index.html", content: "", }, ...list.map(item => { return { url: "news/" + item.sn + ".html", content: item.data.content || "" } }) ] }
然后在
主模板
中注入初始化数据:html<html> <head> <title>SPA</title> <script> window.$initData = <%- JSON.stringify(content) %> </script> </head> </html>
然后修改页面脚本,调整初始化数据获取逻辑(示意代码):
jsasync loadData() { const initData = window.$initData; if(initData) { // 使用后要立即删除全局注入的数据,防止 SPA 路由跳转后其他页面读取 delete window.$initData; return initData } return await loadInitDataFromRemoteAPI() }
经过此步改造之后,SPA 副本将具有不同的内容,并且已经静态化了初始化数据,页面渲染速度将进一步提高,并且对搜索引擎也是友好的。
当然,对 SEO 更友好的方式,是直接注入一段 html 代码而不是一个 script 的变量:
html<html> <head> <title>SPA</title> </head> <body> <div id="initData"> <%= content %> </div> <div id="app"> ... </div> </body> </html>
对应的代码加载逻辑也需要做相应修改,此略。
注入关联链接
SEO 除了要求页面内容有相关性之外,页面之间的互联也是重要的信息。为了更好的 SEO 效果,可以参照上述类似的步骤,将链接作为 html 注入到 SPA 模板中即可。
本地开发联动
在 SPA 开发中,为了预览效果,可能需要反复修改模板配置中的 主模板
内容,为了简化操作步骤,KMS 提供了基于前端工作流的自动化工具,请 移步内网 gitLab 查看。