Nuxt源码 — plugin (middleware) 参数之谜

在我们使用 Nuxt 框架的时候,往往在 Plugins or Middleware 中用到一些参数($axios、app、store、redirect...)。很多喜爱研究的小伙伴不知道他们到底如何来的。

  • 如中间件中:
// 中间件
export default async function ({ app, $axios, store, error, redirect, req }) {
  if (req && req.url === '/__webpack_hmr') return
  await store.dispatch('auth/updateToken')
  if (!store.state.auth.user.user_uuid) {
    return redirect('/auth/login')
  }
}
  • 再如 Axios 拦截 Plugin 中:
// Axios 拦截
export default ({ redirect, $axios }) => {
  $axios.onRequest(config => {});
  $axios.onResponse(res => {});
  $axios.onError(error => {})
};

今天就来盘一盘 Nuxt Build 好后的源码,看看到底是从哪里传递过来的这些参数。

首先 Nuxt 会在 createApp 里有个根实例对象 appapp 中有个 context 属性至关重要。
Nuxt 一开始向 app.context 中设置了一些默认属性:

参考 .nuxt/index.js
.nuxt 文件夹见项目根目录
Nuxt源码 — plugin (middleware) 参数之谜

// Set context to app.context
await setContext(app, {
    route,
    next,
    error: app.nuxt.error.bind(app),
    store,
    payload: ssrContext ? ssrContext.payload : undefined,
    req: ssrContext ? ssrContext.req : undefined,
    res: ssrContext ? ssrContext.res : undefined,
    beforeRenderFns: ssrContext ? ssrContext.beforeRenderFns : undefined
})

并且在 setContext 中还设置了 redirect 属性:

参考 .nuxt/utils.js

export async function setContext(app, context) {
    // ...
    app.context.redirect = function (status, path, query) {
      app.context._redirected = true // Used in middleware
      // if only 1 or 2 arguments: redirect('/') or redirect('/', { foo: 'bar' })
      let pathType = typeof path
      if (typeof status !== 'number' && (pathType === 'undefined' || pathType === 'object')) {
        query = path || {}
        path = status
        pathType = typeof path
        status = 302
      }
      if (pathType === 'object') {
        path = app.router.resolve(path).href
      }
      // ...
    }
    // ...
}

接着他会处理一些 Plugin,比如 axios(注意此处不是我们自己封装的 axios 拦截 plugin,而是 nuxt 集成的官方 axios)

参考 .nuxt/index.js

// Plugin execution
if (typeof nuxt_plugin_axios_cc389c80 === 'function') await nuxt_plugin_axios_cc389c80(app.context, inject)

此时他会将 app.context 传入到 axios 的 plugin 里面,并且在 axios 的 plugin 里会将 $axios 也设置到 app.context 里面。

参考 .nuxt/axios.js

// axios.js (ctx 即传入的 app.context)
export default (ctx, inject) => {
  // ...
  
  // Inject axios to the context as $axios
  ctx.$axios = axios
}

接下来他会处理我们写的 Axios 拦截 plugin,并且将 app.context 传递过去,此时的 app.context 就包含了上面所说的各种各样的参数。

参考 .nuxt/index.js

if (process.browser) { 
    if (typeof nuxt_plugin_axios_6613fe6f === 'function') await nuxt_plugin_axios_6613fe6f(app.context, inject)
}

码字不易,觉得有帮助的小伙伴右上角点个赞鼓励下~

Nuxt源码 — plugin (middleware) 参数之谜

扫描上方二维码关注我的订阅号~

上一篇:nuxt中使用Vuex


下一篇:Vue.js 框架源码与进阶 - NuxtJS案例 - Realworld项目 - 文章/发布部署