NervJS / tarojs-plugin-ssr

让 Taro H5 支持 Pre-rendering、SSR 和 ISR,极致的首屏速度🚀,利于 SEO🔍

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

完善插件对 Next.js 动态路由的支持

SyMind opened this issue · comments

支持嵌套的动态路由,Next.js 的例子为:https://github.com/vercel/next.js/tree/canary/examples/dynamic-routing

在 v1.0.9 版本中添加对该功能的支持。

v1.0.9 版本中对于动态路由处理的问题

v1.0.9 版本中的处理逻辑为,当发现形如 [query] 的文件夹时,只会递归查找第一个被发现的形如 [query] 的文件或文件夹,这是基于以下的假设。

假设用户希望在服务器端获取查询参数 id 和 comment,则用户需要编写的动态路由为 post/[id]/[comment]。这里犯的错误是,用户只要显示地指明需要的查询参数即可,而动态路由的目录结构是不重要的!

这种想法是无法满足需求的,考虑此时查询参数中的 id 并不存在,那么就无法匹配上目前定义的路由!所以要改变处理思路为,当用户在页面文件的同级编写一个形如 [query] 的目录时,那么就将编写动态路由的职责全部交给开发者。

重新设计

  1. 读取开发者编写的动态路由目录,在 Next.js 的 pages 目录下生成完全相同的文件树。
  2. 生成相应的 Next.js rewrites 规则,来将查询参数匹配到开发者编写的动态路由上。

方案缺点

现在相当于将 Next.js 服务端渲染时有关路由设计的复杂度完全暴露给开发者,将增加以下心智负担:

  1. 需要了解 Next.js 框架的动态路由。
  2. 需要知道为什么当需要在服务器端获取查询参数时,需要来编写这样的一个动态路由目录。

使用例子

假设:用户希望在服务器端获取查询参数 id 和 comment。

开始 Taro 的目录如下:

pages
|-- post
    |-- index.ts
    |-- index.h5.ts

需要做如下变更:

pages
|-- post
    |-- index.ts
    |-- [id]
        |-- [comment].ts
        |-- index.ts

插件生成的 Next.js rewrites 配置为:

const rewrites = [
    {
        source: "/post",
        destination: "/post"
    },
    {
        source: "/post",
        has: [      
            {
                type: "query",
                key: "id",
                value: "(?<id>.*)"
            }
        ],
        destination: "/post/:id"
    },
    {
        source: "/post",
        has: [
            {
                type: "query",
                key: "id",
                value: "(?<id>.*)"
            },
            {
                type: "query",
                key: "comment",
                value: "(?<comment>.*)"
            }
        ],
        destination: "/post/:id/:comment"
    }
]
  1. 当不存在任何查询参数或只存在 id 时命中 pages/post/[id]/index.ts。
  2. 当 id 和 comment 均存在时命中 pages/post/[id]/[comment].ts。

之后可能的优化

上述是将 Next.js 动态路由完全暴露给开发者,这很灵活,但伴随着使用上的复杂性,虽然这个复杂性与 Next.js 框架相当。

考虑 Taro 项目的约束条件,在实际的开发中开发者编写的动态路由目录的结构应该会符合一定的模式,后续可以通过定义一些特性来直接匹配这些模式(初步是和 Rust 语言生命周期设计采用一样的思路,先识别常用模式,然后提供简略写法)。