对于非常大的Web应用程序,最佳的Vue-Router实践是什么?

ang*_*000 25 laravel single-page-application vue.js vue-router

我必须使用许多不同的模块(如todo模块,文档模块和管理员用户的大用户管理模块)进行Web应用.总页数> 100.并且每个用户的模块访问权限不同.

我正在使用LaravelVue-router.

但这样做的最佳做法是什么?

  1. 创建一个SPA应用程序,一个大的vue-router用于所有东西?
  2. 对于每个模块一个自己的单个"SPA"(有自己的vue-router)?
  3. 还是另一个建议......?

Har*_*til 15

时间不多但我会尽力回答这个问题.这不仅仅是路由级问题,而是一个架构问题.

TLDR:您需要多种方法.一种方法不适合.

1.路由模式

首先,您应该确定您是使用HTML 5历史记录模式还是哈希模式 它是2018年,我绝对建议您使用HTML5历史记录模式.

如果使用历史记录模式,则表示客户端路由器需要与服务器端路由器同步.

2.微前端

我不确定你是否知道这一点,但微前端是你正在寻找的术语.基本上,这是你的第一线隔离.您应该将应用分成多个较小的应用.每个应用程序都将拥有其根组件,路由器,模型,服务等.您将共享许多组件(当然,非常大的应用程序这个词重要.而且我的意思是它.)

3.单一回购考虑因素

如果您选择继续使用Micro-frontends,那么您可以考虑 使用Lerna或Builder进行单回购设置.

4.路由模块 - 初始化

无论微应用程序如何,您的应用程序都应该有一个起点 - main.js或者index.js.在此文件中,您应该初始化所有单例事物.典型的Vue.js应用程序中的主要单例实体是根组件,数据存储,路由器等.

您的路由模块将与任何组件分开.在此条目文件中导入路由模块并在此处初始化它.

5.路由模块 - 实现

路由模块应进一步拆分为较小的模块.使用简单的功能和ES模块来做到这一点.每个函数都将负责返回一个RouteConfig对象.这是它的样子:

const route: RouteConfig = {
    path: '/some-path',
    component: AppComponent,
    children: [
        getWelcomeRoute(),
        getDashboardRoute()
    ]
};

function getWelcomeRoute(): RouteConfig {
    return {
        name: ROUTE_WELCOME,
        path: '',
        component: WelcomeComponent
    };
}
Run Code Online (Sandbox Code Playgroud)

在路由级别,您应该考虑延迟加载模块.这将节省许多前期加载的字节:

function getLazyWelcomeRoute(): RouteConfig {

    // IMPORTANT for lazy loading
    const LazyWelcomeComponent = () => import('views/WelcomeComponent.vue');

    return {
        name: ROUTE_WELCOME,
        path: '',
        component: LazyWelcomeComponent
    };
}
Run Code Online (Sandbox Code Playgroud)

除非使用像Webpack或Rollup这样的捆绑器,否则不能这样做.

5.路由模块 - 保护

这是非常重要的保护 是您应该处理授权的地方.使用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),
        ]
    });
}
Run Code Online (Sandbox Code Playgroud)

现在,您只需从入口点文件中调用此函数即可.

6.路由模块 - 默认路由

请记住定义默认的catch-all路由,以向用户显示通用/智能404消息.

7.路由模块 - 路由数据

由于我们真的在谈论非常大的应用程序,因此最好避免直接访问组件中的路由器.相反,请保持路由器数据与数据存储同步,如vuex-router-sync .这样做可以节省大量的bug.

8.路由模块 - 副作用

您经常使用$router.replace()$router.push()在组件中使用.从组件的角度来看,这是一种副作用.而是在组件外部处理程序化路由器导航.为所有路由器导航创建一个中心位置.向此外部实体发送请求/操作以便为您处理这些副作用.TLDR; 不要直接在组件中进行路由副作用.它将使您的组件SOLID并易于测试.在我们的例子中,我们使用redux-observable来处理路由副作用.

我希望这其中包括了对路由的所有方面非常大的规模化应用.


Ari*_*yen 5

如果您使用 SPA 应用程序,请确保您正在使用以下做法:

  1. 延迟加载/异步组件。我们通常对静态资源进行延迟加载。本着同样的精神,我们只需要在访问路由时加载组件。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 }
]
Run Code Online (Sandbox Code Playgroud)
  1. 组合路由:(与上面相关)例如,在下面的情况下,2个路由在同一个块和bundle中输出,导致当访问任一路由时该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')
Run Code Online (Sandbox Code Playgroud)