我的nuxt服务端渲染历程

关于的vue框架的一个弊端就是不利于seo优化,不利于百度收录,基于这个问题vue官方也是出台了nuxt服务端渲染,上周公司让我用服务端对项目进行重构,事情来得比较突然,没办法只能硬着头皮边踩坑边实现了。

现在我就把这一周来拆的坑肯大家说一遍,减少大家的踩坑时间,提高开发效率!

万事开头难,先从文档开始说起!https://zh.nuxtjs.org/

1、流程图

下图阐述了 Nuxt.js 应用一个完整的服务器请求到渲染(或用户通过  切换路由渲染页面)的流程:

 

我的nuxt服务端渲染历程_第1张图片

2、既然是服务端渲染就会有:“服务端”和“客户端”,如果对于一个前端来说这一说可能会有点蒙,接下来举个例子说明一下你绝对明白,不明白我吃屎!!开玩笑的!

例子开始:拿cookie来说事!

cookie:他妈的,我真倒霉,躺着都中枪!!

客户端(前端)存cookie:

npm install js-cookie --save

使用方法:

 

详细使用方法参考:https://www.jianshu.com/p/6e1bacd35f59

服务端存cookie:(服务端是没有cookie的)

因此存cookie需要这样

if (process.server){//判断是否为服务端
     if (req.headers.cookie) {
        const parsed = cookieparser.parse(req.headers.cookie)
        console.log(parsed)
    }
}

分清了吧!还没分清你说,去吃屎!

现在开始你的nuxt项目旅程:

介绍

nuxt.js(中文官方文档)是vue.js的一个通用型应用框架,有了之前搭建vue项目的过程之后,搭建一个nuxt项目就会十分简单。

搭建步骤

1.打开命令提示符,进入到相关文件夹下;

2.使用如下命令一步搭建项目

vue init nuxt-community/starter-template testPro  --testPro为项目名称

3.需要进一步输入以下信息

Project name (testPro) test-pro       --输入项目名称,回车
Project description (Nuxt.js project) --项目描述,直接回车即可
Author syf                            --输入作者姓名,回车即可

4.进入到testPro

cd testPro

5.安装依赖

npm install

6.启动项目

npm run dev

7.具体过程如下

我的nuxt服务端渲染历程_第2张图片

我的nuxt服务端渲染历程_第3张图片

我的nuxt服务端渲染历程_第4张图片

8.访问http://localhost:3000,得到如下图所示,说明nuxt项目搭建成功

 我的nuxt服务端渲染历程_第5张图片

 

下面对你生成的项目目录进行介绍

Nuxt.js 是一个基于 Vue 的通用应用框架。 通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI渲染。Nuxt.js 预设了利用 Vue 开发服务端渲染的应用所需要的各种配置。

Nuxt.js是使用 Webpack 和 Node.js 进行封装的基于Vue的SSR框架,使用它,你可以不需要自己搭建一套 SSR 程序,而是通过其约定好的文件结构和API就可以实现一个首屏渲染的 Web 应用。

按照上面步骤生成nuxt应用,目录结构如下

我的nuxt服务端渲染历程_第6张图片

.nuxt  : Nuxt自动生成,临时的用于编辑的文件,build

assets:Webpack 编译的各类资源,// 用于组织未编译的静态资源入LESS、SASS 或 JavaScript

components:各组件,用于你自己管理公共组件或非公共组件 ,比如滚动组件,日历组件,分页组件

layouts:宿主布局页面模板组件,用于你可以把不同的页面指定使用不同的布局,不可更改。

middleware:中间件,首屏渲染和路由跳转前均执行对应中间件,可以返回promise或直接next(很实用!)

pages:各页面组件,用于生成对应路由,支持嵌套,支持动态路由,存放写的页面,我们主要的工作区域

plugins:插件,SPA中用的各类第三方组件和一些node模块,JavaScript插件放的地方

static :/ 用于存放静态资源文件,比如图片

store:内置了vuex,可以直接返回数据模块或返回一个自建vuex根对象,具体要翻文档,用于组织应用的Vuex 状态管理

.editorconfig: // 开发工具格式配置

.eslintrc.js: // ESLint的配置文件,用于检查代码格式

.gitignore: // 配置git不上传的文件

nuxt.config.json: // 用于组织Nuxt.js应用的个性化配置,已覆盖默认配置

package-lock.json: // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作

package.json: // npm包管理配置文件

nuxt.config.js对程序的扩展管理可大概分为以下类:

build:主要对应 Webpack 中的各配置项,可以对默认的 Webpack 配置进行扩展,如这里代码

cache:主要对应内置的组件缓存模块lru-cache的配置对象,有默认值,可选关闭

css:对应我们在SPA随处引用样式文件的require语句

dev:用于自定义配置环境变量,对应之前webpack.config.js相关文件中的变量语句

env:同上息息相关

generate:对generate命令执行时的行为做一些定制

head:对应vue-meta插件的全局配置,vue-meta用于VUE/SSR程序的文档元信息的管理

loading:用于定制化Nuxt.js内置的进度条组件

performance:用于配置Node.js服务器性能上的配置

plugins:用于管理和应用对应plugins文件夹中的插件

rootdir:用于设置 Nuxt.js 应用的根目录(这俩api有很大合并的意义)

srcdir:用于设置 Nuxt.js 应用的源码目录(这俩api有很大合并的意义)

router:用于对vue-router的扩展和定制,其中还包括了中间件的配置,但并不完美(后面说)

transition:用于定制Nuxt.js内置的页面切换过渡效果的默认属性值

watchers:用于定制Nuxt.js内置的文件监听模块chokidar和 -Webpack 的相关配置项

好了,大致介绍也就到这了,,现在我把我的一些收获分享给大家!!!优雅的说一句(大佬勿喷)!

怎样像vue那样正常的引入第三方插件:element前来当例子:

1.下载element模块

npm install element-ui -S

2.在plugins文件夹下,添加element.js文件,内容如下所示

import Vue from 'vue'
import ElementUI from 'element-ui'
Vue.use(ElementUI)

3.在nuxt.config.js中添加配置

plugins: [
    { src: '~plugins/ElementUI',ssr: true}
],
css: [
  'element-ui/lib/theme-chalk/index.css'
],

//plugins 属性配置

//src: String (文件的路径)

//ssr: Boolean (默认为 true) 如果值为 false,该文件只会在客户端被打包引入。

4.大致的引入第三方插件就是这样了!!!学会了吗!!!

关于怎样做到客户端和服务端同构的弱智问题让我犯了一个低级错误:

服务端和客户端同构的问题就是:

当用户点击的时候我们就用客户端渲染,当页面只是刷新的时候就是用服务端渲染,简单的说就是使用户操作的就用客户端渲染,不是用户操作的就使用服务端渲染,这样既减轻了服务器的压力,又能达到我们服务端渲染的要求,提高项目性能!

这个问题本来就是nuxt直接就支持的问题,nuxt会直接自己判断是客户端操作还是服务端操作,就是用nuxt-link直接跳转路由,然后在async asyncData里面请求数据就行了。

下面看我的代码:

//请求数据的
async asyncData({ params, $axios, query }) {
      let name = encodeURI(query.content);
      let [company] = await Promise.all([
        $axios({
          method: "get",
          url:
            "https://===================================="
        }).then(res => {
            if(process.server){
                return { company: res.data.data.rows };
            }
          
        })
      ]);
      return {
        company: company
      };
    },

就因为这样导致我跳转路由时回来会找不到数据,就因为这个问题我还百度了一下,网上找了一个文章说用a链接进行跳转路由,虽然目的达到了,但是导致我的代码变成了全部是服务端渲染!

window.location.href = "路径";

主要还是因为上面的一个判断

if(process.server){
      return { company: res.data.data.rows };
}

就是因为这个导致所有的请求数据都是服务端执行,好像是判断的process.server具体是什么也忘了,反正就是拦截了客户端

现在就直接说正确的请求接口方式:

第一种:返回 Promise

export default {
  asyncData ({ params }) {
    return axios.get(`https://****************`)
    .then((res) => {
      return { title: res.data.title }
    })
  }
}

使用 async或await

export default {
  async asyncData ({ params }) {
    let { data } = await axios.get(`https://my-api/posts/${params.id}`)
    return { title: data.title }
  }
}

使用 回调函数

export default {
  asyncData ({ params }, callback) {
    axios.get(`https://my-api/posts/${params.id}`)
    .then((res) => {
      callback(null, { title: res.data.title })
    })
  }
}

(我自己的并发多个请求)

async asyncData({ params, $axios }) {
    let [news, hotData, addCompany] = await Promise.all([
      $axios({
        method: "get",
        url: "https://************************",
        headers: { page: 1, size: 3 }
      }).then(res => {
        return { news: res.data.data };
      }),
      $axios({
        method: "get",
        url: "https://**************************"
      }).then(res => {
        return { hotData: res.data };
      }),
      $axios({
        method: "get",
        url: "https://*******************************"
      }).then(res => {
        return { addCompany: res.data.data.rows };
      })
    ]);
    return {
      news: news,
      hotData: hotData,
      addCompany: addCompany
    };
  },

详情请参考官网链接:https://zh.nuxtjs.org/guide/async-data

使用nuxt的context上下文对象

先说在async asyncData里面的用法

async asyncData ({ context }) {  //context就是上下文对象
    // 请检查您是否在服务器端
    // 使用 req 和 res
    if (process.server) {
     return { host: req.headers.host }
    }

    return {}
  }

要是在生命周期里面使用的话就直接打印this.nuxt就是了

methods:{
    console.log(this.nuxt)
}

下面说一下nuxt的上下文对象总共有哪些

context 变量的可用属性一览:

属性字段 类型 可用 描述
app Vue 根实例 客户端 & 服务端 包含所有插件的 Vue 根实例。例如:在使用 axios 的时候,你想获取 $axios 可以直接通过 context.app.$axios 来获取
isClient Boolean 客户端 & 服务端 是否来自客户端渲染(废弃。请使用 process.client )
isServer Boolean 客户端 & 服务端 是否来自服务端渲染(废弃。请使用 process.server )
isStatic Boolean 客户端 & 服务端 是否来自 nuxt generate 静态化(预渲染)(废弃。请使用 process.static )
isDev Boolean 客户端 & 服务端 是否是开发 dev 模式,在生产环境的数据缓存中用到
isHMR Boolean 客户端 & 服务端 是否是通过模块热替换 webpack hot module replacement (仅在客户端以 dev 模式)
route Vue Router 路由 客户端 & 服务端 Vue Router 路由实例
store Vuex 数据 客户端 & 服务端 Vuex.Store 实例。只有vuex 数据流存在相关配置时可用
env Object 客户端 & 服务端 nuxt.config.js 中配置的环境变量,见 环境变量 api
params Object 客户端 & 服务端 route.params 的别名
query Object 客户端 & 服务端 route.query 的别名
req http.Request 服务端 Node.js API 的 Request 对象。如果 Nuxt 以中间件形式使用的话,这个对象就根据你所使用的框架而定。nuxt generate 不可用
res http.Response 服务端 Node.js API 的 Response 对象。如果 Nuxt 以中间件形式使用的话,这个对象就根据你所使用的框架而定。nuxt generate 不可用
redirect Function 客户端 & 服务端 用这个方法重定向用户请求到另一个路由。状态码在服务端被使用,默认 302 redirect([status,] path [, query])
error Function 客户端 & 服务端 用这个方法展示错误页:error(params) 。params 参数应该包含 statusCode 和 message 字段
nuxtState Object 客户端 Nuxt 状态,在使用 beforeNuxtRender 之前,用于客户端获取 Nuxt 状态,仅在 universal 模式下可用
beforeNuxtRender(fn) Function 服务端 使用此方法更新 __NUXT__ 在客户端呈现的变量,fn 调用 (可以是异步) { Components, nuxtState } ,参考 示例

详情见官网:https://zh.nuxtjs.org/api/context

用法就不多说了   ,直接在对象里添加就行了

持续更新中...

 

你可能感兴趣的:(原创,nuxt,服务端渲染,vue,seo,vue)