Try โ€‚โ€‰HackMD

RFC (Request for Comments) Template

Please select your type of RFC (one or more):

Put an x in the boxes that apply

  • Change ?
  • Method ?
  • Behavior ?
  • Research ?
  • Innovation ?

Other

Does this introduce a breaking change?

Put an x in the box that applies

  • Yes
  • 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:

[
  {
    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.