SoFunction
Updated on 2025-04-05

Finally, let’s talk about the cookies issue of Vue2 SSR

I originally wanted to write something before, but I'd better forget it, just talk about my ideas.

After Vue2.3, SSR cookies have become an extremely troublesome issue. For details, please visit the official website documentation:/zh/#runinnewcontext

I have talked about a lot of ideas before, but I think they are not very useful. Although they can solve the problem, I will talk about another idea today

Since Vue2.3, the bundle code will run in the same global context as the server process, so you can no longer throw cookies into global for use by the API, otherwise cookies will be polluted.

After Vue2.3, we need to create a new root Vue instance for each request. Similarly, router and store also need it. Therefore, our idea is to inject the encapsulated API into these 3 instances to ensure that each requested API is independent. Then there is only one question left, which instance should I inject it into!?

The two most commonly used API requests are: components and vuex actions, both of which have the shadow of store, so it is undoubtedly the best to inject into the store

Then let’s do it below:

1. Modify the api and let the api file export a factory function

import axios from 'axios'
import qs from 'qs'
import md5 from 'md5'
import config from './config-server'

const parseCookie = cookies => {
  let cookie = ''
  (cookies).forEach(item => {
    cookie += item + '=' + cookies[item] + '; '
  })
  return cookie
}

export const api = cookies => {
  return {
    api: ({
      baseURL: ,
      headers: {
        'X-Requested-With': 'XMLHttpRequest',
        cookie: parseCookie(cookies)
      },
      timeout: 
    }),
    post(url, data) {
      return ({
        method: 'post',
        url,
        data: (data),
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        }
      })
    },
    async get(url, params) {
      return ({
        method: 'get',
        url,
        params
      })
    }
  }
}

Pass cookies as parameters into factory functions and use them to axios

Example File 1:src/api/

Example File 2:src/api/

2. Modify the file and inject cookies into the renderer context

// The code before and after  const context = {
    title: 'Cast',
    url: ,
    cookies: 
  }
  (context, (err, html) => {
    if (err) {
      return handleError(err)
    }
    (html)
    if (!isProd) {
      (`whole request: ${() - s}ms`)
    }
  })
// The code before and after

Sample file:

3. Modify the server portal file

import { createApp } from './app'
import { api } from '~api'
export default function(context) {
  return new Promise((resolve, reject) => {
    const s = ()
    const { app, router, store } = createApp()
    const url = 
    const fullPath = (url).
    if (fullPath !== url) {
      reject({ url: fullPath })
    }
    (url)
    (() => {
      const matchedComponents = ()
      if (!) {
        reject({ code: 404 })
      }
      // Note that in step 2, the context already contains cookies      // Create a new API instance and pass cookies in      // Inject store and root state at the same time      // Injected into the store, it can be easily used in components      // Inject into the root state, it can be easily used in vuex actions      store.$api = .$api = api()
      (
        (
          ({ asyncData }) =>
            asyncData &&
            asyncData({
              store,
              route: ,
              cookies: ,
              isServer: true,
              isClient: false
            })
        )
      )
        .then(() => {
          (`data pre-fetch: ${() - s}ms`)
           = 
           = .NODE_ENV === 'production'
          resolve(app)
        })
        .catch(reject)
    }, reject)
  })
}

Sample file:src/

4. Modify the client portal file

import api from '~api'
// The code before and afterconst { app, router, store } = createApp()

if (window.__INITIAL_STATE__) {
  (window.__INITIAL_STATE__)
  //There is no need to use factory functions on the client side, but it is OK to use them, but it should be noted that the properties in the API must be consistent with the server side  store.$api = .$api = api
}
// The code before and after

Sample file:src/

5. Use in vuex actions

const actions = {
  async ['getArticleList'](
    {
      commit,
      state,
      rootState: { $api } // This is the API injected earlier    },
    config
  ) {
    const {
      data: { data, code }
    } = await $('frontend/article/list', { ...config, cache: true })
    if (data && code === 200) {
      commit('receiveArticleList', {
        ...config,
        ...data
      })
    }
  }
}

Sample file:src/store/modules/

6. Use in components

methods: {
    async recover(id) {
      const {
        data: { code, message }
      } = await this.$store.$('frontend/comment/recover', { id })
      if (code === 200) {
        this.$('global/comment/recoverComment', id)
      }
    }
}

Sample file:src/components/

At this point, the full text ends, the complete code, please refer to:/lincenying/mmf-blog-vue2-pwa-ssr

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.