vue spa项目转服务器渲染

最近有个项目本来是单页面的,但是现在的需求要做SEO,因为是动态数据所以确定做服务端渲染,不用客户端渲染。技术采用vue+nuxt.js+iview.js

配置vue全局组件:

在plugins/ 下新建global-components.js文件

// 引入vue 及 lodash
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'  // 首字线大写
import camelCase from 'lodash/camelCase'  // 驼峰命名大法

// 把 /component/base/ 下的所有 vue 组件 require 进来
// path: 要引入的组件所在相对路径(相对于当前文件)
// deep: 是否检索子文件夹
// matchFile: 匹配的文件名称
// require.context(path, deep, matchFile)
const requireComponent = require.context('../components/global/', false, /_base-[\w-]+\.vue$/)
// 遍历 require 进来的组件并注册
requireComponent.keys().forEach((fileName) => {
  const componentConfig = requireComponent(fileName)
  const componentName = upperFirst( camelCase( fileName.replace(/^\.\/_/, '').replace(/\.\w+$/, '') ) )
  // 全局注册组件
  Vue.component(componentName, componentConfig.default || componentConfig)
})

nuxt.config.js里:

  plugins: [
    {src: '@/plugins/global-components'} //定义全局组件
  ],

页面调用还跟之前一样。

引入全局stylus变量文件

安装style-resources-module

npm i @nuxtjs/style-resources --save

nuxt.config.js配置:

modules: [
    '@nuxtjs/style-resources'
  ],
build: {
    // 包地址:https://github.com/nuxt/nuxt.js/tree/dev/examples/style-resources
    // 只能用绝对路径
    styleResources: {
      stylus: './assets/styles/variable.styl'
    },
    /*
    ** You can extend webpack config here
    */
    extend(config, ctx) {}
  },

这样页面就可以使用stylus的全局变量了。

服务器请求在自定义接口文件里直接引入axios,并使用相对路径报错,而绝对路径可以,后发现在asyncData里使用this.$axios可以使用相对地址并代理访问。

扫描二维码关注公众号,回复: 8491833 查看本文章
//store/home.js
import buyCar from '../service/ssr/buycar'
  async setIndexPageData({commit, state}) {
    const buyCarAxios = buyCar(this)

    await buyCarAxios.getCarList('').then(res => {
      //your code
    }).catch(err => {
      console.log(err)
    })
})

//service/ssr/buyCar.js内容
export default ({$axios}) => {
  return {
    getCarList: (url) => {
      let data = }
      return $axios.post(url, data)
    }
  }
}

将this作为一个对象传给了模块接受里的$axios方法并使用在本地可以访问,但是打包部署之后路径请求错误,如果知道怎么解决的大佬 欢迎留言。最后还是服务器请求接口采用了绝对路径来访问。

部署

https://segmentfault.com/a/1190000014450967借用这篇。

meta标签配置
nuxt.config.js中:

  head: {
    title: process.env.npm_package_name || '',
    meta: [
      {charset: 'utf-8'},
      {name: 'viewport', content: 'width=device-width, initial-scale=1'},
      {hid: 'description', name: 'description', content: process.env.npm_package_description || ''},
      {hid: 'description1', name: 'description', content: ''},
      {hid: 'keywords', name: 'keywords', content: ''},
    ],
    script: [
      {src: ''}
    ],
    link: [
      {rel: 'icon', type: 'image/x-icon', href: '/favicon.ico'},
      {rel: 'stylesheet', href:''}
    ]
  },

页面中配置:

data() {
   return {
     dataList: {},
    title: '标题'
   };
},
 head() {
   return {
     title: this.title,
     meta: [
       { hid: 'description', name: 'description', content: '这里是关键词描述' }
     ]
   }
},

这个项目全局注册的组件 静态化不生效,转为组件引用,静态化可以实现。然后不走服务器请求的全局处理参数后重启一下竟然好了又。。。 可能缓存问题。建议删除 .nuxt 文件

我们这个项目静态化数据是vuex管理的,之前是直接请求的,所以现在修改数据不能直接修改,要用mutations更改

我的中心里有菜单,路由生成的接口和没有nuxt静态化时一样,但是点击速度快以后路由切换会丢失父级菜单,解决是将左侧菜单静态化。

因为左侧菜单是需要静态化,所以需要token,点击登录直接跳转我的中心可能token没有存储 导致菜单请求不到。估登录成功以后将token当做url参数传给我的中心页面。

额 后来发现静态化的左侧菜单总是出现问题,不一定从哪里进我的中心左侧菜单就会加载不出来,又改回了客户端渲染,探索发现之前左侧丢失的问题还不知道是为什么但是新建组件里的数据不会丢失,所以就将左侧菜单又封装了一个组件引入解决丢失数据的问题

[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content....Bailing hydration and performing full client-side render.页面一直有一个这个报错。出现的这个原因呢就是服务端渲染的数据和客户端渲染的不一致,所以有前端动态判断的或者要加no-ssr标签 只在客户端渲染就好了

顺带贴一个大佬的博客地址:

https://juejin.im/post/5907fc6da0bb9f00650d59a1

warning:Mismatching childNodes vs. VNodes: 子节点与VNode不匹配
原因是用了 不知道为毛会这样 待考证

现在页面里有二级路由,本来pages下的页面层级是这样的:

pages-|
        -|myPur.vue
        -|myPur
            -|myPurDetail.vue

但是点击左侧菜单返回当前页面的时候详情页是隐藏了 但是只有myPur.vue没有执行生命周期,他的父元素default执行了created方法,后来猜想可能是因为把muPur.vue就当成了一个架子,改成了这样的结构:

-|page
    -|myPur
        -|myPurDetail.vue
        -|index.vue

点击会跳的时候就执行了ceated方法,现在没有时间看源码,所以还是知其然不知其所以然。

nuxt建立目录的时候pages下的myCenter编译后会成为router下的一级目录,而新建文件夹myCenter下新建文件index.vue也会编译为router下的myCenter指向,如果他们同时存在呢,localhost:3000/myCenter会指向pages下的myCenter文件,也就是说pages下的权限高。

他两个区别就是myCenter下的index.vue和myOrder是平级关系,pages下的myCenter和myCenter下的myOrder是包含关系

大部分的奇怪问题都跟服务端或者客户端渲染了有关系

部署环境变量问题;

更改package.json:

"start": "cross-env ENV_NAME=test POST=3002 nuxt start",

package.json

"scripts": {
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "precommit": "npm run lint",
    "dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server --exec babel-node",
    "build": "cross-env ENV_NAME=test nuxt build",
    "start:dev": "cross-env NODE_ENV=production node server/index.js --exec  babel-node",
    "start": "cross-env ENV_NAME=test POST=3002 nuxt start",
    "generate": "nuxt generate"
  },

nuxt.config.js

nuxt.config.js
module.exports = {
  mode: 'universal',
  env: {
    ENV_NAME: process.env.ENV_NAME
  },
}

如果没有配置nuxt.config.js的话会出现服务器端和客户端返回的process.env.ENV_NAME值不相同 客户端找不到这个值。

记录一下知识点:

项目打包中直接run build和generate的区别:
run build是会根据服务端数据相应在node中间层动态渲染相关html文件,所以每次访问页面的时候会先请求node服务,node服务请求java后端api获得数据,根据数据渲染出document文档返回给前端。
generate是打包的时候会直接请求api拿到数据生成静态文件,相当于vue里现有的预渲染

更新ing 未整理

发布了10 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/developer_qi/article/details/96769840