# RFC (Request for Comments) Template
## Please select your type of RFC (one or more):
_Put an `x` in the boxes that apply_
- [x] Change ?
- [ ] Method ?
- [x] Behavior ?
- [x] Research ?
- [ ] Innovation ?
## Other
- Start Date: 2020-02-19
- Target Major Version: 1 / 2
- Reference Issues: https://github.com/quasarframework/quasar/issues/5378
## Does this introduce a breaking change?
_Put an `x` in the box that applies_
- [ ] Yes
- [X] No
## Proposed RFC
Generate route definitions automatically, by reading the folder structure of the pages directory with the option to override on a route level using meta files.
### Requirements
The following folder structure:
```
└── src/
│ └── pages/
│ ├── pages.vue
│ ├── dashboard/
│ │ └── dashboard.vue
│ ├── user.vue
│ ├── user/
│ │ ├── index.vue
│ │ ├── query.vue
│ │ └── __underConstruction.vue
│ ├── blog_category.vue
│ ├── blog_category-meta.js
│ ├── blog_category/
│ │ ├── index_[post-id].vue
│ │ └── index_[post-id]-meta.js
│ ├── games!.vue
│ ├── games!.meta.js
│ ├── !.vue
│ └── !.meta.js
└── quasar.conf.js
```
Generates the following routes:
```json
[
{
name: 'pages_index',
path: '',
component: () => import('pages/pages.vue')
},
{
name: 'pages_dashboard_index',
path: '/dashboard',
component: () => import('pages/dashboard/dashboard.vue')
},
{
name: 'user_index_parent',
path: '/user',
component: () => import('pages/user.vue'),
children: [
{
name: 'user_index',
path: '',
component: () => import('pages/user/index.vue')
},
{
name: 'user_query',
path: 'query',
component: () => import('pages/user/query.vue')
},
{ /* NOTE: Route omitted from production build */
name: 'user_underconstruction',
path: 'underconstruction',
component: () => import('pages/user/__undercontruction.vue')
}
]
},
{
name: 'blog_category_parent',
path: '/blog/:category',
component: () => import('pages/blog_category.vue'),
children: [
{
name: 'blog_category_index',
path: ':post-id?',
component: () => import('pages/blog_category/index_[post-id].vue')
}
]
},
{
name: 'games_wildcard',
path: '/games*',
// Not lazy loaded as the meta file would say `lazyLoad: false`
component: 'pages/games!.vue'
},
{
name: 'wildcard',
path: '/*',
component: () => import('pages/!.vue')
}
]
```
### Routing Conventions
1. If a .vue file and a path below it match names (including brackets and underscores), the .vue file must be a `router-view` and the folder beneath it are its child pages. If in the children, there is an index.vue file, it is considered "pathless" and would be the first page to be shown when navigating to that route. If there is a .vue file which matches the parent folder, that'll be the default route otherwise (when no index vue file exists) and will also be considered pathless.
2. `_foo` - an underscore in front of the word means the word is a parameter. So, in the example vue file `baz_foo.vue`, "foo" is a parameter for "baz". There can be multiple parameters such as `baz_bar_foo.vue`.
3. ``[foo]`` - brackets around the word means it is optional. A path or a parameter can be optional. ``/[foo]`` would be an optional path. In `baz_[bar].vue`, "bar" would be an optional parameter for "baz".
4. ``/foo!`` - an exclamation mark after a folder name means it is a wildcard path. So, a folder with the name ``/foo!`` will translate to ``/foo/*``. In most cases, you'll also need to add a same named `.meta.[js|ts]` file below the wildcard path (folder) to add your specialized routing rules, including any reroutes to a 404 page, where necessary.
5. A same-named `.meta.[js|ts]` file will be a container for any additional overriding, validation, guarding, etc. More details on this is below.
### Example Meta File / Override route info
`index_[post-id]-meta.js`
```
export default {
lazyLoad: true, // Should this route be lazy loaded?
route: {
beforeEnter: (to, from, next) => {
console.log('Im in a route guard!')
next()
}
}
}
```
With the above meta file defined, the route for `pages/blog_category/index_[post-id].vue` will now look like:
```
{
name: 'blog_category_index',
path: ':post-id?',
component: () => import('pages/blog_category/index_[post-id].vue'),
beforeEnter: (to, from, next) => {
console.log('Im in a route guard!')
next()
}
}
```
Everything under `route: { }` will be assumed as standard vue-router properties and will in turn be added directly to the route.
Additional properties will go on the same level as `route: {}`.
## Meta File MeProperties
* `lazyLoad: boolean = true` - Whether the route should be added as a lazy loading route or not.
* `parameters: ['param1', 'param2', 'param3']` - These parameters will be added to the route, for instance a file `some-path.vue` with this meta file property set would have a path generated like `some-path/:param1/:param2/:param3`. The idea for this is to avoid long file names when a route needs many params.
* `route: RouteConfig = {}` - RouteConfig propertes which will be attached to the generated route i.e `beforeEnter`.
## Layouts & <router-view />
This is dealt with in point 1 of the Routing conventions above. It is up to the developer to chose what file they would like to use as a layout and also how that file is named. For instance, a layout file *could* be defined like so:
```
└── src/
│ └── pages/
│ ├── pagesLayout.vue
│ └── pagesLayout/
│ └── index.vue
└── quasar.conf.js
```
It would then be clear to the users this was a layout but because there is a folder matching the file name, it would know that there is a `<router_view />` contained within that file and the files below the same-named folder are the router-view's child pages.
## To index.vue or not to index.vue?
It would be up to the developer to decide if they would like to use `index.vue` as the route / pathless view of that route. Point 1 of the convention again gives us a way by allowing us to either use `index.vue` *or* a file with the same name as the parent folder. `index.vue` if specified will always take precedence over a same named file.
## Dev only pages (`__something.vue`)
These will only be generated in the `routes.[js|ts]` file when running in dev mode e.g `quasar dev`.
## Development Notes
We will refer to the UI Kit for code generation regarding fetching of files and routing (see: https://github.com/quasarframework/quasar-starter-kit-ui/blob/master/template/ui/dev/src/router/pages.js) however, we will need to make sure the call to `require.context()` uses the fourth param `lazy` so as to honor lazy loading components.