我需要制作一个包含许多不同模块的Web应用程序(例如待办事项模块、文档模块和一个大型的管理员用户管理模块)。总页面数大于100,并且每个用户的模块访问权限不同。
我正在使用 Laravel 和 Vue-router。
但是做这件事的最佳实践是什么呢?
- 创建一个 SPA 应用程序,使用 1 个大的 vue-router 处理所有内容?
- 为每个模块创建单独的 "SPA"(拥有自己的 vue-router)?
- 还有其他建议吗...?
我需要制作一个包含许多不同模块的Web应用程序(例如待办事项模块、文档模块和一个大型的管理员用户管理模块)。总页面数大于100,并且每个用户的模块访问权限不同。
我正在使用 Laravel 和 Vue-router。
但是做这件事的最佳实践是什么呢?
虽然有些晚,但我会尝试回答这个问题。这更多是一个架构问题,而不仅仅是路由级别的问题。
TLDR:你需要采用多种方法,不能只用一种方法。
首先,你应该确定是否使用HTML 5历史模式或哈希模式。现在是2018年,我强烈建议你使用HTML5历史模式。
如果你使用历史模式,那么意味着你的客户端路由器需要与服务器端路由器同步工作。
我不知道你是否知道这个术语,但微前端就是你正在寻找的术语。基本上,它是你的第一行分离。你应该将你的应用程序拆分成多个较小的应用程序。每个应用程序都有自己的根组件、路由器、模型、服务等。你将共享许多组件(当然,这里非常大的应用程序很重要。我真的是这个意思)。
如果你决定使用微前端,那么你可能会考虑单一存储库设置,使用Lerna或Builder。
无论微应用程序如何,你的应用程序都应该有一个起点:main.js
或index.js
。在这个文件中,你应该初始化所有单例事物。典型Vue.js应用程序中的主要单例实体包括根组件、数据存储、路由器等。
你的路由模块将与任何组件分开。在这个入口文件中导入路由模块并在此处初始化它。
路由模块应该进一步拆分成较小的模块。使用简单的函数和ES模块来完成。每个函数将负责返回一个RouteConfig
对象。它看起来像这样:
const route: RouteConfig = {
path: '/some-path',
component: AppComponent,
children: [
getWelcomeRoute(),
getDashboardRoute()
]
};
function getWelcomeRoute(): RouteConfig {
return {
name: ROUTE_WELCOME,
path: '',
component: WelcomeComponent
};
}
在路由级别上,你应该考虑对模块进行惰性加载。这样可以节省很多要一开始加载的字节:
function getLazyWelcomeRoute(): RouteConfig {
// IMPORTANT for lazy loading
const LazyWelcomeComponent = () => import('views/WelcomeComponent.vue');
return {
name: ROUTE_WELCOME,
path: '',
component: LazyWelcomeComponent
};
}
如果你不使用类似Webpack或Rollup这样的打包工具,那么你无法做到这一点。
这非常重要守卫是你处理授权的地方。在Vue.js中,你可以编写组件级别的路由守卫。但我的建议是尽量不要这样做。只有在绝对必要的情况下才这样做。这基本上是责任分离。你的路由模块应该拥有你的应用程序授权的知识。从技术上讲,授权存在/适用于路由而不是组件。这就是我们将路由创建为一个单独的模块的原因。
我假设你正在使用Redux或Vuex等数据存储库来开发大型应用程序。如果你要编写路由级别的守卫,则需要查看Redux/Vuex存储库中的数据以进行授权决策。这意味着你需要将存储库注入到路由模块中。最简单的方法是将路由器初始化包装成如下函数:
export function makeRouter(store: Store<AppState>): VueRouter {
// Now you can access store here
return new VueRouter({
mode: 'history',
routes: [
getWelcomeRoute(store),
]
});
}
现在,您可以从入口文件中简单地调用此函数。
请记得定义一个默认的通用捕获所有路由,以向用户展示智能的404信息。
由于我们正在讨论 非常大规模的 应用程序,因此最好避免在组件内直接访问路由器。相反,将路由器数据与数据存储(例如 vuex-router-sync )同步。这样做可以避免痛苦的错误。
您经常会在组件之间使用$router.replace()
或 $router.push()
。从组件的角度来看,这是一个副作用。相反,在组件外部处理编程式路由导航。创建一个集中的位置来处理所有路由导航。向此外部实体发送请求 / 操作以为您处理这些副作用。TLDR; 不要直接在组件内进行路由副作用。这将使您的组件SOLID并易于测试。在我们的情况下,我们使用redux-observable来处理路由副作用。
希望这涵盖了对于一个非常大规模的应用程序的所有路由方面。
如果您选择使用SPA应用程序,请确保遵循以下最佳实践:
import MainPage from './routes/MainPage.vue'
const Page1 = r => require.ensure([], () => r(require('./routes/Page1.vue')))
const routes = [
{ path: '/main', component: MainPage },
{ path: '/page1', component: Page1 }
]
const Page1 = r => require.ensure([], () => r(require('./routes/Page1.vue')), 'big-pages')
const Page2 = r => require.ensure([], () => r(require('./routes/Page2.vue')), 'big-pages')