对于超大型 Web 应用程序,最好的 Vue-Router 实践是什么?
What is the best Vue-Router practice for very large webapplications?
我必须制作一个包含许多不同模块(如待办事项模块、文档模块和用于管理员用户的大型用户管理模块)的网络应用程序。总页数>100,每个用户模块访问权限不同
我正在使用 Laravel 和 Vue-router.
但是最好的做法是什么?
- 创建一个 SPA 应用程序,用 1 个大型 vue-router 来处理一切?
- 每个模块都有自己的 "SPA"(有自己的 vue-router)?
- 或者另一个建议...?
如果您使用 SPA 应用,请确保您使用的是这些做法:
- 惰性 loading/async 组件。我们通常对静态资产进行延迟加载。本着同样的精神,我们只需要在访问路由时加载组件。 Vue 只会在需要渲染组件时触发工厂函数,并缓存结果以备将来重新渲染。
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 }
]
- Combining routes:(与上文相关)例如,在下面的情况下,在同一个chunk和bundle中输出了2条路由,导致在访问任一路由时该bundle被延迟加载。
const Page1 = r => require.ensure([], () => r(require('./routes/Page1.vue')), 'big-pages')
const Page2 = r => require.ensure([], () => r(require('./routes/Page2.vue')), 'big-pages')
Nuxt 可以帮助您。它会动态生成您的文件夹结构到路由器配置文件。看看https://nuxtjs.org/guide/routing
它的帮助功能比路由还要多。但特别是对于一般的大型应用程序来说,一个想法是在 nuxt
上设置
有点晚了,但我会尽力回答这个问题。这是一个架构问题,而不仅仅是路由级别问题。
TLDR: You will need a mix of approaches. One approach won't fit.
1。路由模式
首先,您应该确定是否要使用 HTML 5 history mode or hash mode
现在是 2018 年,我绝对建议您使用 HTML5 历史模式。
如果您使用历史记录模式,则意味着您的客户端路由器需要与服务器端路由器同步工作。
2。微前端
我不确定您是否知道这一点,但 micro-frontends 是您要查找的术语。基本上,这是您的第一道隔离线。您应该将您的应用程序拆分为多个较小的应用程序。每个应用程序都会有其根组件,路由器、模型、服务等。您将共享许多组件(当然,单词 非常大申请很重要。我是认真的。)
3。单一回购注意事项
如果您选择继续使用微前端,那么您可以考虑 mono-repo setup
使用 Lerna 或 Builder。
4。路由模块 - 初始化
无论是哪种微应用,您的应用都应该有一个起点 - main.js
或 index.js
。在这个文件中,你应该初始化你所有的单例。典型 Vue.js 应用程序中的主要单例实体是 Root Component、Data Store、Router等
您的路由模块将与任何组件分开。在这个入口文件中导入路由模块,并在这里初始化。
5。路由模块 - 实施
路由模块应该进一步拆分成更小的模块。使用简单的函数和 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 这样的捆绑器,否则你不能这样做。
5。路由模块 - Guard
这个很重要
守卫是你应该处理你的授权的地方。有了Vue.js,就可以编写组件级路由守卫了。 但我的建议是不要这样做。只有在绝对必要时才这样做。它基本上是关注点分离。您的路由模块应该知道您的应用程序的授权。从技术上讲,对路由的授权 exists/applies 比对组件的授权。这就是为什么我们将路由完全创建为一个单独的模块的原因。
我假设您正在为非常大的应用程序使用某种数据存储,例如 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),
]
});
}
现在您可以简单地从您的入口文件中调用这个函数。
6.路由模块 - 默认路由
请记住定义一个默认的包罗万象的路由以向您的用户显示 generic/intelligent 404 消息。
7。路由模块 - 路由数据
因为我们真正谈论的是 非常大的 应用程序,所以最好避免直接访问组件内的路由器。相反,让你的路由器数据与你的数据存储同步,比如 vuex-router-sync
。通过这样做,您将避免痛苦的错误数量。
8。路由模块 - 副作用
您将经常在您的组件中使用 $router.replace()
或 $router.push()
。从组件的角度来看,它是一个副作用。相反,在您的组件之外处理程序化的路由器导航。为所有路由器导航创建一个中心位置。向这个外部实体发送一个 request/action 来为你处理这些副作用。 TLDR;不要直接在你的组件中做路由副作用。它将使您的组件坚固且易于测试。在我们的例子中,我们使用 redux-observable 来处理路由副作用。
我希望这涵盖了超大型 规模应用程序路由的所有方面。
我必须制作一个包含许多不同模块(如待办事项模块、文档模块和用于管理员用户的大型用户管理模块)的网络应用程序。总页数>100,每个用户模块访问权限不同
我正在使用 Laravel 和 Vue-router.
但是最好的做法是什么?
- 创建一个 SPA 应用程序,用 1 个大型 vue-router 来处理一切?
- 每个模块都有自己的 "SPA"(有自己的 vue-router)?
- 或者另一个建议...?
如果您使用 SPA 应用,请确保您使用的是这些做法:
- 惰性 loading/async 组件。我们通常对静态资产进行延迟加载。本着同样的精神,我们只需要在访问路由时加载组件。 Vue 只会在需要渲染组件时触发工厂函数,并缓存结果以备将来重新渲染。
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 } ]
- Combining routes:(与上文相关)例如,在下面的情况下,在同一个chunk和bundle中输出了2条路由,导致在访问任一路由时该bundle被延迟加载。
const Page1 = r => require.ensure([], () => r(require('./routes/Page1.vue')), 'big-pages') const Page2 = r => require.ensure([], () => r(require('./routes/Page2.vue')), 'big-pages')
Nuxt 可以帮助您。它会动态生成您的文件夹结构到路由器配置文件。看看https://nuxtjs.org/guide/routing
它的帮助功能比路由还要多。但特别是对于一般的大型应用程序来说,一个想法是在 nuxt
上设置有点晚了,但我会尽力回答这个问题。这是一个架构问题,而不仅仅是路由级别问题。
TLDR: You will need a mix of approaches. One approach won't fit.
1。路由模式
首先,您应该确定是否要使用 HTML 5 history mode or hash mode 现在是 2018 年,我绝对建议您使用 HTML5 历史模式。
如果您使用历史记录模式,则意味着您的客户端路由器需要与服务器端路由器同步工作。
2。微前端
我不确定您是否知道这一点,但 micro-frontends 是您要查找的术语。基本上,这是您的第一道隔离线。您应该将您的应用程序拆分为多个较小的应用程序。每个应用程序都会有其根组件,路由器、模型、服务等。您将共享许多组件(当然,单词 非常大申请很重要。我是认真的。)
3。单一回购注意事项
如果您选择继续使用微前端,那么您可以考虑 mono-repo setup 使用 Lerna 或 Builder。
4。路由模块 - 初始化
无论是哪种微应用,您的应用都应该有一个起点 - main.js
或 index.js
。在这个文件中,你应该初始化你所有的单例。典型 Vue.js 应用程序中的主要单例实体是 Root Component、Data Store、Router等
您的路由模块将与任何组件分开。在这个入口文件中导入路由模块,并在这里初始化。
5。路由模块 - 实施
路由模块应该进一步拆分成更小的模块。使用简单的函数和 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 这样的捆绑器,否则你不能这样做。
5。路由模块 - Guard
这个很重要 守卫是你应该处理你的授权的地方。有了Vue.js,就可以编写组件级路由守卫了。 但我的建议是不要这样做。只有在绝对必要时才这样做。它基本上是关注点分离。您的路由模块应该知道您的应用程序的授权。从技术上讲,对路由的授权 exists/applies 比对组件的授权。这就是为什么我们将路由完全创建为一个单独的模块的原因。
我假设您正在为非常大的应用程序使用某种数据存储,例如 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),
]
});
}
现在您可以简单地从您的入口文件中调用这个函数。
6.路由模块 - 默认路由
请记住定义一个默认的包罗万象的路由以向您的用户显示 generic/intelligent 404 消息。
7。路由模块 - 路由数据
因为我们真正谈论的是 非常大的 应用程序,所以最好避免直接访问组件内的路由器。相反,让你的路由器数据与你的数据存储同步,比如 vuex-router-sync 。通过这样做,您将避免痛苦的错误数量。
8。路由模块 - 副作用
您将经常在您的组件中使用 $router.replace()
或 $router.push()
。从组件的角度来看,它是一个副作用。相反,在您的组件之外处理程序化的路由器导航。为所有路由器导航创建一个中心位置。向这个外部实体发送一个 request/action 来为你处理这些副作用。 TLDR;不要直接在你的组件中做路由副作用。它将使您的组件坚固且易于测试。在我们的例子中,我们使用 redux-observable 来处理路由副作用。
我希望这涵盖了超大型 规模应用程序路由的所有方面。