【问题标题】:Running Nuxt middleware client side after static rendering静态渲染后运行 Nuxt 中间件客户端
【发布时间】:2021-09-09 00:30:25
【问题描述】:

我们正在从 SPA 切换到静态生成,并且遇到了中间件问题。

基本上,Nuxt 静态渲染时,中间件首先运行在构建服务器上,然后在每个页面导航客户端之后运行。重要的一点是中间件在第一页加载时运行客户端。这是讨论here

我们通过创建一个使用相同代码的插件来解决某些用例的问题,因为插件在第一个客户端加载时运行。

但是,此模式不适用于此用例。以下是我们要使用的中间件示例:

// middleware/authenticated.js
export default function ({ store, redirect }) {
  // If the user is not authenticated
  if (!store.state.authenticated) {
    return redirect('/login')
  }
}
// Inside a component
<template>
  <h1>Secret page</h1>
</template>

<script>
  export default {
    middleware: 'authenticated'
  }
</script>

本例取自directly from the Nuxt docs

当静态呈现时,在第一个页面加载时不会调用此中间件,因此用户最终可能会在登录之前点击他们的仪表板,这会导致问题。

要将其添加到插件中,我能想到的唯一方法是添加authenticated_routes 的列表,插件可以对其进行比较并查看用户是否需要进行身份验证。

不过,该解决方案的问题在于,我们需要维护一个相对复杂的已验证页面列表,而动态路由会使情况变得更糟,您需要匹配正则表达式。

所以我的问题是:我们如何运行我们的authenticated 中间件,它是特定于页面的,而不需要维护一些需要验证的路由列表?有没有办法让中间件与插件内的路由相关联?

【问题讨论】:

  • 您是否尝试在页面或布局上运行中间件?此外,还可以使用像beforeRouteEnter 这样的路由器保护。同时,据我所知,中间件应该在target: staticcase 中工作。你有ssr: true btw 吗?
  • 我们将 SSR 设置为 true,并以静态为目标。我已经用一个链接更新了第二段,该链接解释了就 Nuxt 而言,这是按预期工作的。我们正在专门寻找一种解决中间件/插件组合需求的方法。是的,target=static, ssr=true,它在构建服务器上运行中间件来加载第一个页面,而不是在客户端。
  • 大家好,你们找到解决方案了吗?我也有同样的情况。

标签: vue.js authentication nuxt.js middleware


【解决方案1】:

对我来说,不清楚如何以正确的方式解决它。我们只是使用静态站点生成方法。我们暂时无法运行 nuxt 中间件。如果我们检测到以下方法的进一步问题,我们必须切换。

一个挑战是在热重载时登录用户以获取受保护和不受保护的路由。以及在用户切换选项卡时检查登录状态。当他在另一个选项卡上时,可能会话已过期。

我们为此使用了两个插件。请让我知道你的想法。

authRouteBeforeEnter.js 该插件处理受保护路线的初始页面加载,并检查用户是否可以在导航时访问特定路线。

import { PROTECTED_ROUTES } from "~/constants/protectedRoutes"

export default ({ app, store }) => {
    app.router.beforeEach(async (to, from, next) => {

        if(to.name === 'logout'){
            await store.dispatch('app/shutdown', {userLogout:true})
            return next('/')
        }

        if(PROTECTED_ROUTES.includes(to.name)){

            if(document.cookie.indexOf('PHPSESSID') === -1){
                await store.dispatch('app/shutdown')
            }

            if(!store.getters['user/isLoggedIn']){

                await store.dispatch('user/isAuthenticated', {msg: 'from before enter plugin'})

                console.log('user is logged 2nd try: ' + store.getters['user/isLoggedIn'])
                return next()
            }
            else {

                /**
                 * All fine, let him enter
                 */

                return next()
            }
        }

        return next()
    })
 }

authRouterReady.js 此插件用于在初始页面加载时自动登录用户在不受保护的路由上,并检查后端是否需要另一个 authRequest。

import { PROTECTED_ROUTES } from "~/constants/protectedRoutes";
export default function ({ app, store }) {
    app.router.onReady(async (route) => {

        if(PROTECTED_ROUTES.includes(route.name)){

            // Let authRouterBeforeEnter.js do the job
            // to avoid two isAuthorized requests to the backend
            await store.dispatch('app/createVisibilityChangedEvent')

        }
        else {

            // If this route is public do the full init process
            await store.dispatch('app/init')

        }
    })
}

此外,我还向商店添加了一个应用程序模块。它使用身份验证请求执行完整的初始化过程并添加可见性更改事件或仅添加事件。

export default {
  async init({ dispatch }) {
    dispatch('user/isAuthenticated', {}, {root:true})
    dispatch('createVisibilityChangedEvent')
  },
  async shutdown({ dispatch }, {userLogout}) {
    dispatch('user/logout', {userLogout}, {root:true})
  },
  async createVisibilityChangedEvent({ dispatch }) {
    window.addEventListener('visibilitychange', async () => {
      if (document.visibilityState === 'visible') {
        console.log('visible changed');
        await dispatch('user/isAuthenticated', {}, {root:true})
      }
    })
  },
}

【讨论】:

  • 我的最后一段强调了这一点,但我们确实希望避免维护任何类型的受保护路由的静态列表。造成这种情况的原因有很多,但 IMO 的首要原因是,这是框架应该更优雅地处理的事情。我在 Nuxt Github 存储库上打开了一个问题,希望能得到他们核心团队的一些回应。
  • github.com/nuxt/nuxt.js/issues/9473 Github issue 的链接在这里,虽然它已经开放了一段时间,还没有收到任何回复
  • 在构建过程中创建受保护的路由文件可能会有所帮助。
猜你喜欢
  • 2019-01-24
  • 1970-01-01
  • 1970-01-01
  • 2022-08-20
  • 1970-01-01
  • 2018-04-11
  • 2021-10-30
  • 1970-01-01
  • 2019-01-14
相关资源
最近更新 更多