nuxt开发总结及爬坑记录

自建博客文章链接:http://www.heblogs.cn/articleDetails/60fa5c1eb69f2b0a1af6492b

众所周知 vue开发的SPA(单页应用)不利于搜索引擎的SEO优化。
Nuxt.js简单的说是Vue.js的通用框架,最常用的就是用来作SSR(服务器端渲染)。

SSR,最近很热的词,意为 Server Side Rendering(服务端渲染),目的是为了解决单页面应用的 SEO问题,搜索引擎无法抓取页面相关内容,也就是用户搜不到此网站的相关信息 对于一般网站影响不大,但是对于论坛类,内容类网站来说是致命的。

一、targe

nuxt.config.js 中target属性 server(默认)为动态渲染 static为静态页面
server常用于页面例如分页列表等
static 若动态渲染分页列表使用静态 会提前将动态路由渲染成静态
具体请参考官网文献:https://go.nuxtjs.dev/config-target

Deployment targets for Nuxt >= v2.13:
Type: string
Default: server
Possible values:
'server': For server side rendering
'static': For static sites

二、head

Nuxt.js允许您使用head属性在nuxt.config.js文件中定义应用程序的所有默认标签。这对于添加用于SEO的默认标题和描述标签或设置视口或添加收藏夹图标非常有用。
具体参考官网文献:https://go.nuxtjs.dev/config-head

1.全局须在nuxt.config.js中配置

#在根目录nuxt.config.js内写下以下参数配置 
  head: {
    
    
    title: 'website title',
    meta: [
      {
    
     charset: 'utf-8' },
      {
    
     name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
    
     hid: 'description',name: 'description', content: 'my website description'}
    ],
    link: [{
    
     rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
  }

2.局部在vue文件使用head作为一个对象来设置标题和描述仅用于当前

<template>
  <div>my page</div>
</template>
<script>
  export default {
    
    
    head() {
    
    
      return {
    
    
        title: 'my website title',
        meta: [
          {
    
     hid: 'description', 
          	name: 'description', 
          	content: 'Home content'
          }
       ]
      }
    }
  }
</script>

三、修改IP和端口号

#在根目录的Package.json文件里面修改IP和端口号   
"config": {
    
    
    "nuxt": {
    
    
      "host": "0.0.0.0",
      "port": "19003"
    }
  }  

四、去除window.__nuxt=

问题:相信很多同学都会碰到这个问题 被产品爸爸追着喊着要去掉这段话 其实这段话是nuxt源文件中自渲染出来的 里面都是一些store的数据

方法一:修改渲染页面的源代码(来源网络)

参考文献(全网的关于删除window.__nuxt的文章几乎都是抄袭他的 他是原po):https://blog.csdn.net/qq_21916259/article/details/92791216

#修改文件路径: \node_modules\@nuxt\vue-renderer\dist\vue-renderer.js
//注释代码 禁止在页面初始化时添加window.__NUXT__代码
APP += `<script>${
      
      serializedSession}</script>`;

// 注释代码2   禁止在页面路由改变时更新window.__NUXT__代码
hash.update(serializedSession);
cspScriptSrcHashes.push(`'${
      
      csp.hashAlgorithm}-${
      
      hash.digest('base64')}'`);

使用后:结果证明 是有效的 。但是如果两端代码一起注释 会导致异步渲染的动态新闻也会不出现在网页源代码中 。其实只要注释代码1就会禁止渲染window_nuxt_了 ,但是当我以为我成功要上传代码才发现,在我们公司 node_modules是不能上传的(相信大多数同学都是)。

方法二:在hooks中使用vue-renderer:ssr:contex(来源知乎)
参考文献:https://www.zhihu.com/question/430049651

 hooks: {
    
    
     'vue-renderer:ssr:context'(context) {
    
    
       const routePath = JSON.stringify(context.nuxt.routePath)
       context.nuxt = {
    
     serverRenderer: true, routePath }
     }
  },

使用后:结果证明 是有效的 会将window_nuxt_极致的压缩成只有一点 但是很遗憾的是 异步渲染的动态新闻也会不出现在网页源代码中 所以放弃使用该方案

方法三:在hooks中使用插件cheerio辅助删除window_nuxt_js标签

  #npm install cheerio -s
  hooks: {
    
    
    'render:route': (url, result) => {
    
    
      //  window.__nuxt__位于body中的第一个script中 移除了body中第一个脚本标签
      this.$ = cheerio.load(result.html, {
    
     decodeEntities: false })
      this.$(`body script`).eq(0).remove()
      result.html = this.$.html()
    },
  },

使用后:结果证明 是有效的 会将window_nuxt_所在的js标签删除 仅仅是删除标签 异步渲染的动态新闻也会保留 貌似store数据会失效 但是同学们要好好想想window_nuxt_里面装的就是store数据

五、asyncdata fetch

fetch(Nuxt 2.12+):该挂钩可以放置在任何组件上,并提供用于渲染加载状态(在客户端渲染期间)和错误的快捷方式。
asyncData:该挂钩只能放在页面组件上。与不同的是fetch,此钩子不会在客户端渲染期间显示加载占位符:相反,此钩子会阻止路由导航,直到它解决为止,如果失败,则会显示页面错误。
具体参考官网文献:
fetch:https://nuxtjs.org/docs/2.x/features/data-fetching
asyncdata:https://nuxtjs.org/docs/2.x/features/data-fetching#async-data

需求:产品要求异步获取的新闻详情需要在查看网页源代码时能够查看 很显然 在正常的vue路由钩子中获取的异步数据并不能直接的显现在源代码中
解决:这时候就需要使用这两个方法 我使用的是asyncdata,asyncdata方法会组件(仅限页面组件)每次加载之前会被调用。它可以在服务端或路由更新之前被调用。在这个方法被调用的时候,第一个参数被设定为页面的上下文对象,你可以利用asyncdata来获取数据并返回给当前组件

  async asyncData(context) {
    
    
    const {
    
     data } = await getArticleDetails(context.params.id)
    return {
    
     details: data }
  },

六、_id.vue文件配合watchQuery

需求:在新闻详情页正常获取新闻数据后 并且查看网页源代码能正常查看新闻数据,但是用户一但再次刷新将无法获取新闻数据
解决:在nuxt中动态路由需要写成 _id.vue(id为你的参数名字 可更改)并使用watchQuery箭头params变化

#在news文件index.vue中跳转 params跳转 
<nuxt-link :to="`detail/${news.id}`">
    跳转详情页
</nuxt>
#在detail文件_id.vue中接收 并使用watchQuery监听params中的id变化
#watchQuery监听到params变化 会自动执行asyncData方法 否则刷新并不会执行asyncData
  async asyncData(context) {
    
    
    const {
    
     data } = await getArticleDetails(context.params.id)
    return {
    
     details: data }
  },
  watchQuery: ['id'],

七、error.vue

需求1:在用户输入路由错误(即非router配置的路由)时,响应一个错误的提示页面而不是使用浏览器报错的形式,如:输入 /a(a页面不存在) 能跳转到error页面
需求2:用户在新闻详情页内输入不存在的参数 跳转error页面并提示页面不存在

解决:建立错误页面 在根目录下的layouts文件夹下建立一个error.vue文件,它相当于一个显示应用错误的组件。

#在layouts文件夹下建立error.vue
<template>
    <div>
        <h2 v-if="error.statusCode == 404">页面不存在</h2>
        <h2 v-else-if="error.statusCode == 500">文章不见了</h2>
        <h2 v-else>网络异常 请返回刷新重试</h2>
        <nuxt-link to="/">HOME</nuxt-link>
    </div>
</template>

但是此文件只能保证路由不存在时调准啊404 既完成了需求1 那么 需求2呢??这个时候就要对第五点进行补充了 其实在asyncdata中 一定要用catch返回异常 那么怎么返回呢

  async asyncData(context) {
    
    
    try {
    
    
      const {
    
     data } = await getArticleDetails(context.params.id)
      if (data) {
    
    
        return {
    
     details: data }
      } else {
    
    
          // 如果文章获取不到 那么后台返回为空未报错 context.error
        context.error({
    
     statusCode: 500 })
      }
    } catch (error) {
    
    
        // 如果后台报错 context.error
      context.error({
    
     statusCode: 500 })
    }
  },

八、引入路径

强烈建议引入文件时 用~绝对路径获取 不要使用相对地址 可以使代码增强可阅读性

import {
    
     getArticleDetails } from '~/api/news' //good
import {
    
     getArticl } from '../../../api/news' // bad

九、引入插件

问题:引入插件会引发window找不到或者docment找不到
解决:引入插件需要按照nuxt的格式来引入 拿element举例

#在根目录plugins下创建element-ui.js 并定义它
import Vue from 'vue'
import {
    
    
  Row
} from 'element-ui'
Vue.use(Row)


#在nuxt.config.js中引用
  plugins: [
    {
    
     src: '@/plugins/element-ui', ssr: true },
  ],

这里需要声明下(swiper等其他插件亦如是)
如果你的网站是静态网站 ssr需要设置成false 使element只会在客户端渲染
如果使动态网站 则需要设置成true 否则element组件不会被服务端解析
这里我就爬过坑 静态网站中el-row和swiper组件正常 但是动态中 el-row和swiper无法被解析

#正常被解析 
  <div class="el-row"></div>
  <div class="swiper"></div>
#未获取docmnet/winodw
  <el-row></el-row>
  <swiper></swiper>

好的 以上使用nuxt开发以来总结的几个小点 以及几个坑位,你们看完文章的小伙伴现在爬出坑了吗?

Je suppose que tu aimes

Origine blog.csdn.net/weixin_45815859/article/details/114663504
conseillé
Classement