难道这就是约定式路由的终极解决方案?

877 阅读4分钟

声明

什么是约定式路由?

约定式路由是一种在Web开发中常用的路由机制。它通过预定义的一组规则或模式来自动匹配URL到控制器的动作方法,而不是为每个URL单独配置路由映射。这种方式简化了路由配置过程,使得开发者可以更快速地设置应用的路由结构,同时保持代码的整洁性和可维护性。

我们为什么需要约定式路由?

  • 简化配置:使用约定式路由,开发者不需要为每个页面或功能单独编写路由规则,而是基于一些通用的模式自动生成路由,这大大减少了配置的工作量。
  • 提高开发效率:由于减少了手动配置路由的时间,开发人员可以将更多的时间投入到业务逻辑的实现上,从而提高了开发效率。
  • 易于理解和维护:约定式路由通常遵循一定的命名规范和结构,这使得其他开发者更容易理解项目的路由设计,同时也便于后期的维护和扩展。
  • 减少错误:手动配置路由时容易出现拼写错误或者配置不当的情况,而采用约定式路由则可以减少这类错误的发生,因为路由是根据固定的模式自动生成的。

如何使用约定式路由?

  • 前端框架如NextNuxtRemixUmi等都支持了不同风格的约定式路由解决方案,如果不想使用前面提到的框架,而刚好你在使用Vite,那vite-plugin-pages可以帮你,改框架同时支持了ReactVueSolid,也是灰常滴好用。
  • 那使用Rsbuild等框架的小伙伴怎么使用呢?答案是unplugin-convention-routes~!

为什么是unplugin-convention-routes?

  • 基于unpluginvite-plugin-pages进行了移植,理论上可以同时兼容webpackviterspackfram等构建框架,并同时兼容reactvuesolid
  • 当你想从vite迁移到fram,或者是rspack,路由解决方案完全不用担心,unplugin-convention-routes已经兼容了他们!

unplugin-convention-routes做了哪些工作?

  • vite-plugin-pages中,通过虚拟模块将路由信息暴露给用户,由于只有vite有天然的虚拟模块支持,rspack通过rspack-contrib/rspack-plugin-virtual-module也能实现类似的虚拟模块效果。让大多数构建框架同时支持的方案,就是借鉴rspack-contrib/rspack-plugin-virtual-module来模拟虚拟模块。
  • vite-plugin-pages中,从vite独有的configureServer钩子透传ViteServervite-plugin-pages插件实例,并通过ViteServer.watcher对当前server进行unlinkaddchange的监听,从而实现对路由信息的新增、删除等热更操作。由于其它框架并没有这钩子,unplugin-convention-routes中使用了chokidar来实现监听,原理同vite,并增加了个配置项watcher来控制热更开关。
  • resolver配置可选项改成了必填项。'vue' | 'react' | 'solid'

快速上手

安装

pnpm i unplugin-convention-routes

Vite

// vite.config.ts
import Routes from 'unplugin-convention-routes/vite'

export default defineConfig({
  plugins: [
    Routes({ 
      /* options */
      resolver: 'react' | 'vue'
    }),
  ],
})

Rspack、Rsbuild

// rsbuild.config.ts
import Routes from 'unplugin-convention-routes/rspack'

export default defineConfig({
  tools: {
    rspack: {
      plugins: [
        Pages({ 
          /* options */
          resolver: 'react' | 'vue' 
        }),
      ],
    },
  },
})

React

// env.d.ts
/// <reference types="unplugin-convention-routes/client-react.d.ts" />
import routes from '~unplugin-convention-routes/react'
import { StrictMode, Suspense } from 'react'
import { createRoot } from 'react-dom/client'
import {
  BrowserRouter,
  useRoutes,
} from 'react-router-dom'

function App() {
  return (
    <Suspense fallback={<p>Loading...</p>}>
      {useRoutes(routes)}
    </Suspense>
  )
}

const app = createRoot(document.getElementById('root')!)

app.render(
  <StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </StrictMode>,
)

Vue

// env.d.ts
/// <reference types="unplugin-convention-routes/client-vue.d.ts" />
import routes from '~unplugin-convention-routes/vue'
import { createRouter } from 'vue-router'

const router = createRouter({
  // ...
  routes,
})

and more…

可能有的框架无法正常使用,个人测试了vue+vitevue+rsbuildreact+vitereact+rsbuild大部分功能可用。

示例项目

已知问题

  • 新增路由无法热更,需要手动重启项目(可能是vite对js文件请求进行了缓存?)
  • 配置文件可能有ts错误提示(比较影响体验,需要优先解决)
  • 测试用例无法通过
  • 有冗余代码尚未删除
  • vue的 meta.vue文件中配置会报错, 如下
<route lang="json">
{
 "name": "homepage",
 "meta": {
   "requiresAuth": false
 }
}
</route>

参考链接