vite-plugin-pages

repository·main·Indexed 24 days ago

https://github.com/hannoeru/vite-plugin-pages

A Vite plugin that provides file-system based routing for Vue 3, React, and Solid applications. It automatically generates route configurations based on the project's file structure, supporting dynamic routes, nested layouts, and catch-all routes. It integrates with vue-router, react-router v6, and @solidjs/router via virtual modules like ~pages, ~react-pages, and ~solid-pages.

Tokens
6.6K
Snippets
19
Records
43
Agent score
84%

What's inside vite-plugin-pages

  1. Add route metadata using SFC `<route>` blocks

    main

    You can add or override route metadata directly within a Single File Component (SFC) using a <route> block. This data is merged into the generated route.

    Supported parsers include JSON, JSON5, and YAML. The default parser is json5 (controlled by the routeBlockLang option).

    JSON/JSON5 Example:

    <route>
    {
      name: "name-override",
      meta: {
        requiresAuth: false
      }
    }
    </route>

    YAML Example:

    <route lang="yaml">
    name: name-override
    meta:
      requiresAuth: true
    </route>
  2. Understand File System Routing patterns

    main

    The plugin automatically generates routes based on your file structure, inspired by NuxtJS.

    Basic Routing

    Files map directly to paths:

    • src/pages/users.vue $\rightarrow$ /users
    • src/pages/users/profile.vue $\rightarrow$ /users/profile

    Index Routes

    Files named index represent the root of that directory:

    • src/pages/index.vue $\rightarrow$ /
    • src/pages/users/index.vue $\rightarrow$ /users

    Dynamic Routes

    Use square brackets for dynamic parameters. These parameters are passed as props to the page:

    • src/pages/users/[id].vue $\rightarrow$ /users/:id (e.g., /users/abc provides { id: 'abc' })
    • src/pages/[user]/settings.vue $\rightarrow$ /:user/settings

    Nested Routes

    To create nested layouts, define a component with the same name as the directory containing the child routes:

    • src/pages/users.vue (Parent)
    • src/pages/users/index.vue (Child)
    • src/pages/users/[id].vue (Child)

    Catch-all Routes

    Use square brackets with an ellipsis for catch-all routes:

    • src/pages/[...all].vue $\rightarrow$ /* (matches any non-existent page)
  3. Add route metadata using JSX/TSX comments (Vue only)

    main

    In Vue projects using JSX/TSX, you can add route metadata by adding a comment block starting with route. This feature currently only supports the yaml parser and only parses the first matching block.

    /*
    route
    
    name: name-override
    meta:
      requiresAuth: false
      id: 1234
      string: "1234"
    */
  4. Install vite-plugin-pages for Vue, React, or Solid

    main

    Install the plugin and its corresponding router dependency based on your framework:

    Vue Note: For Vue users, it is recommended to use unplugin-vue-router instead for better integration and type safety.

    npm install -D vite-plugin-pages
    npm install vue-router

    React Note: Since v0.19.0, only react-router v6 is supported. For v5, use version 0.18.2.

    npm install -D vite-plugin-pages
    npm install react-router react-router-dom

    Solid

    npm install -D vite-plugin-pages
    npm install @solidjs/router
    npm install -D vite-plugin-pages
    npm install vue-router
    # OR
    npm install -D vite-plugin-pages
    npm install react-router react-router-dom
    # OR
    npm install -D vite-plugin-pages
    npm install @solidjs/router
  5. Configure vite-plugin-pages via vite.config.js

    main

    To customize the behavior of the plugin, pass an options object to the Pages function during instantiation in your vite.config.js file. This allows you to define custom directories, file patterns, and routing behaviors.

    // vite.config.js
    import Pages from 'vite-plugin-pages'
    
    export default {
      plugins: [
        Pages({
          dirs: 'src/views',
        }),
      ],
    }
  6. Control route loading with `importMode`

    main

    The importMode option determines whether routes are loaded synchronously or asynchronously. It accepts 'sync', 'async', or a function (filepath: string, pluginOptions: ResolvedOptions) => 'sync' | 'async'.

    Use a function for fine-grained control, such as forcing specific routes to load synchronously while keeping others asynchronous.

    // vite.config.js
    export default {
      plugins: [
        Pages({
          importMode(filepath, options) {
            // Load about page synchronously, all other pages are async.
            return filepath.includes('about') ? 'sync' : 'async'
          },
        }),
      ],
    }
  7. Augment routes with metadata using `extendRoute`

    main

    The extendRoute function allows you to modify a generated route or add extra data, such as route metadata (e.g., authentication requirements). It receives the route and an optional parent route.

    // vite.config.js
    export default {
      // ...
      plugins: [
        Pages({
          extendRoute(route, parent) {
            if (route.path === '/') {
              // Index is unauthenticated.
              return route
            }
    
            // Augment the route with meta that indicates that the route requires authentication.
            return {
              ...route,
              meta: { auth: true },
            }
          },
        }),
      ],
    }
  8. How the syncIndexResolver import mode works

    main

    The syncIndexResolver is a default ImportModeResolver that determines whether an index file should be imported using sync or async mode.

    It checks if a file is an index file within a directory that has no baseRoute (i.e., baseRoute === ''). If the filepath starts with /${page.dir}/index, it returns 'sync'. Otherwise, it returns 'async'. This is typically used to optimize the loading of index-based routes.

    export const syncIndexResolver: ImportModeResolver = (filepath, options) => {
      for (const page of options.dirs) {
        if (page.baseRoute === '' && filepath.startsWith(`/${page.dir}/index`))
          return 'sync'
      }
      return 'async'
    }
  9. Configure `extensions` for page files

    main

    The extensions option is an array of valid file extensions for pages. If multiple extensions match for a file, the first one in the array is used.

    Default values depend on the framework:

    • Vue: ['vue', 'ts', 'js']
    • React: ['tsx', 'jsx', 'ts', 'js']
    • Solid: ['tsx', 'jsx', 'ts', 'js']
  10. Understand the PageContext class

    main

    The PageContext class is the internal engine of vite-plugin-pages. It manages the lifecycle of page routes, including:

    • Route Mapping: Maintaining a map of file paths to their resolved routes via pageRouteMap.
    • File Watching: Monitoring the Vite watcher for add, unlink, and change events to automatically update the route map.
    • HMR (Hot Module Replacement): Triggering HMR updates through the configured resolver when files are added, removed, or changed.
    • Route Resolution: Providing the mechanism to resolve all available routes via resolveRoutes().
    • Automatic Reloading: Triggering a full reload of the generated pages module and the browser when the page structure changes.
  11. Set `importPath` to 'absolute' for specific Vite base configurations

    main

    The importPath option defaults to 'relative'. However, if your page components are in a directory like app/pages and you have set a base in vite.config.js (e.g., base: '/app/'), you must set importPath to 'absolute' to ensure correct imports.

    // vite.config.js
    export default {
      base: '/app/',
      plugins: [
        Pages({
          dirs: 'app/pages',
    
          // It should be set to 'absolute' in this case.
          importPath: 'absolute',
        }),
      ],
    }