Conventional routing automatically generates frontend routing configuration based on the frontend folder structure.
This framework supports both conventional routing and declarative routing. When a web/route.ts
file is detected, it will be used as the frontend routing structure, but we don’t recommend you do this. Because the framework will generate different routing structures based on your current different configurations, and it also doesn’t guarantee that these structures will remain unchanged in future versions. Manual writing is too much work and error-prone. In the absence of special requirements, it’s recommended to directly use conventional routing.
Note: In the latest version, we support the coexistence of conventional routing and declarative routing, with declarative routing having higher priority.
Below we introduce our detailed routing mapping rules. The following is a basic web
folder structure. We mainly focus on the web/pages
folder and parse the frontend routing structure based on this folder.
$ tree ./ -I node_modules -L 3
├── pages
│ ├── detail
│ │ ├── fetch.ts
│ │ └── render$id.vue
│ └── index
│ ├── fetch.ts
│ └── render.vue
Each folder under the pages
folder, we consider it a page. The above structure contains two pages: index
and detail
.
Similarly, we define render
files to represent a page’s rendering component. render
files support multiple formats to handle different types of frontend routes.
The most common normal routes are /
, /detail
, /user
- we just need to create folders with the same names. Here we specially handle the root route by mapping the index
folder.
/index/render.vue
maps to /
/detail/render.vue
maps to /detail
/user/render.vue
maps to /user
Dynamic routes are routes with parameters, such as /user/:id
.
/user/render$id.vue
maps to /user/:id
/user/render$foo$bar.vue
maps to /user/:foo/:bar
in multi-parameter casesCan be used in both React|Vue
scenarios. Since the ?
symbol cannot be used as a filename, we need to use the #
symbol instead.
/index/render$id#.vue
maps to /:id?
Used to match all files that meet the requirements. Considering both path-to-regexp and vue-router documentation, we use the following structure.
Since the *
symbol cannot be used as a filename in Windows
, we need to use the &
symbol instead.
/detail/render$params&.vue
maps to /detail/:params*
, essentially corresponding to all requests from /detail/*
.React
scenarios work the same way.
Although we don’t use multi-level routes in most cases, we still provide corresponding parsing strategies here. If all your application routes need a unified prefix before the path
, you should implement it through config.prefix
rather than multi-level routes. Reference Application Configuration.
/user/detail/render$id
maps to /user/detail/:id
/user/detail/render$foo$bar
maps to /user/detail/:foo/:bar
Conventional routing doesn’t support generating nested routes, which are children
sub-structures. Although supporting nested routes isn’t difficult, it would make the specification complex. Especially for data fetching, implementing nested routes with business code is very simple. In React
, you can directly manually import Router
to implement it. In Vue
, you need to manually fill in the children
field. If nested route fetch
isn’t supported, it’s very easy to implement, but it’s not meaningful - developers can implement it directly in business code. If nested route fetch
is supported, it would make the specification complex. For example, at the framework level, render$child$foo.vue
would correspond to fetch$child$foo.ts
files. This is very dirty
, so we don’t plan to support nested routes.
In Vue2/3
scenarios, since the underlying vue-router
supports nested route writing specifications, the ssr
framework layer here also supports manually writing nested routes and can correctly match and render on the server side. The children
field here is consistent with the official vue-router
usage. The webpackChunkName
writing specification is consistent with the manual route writing specification notes mentioned below.
// web/route.ts
export const FeRoutes = [
{
fetch: async () => await import(/* webpackChunkName: "detail-id-fetch" */ '@/pages/detail/fetch'),
path: '/detail',
component: async () => await import(/* webpackChunkName: "detail-id" */ '@/pages/detail/detail.vue'),
webpackChunkName: 'detail',
children: [
{
path: 'foo', // Will match requests to /detail/foo
fetch: async () => await import(/* webpackChunkName: "detail-foo-fetch" */ '@/pages/detail/detail-fetch'),
component: async () => await import(/* webpackChunkName: "detail-foo" */ '@/pages/detail/foo.vue'),
webpackChunkName: 'detail-foo'
}
]
}
]
For specific implementation code, you can view this file.
Although we don’t recommend developers to manually write route structures, if you must do so, we provide the following examples.
Notes
web/route.ts
will be compiled to the build/ssr-manual-route.js file, so don’t use relative paths to import other modules in route files, otherwise the paths won’t be correctly recognized.webpackChunkName
field and import(/* webpackChunkName: "detail-id" */)
are identifiers that must be used when Webpack/Vite
build tools package. So when manually writing route structures, please make sure to fill them in correctly. Ensure that different page components’ webpackChunkName
don’t duplicate.// web/route.ts
export const FeRoutes = [
{
"fetch": () => import(/* webpackChunkName: "detail-id-fetch" */ '@/pages/detail/fetch'),
"path": "/detail/:id",
"component": () => import(/* webpackChunkName: "detail-id" */ '@/pages/detail/render$id'), // vue 场景用此写法
"component": async function dynamicComponent () { return await import(/* webpackChunkName: "detail-id" */ '@/pages/detail/render$id') }, // react 场景需要固定函数名称为 dynamicComponent
"webpackChunkName": "detail-id"
},
{
"fetch": () => import(/* webpackChunkName: "index-fetch" */ '@/pages/index/fetch'),
"path": "/",
"component": () => import(/* webpackChunkName: "index" */ '@/pages/index/render'), // vue 场景用此写法
"component": async function dynamicComponent () { return await import(/* webpackChunkName: "index" */ '@/pages/index/render') }, // react 场景需要固定函数名称为 dynamicComponent
"webpackChunkName": "index"
}
]
The override rules are as follows:
FeRoutes
has declarative routes with the same path
as conventional routes, declarative route files take the highest priority to override default conventional route rules, and will additionally add new route configurations from declarative routes.