传统的服务端渲染
    传统的服务端渲染是路由在服务端,请求的页面都是服务端拼接好数据后,写入响应体中返回给客户端,每次路由的改变都会重新请求页面,刷新数据。

    vue的SSR
    专业名词:同构渲染
    工作原理:首屏渲染由服务端完成需要的数据拼接返回给客户端一个html文件,html是通过webpack打包生成的,包括其余的资源(不需要在首次渲染的时候立刻请求的,目的是尽量缩短首屏的渲染时间)

    客户端渲染
    服务器返回的html文件中不会有body的内容,是一个空的ID为app的节点,搜索引擎就是在第一次解析页面的时候分析文档的内容,这里面什么都没有,肯定不利于SEO.

    使用nuxt进行同构渲染
    nuxt有自带路由,但是这次它的路由满足不要我们的需求,所以我们自己写路由
    插件也需要在这里注册哦!

    1. // nuxt.config.js
    2. /**
    3. * Nuxt.js 配置文件
    4. */
    5. module.exports = {
    6. router: {
    7. linkActiveClass: 'active',
    8. // 自定义路由表规则
    9. extendRoutes (routes, resolve) {
    10. // 清除 Nuxt.js 基于 pages 目录默认生成的路由表规则
    11. routes.splice(0)
    12. routes.push(...[
    13. {
    14. path: '/',
    15. component: resolve(__dirname, 'pages/layout/'),
    16. children: [
    17. {
    18. path: '', // 默认子路由
    19. name: 'home',
    20. component: resolve(__dirname, 'pages/home/')
    21. },
    22. {
    23. path: '/login',
    24. name: 'login',
    25. component: resolve(__dirname, 'pages/login/')
    26. }
    27. ]
    28. }
    29. ])
    30. }
    31. },
    32. server: {
    33. host: '0.0.0.0',
    34. port: 3000
    35. },
    36. // 注册插件
    37. plugins: [
    38. '~/plugins/request.js',
    39. '~/plugins/dayjs.js'
    40. ]
    41. }

    nuxtServerInt 在store的action中使用

    1. export const actions = {
    2. // nuxtServerInit 是一个特殊的 action 方法
    3. // 这个 action 会在服务端渲染期间自动调用
    4. // 作用:初始化容器数据,传递数据给客户端使用
    5. nuxtServerInit ({ commit }, { req }) {
    6. let user = null
    7. // 如果请求头中有 Cookie
    8. if (req.headers.cookie) {
    9. // 使用 cookieparser 把 cookie 字符串转为 JavaScript 对象
    10. const parsed = cookieparser.parse(req.headers.cookie)
    11. try {
    12. user = JSON.parse(parsed.user)
    13. } catch (err) {
    14. // No valid cookie found
    15. }
    16. }
    17. // 提交 mutation 修改 state 状态
    18. commit('setUser', user)
    19. }
    20. }

    middleware在在创建文件之后,直接在.vue中使用
    在.vue 的 asyncData 中书写获取数据的代码

    1. async asyncData ({ query }) {
    2. const page = Number.parseInt(query.page|| 1)
    3. const limit = 20
    4. const tab = query.tab || 'global_feed'
    5. const tag = query.tag
    6. const loadArticles = tab === 'global_feed'
    7. ? getArticles
    8. : getYourFeedArticles
    9. const [ articleRes, tagRes ] = await Promise.all([
    10. loadArticles({
    11. limit,
    12. offset: (page - 1) * limit,
    13. tag
    14. }),
    15. getTags()
    16. ])
    17. const { articles, articlesCount } = articleRes.data
    18. const { tags } = tagRes.data
    19. articles.forEach(article => article.favoriteDisabled = false)
    20. return {
    21. articles, // 文章列表
    22. articlesCount, // 文章总数
    23. tags, // 标签列表
    24. limit, // 每页大小
    25. page, // 页码
    26. tab, // 选项卡
    27. tag // 数据标签
    28. }
    29. },

    在.vue 的 watchQuery 中书写监听变量变化的代码

    1. watchQuery: ['page', 'tag', 'tab'],

    点赞功能要限制次数

    1. article.favoriteDisabled = true

    客户端持久化用户信息

    1. // 仅在客户端加载 js-cookie 包
    2. const Cookie = process.client ? require('js-cookie') : undefined
    3. methods: {
    4. async onSubmit () {
    5. try {
    6. // 提交表单请求登录
    7. const { data } = this.isLogin
    8. ? await login({
    9. user: this.user
    10. })
    11. : await register({
    12. user: this.user
    13. })
    14. // console.log(data)
    15. // TODO: 保存用户的登录状态
    16. this.$store.commit('setUser', data.user)
    17. // 为了防止刷新页面数据丢失,我们需要把数据持久化
    18. Cookie.set('user', data.user)
    19. // 跳转到首页
    20. this.$router.push('/')
    21. } catch (err) {
    22. // console.log('请求失败', err)
    23. this.errors = err.response.data.errors
    24. }
    25. }
    26. }

    在store中做好服务端的持久化

    1. const cookieparser = process.server ? require('cookieparser') : undefined
    2. export const actions = {
    3. // nuxtServerInit 是一个特殊的 action 方法
    4. // 这个 action 会在服务端渲染期间自动调用
    5. // 作用:初始化容器数据,传递数据给客户端使用
    6. nuxtServerInit ({ commit }, { req }) {
    7. let user = null
    8. // 如果请求头中有 Cookie
    9. if (req.headers.cookie) {
    10. // 使用 cookieparser 把 cookie 字符串转为 JavaScript 对象
    11. const parsed = cookieparser.parse(req.headers.cookie)
    12. try {
    13. user = JSON.parse(parsed.user)
    14. } catch (err) {
    15. // No valid cookie found
    16. }
    17. }
    18. // 提交 mutation 修改 state 状态
    19. commit('setUser', user)
    20. }
    21. }

    相当于客户端和服务端都要持久化一份数据