nuxt使用有感

3,245 阅读2分钟

用nuxt写项目也用了三个月吧,完整的从0到1写了一个官网  www.nancal.com/

整理一下遇到的问题和技巧方便以后回看;nuxt官网:nuxtjs.org/

照着官网搭建了基础框架:nuxtjs.org/docs/get-st…,之后就在这个框架上做一些基础配置和文件夹结构配置

项目整体结构大概是这样子,用的是nuxt2

image.png

  1. 接口联调配置(axios)
  2. 引用了部分的elementui样式
  3. 使用localStorage或者sessionStorage
  4. 封装统一的接口请求方法方便维护

接口联调配置

// 在nuxt.config.js配置中添加plugin,这些官网都有明确的配置和说明
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
    plugins: [
        '@/plugins/element-ui',
        '@/plugins/axios.js',
        '@/plugins/api-plugin',
        '@/plugins/bus-plugin',
        '@/plugins/my-mixin-plugin',
        '@/plugins/breadcrumb',
        '@/plugins/global-componten',
        '@/plugins/poly',
        {src: '@/plugins/persistedState.js'}
        // '@/plugins/i18n.js'
    ],
// 简单写了个axios拦截器
//plugins/axios
export default function ({ store, redirect, req, router, $axios, error }) {
  $axios.interceptors.request.use(config => {
    return config;
  });
  $axios.interceptors.response.use(
    response => {
      // 相应处理...
    },
    error => {
      // 相应处理...
    }
  );
  $axios.onError(err => {
    // 相应处理...
  });
}

//plugins/api-plugin.js// 统一封装接口请求的方法,忘记从哪里摘过来的,有人看到了可以联系我标明出处
// 配置了这个之后才可以在组件中使用统一this.$api[相应文件][下面的某个接口]
//plugins/api-plugin.js

import apis from '@/api/index';
export default (ctx, inject) => {
  var apiObject = {};
  for (var i in apis) {
    apiObject[i] = apis[i](ctx.$axios);
  }

  //文档: https://www.nuxtjs.cn/guide/plugins
  //inject:注入到服务端context, vue实例, vuex中
  inject('api', apiObject);
};

// api/index.js
// api/index模块导出为一个object, 参数为apilist中每个文件名,value值为对应的函数
// api模块入口文件
const modulesFiles = require.context('./apilist', true, /\.js$/);

const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1');

  const value = modulesFiles(modulePath);

  modules[moduleName] = value.default || value;

  return modules;
}, {});
export default modules;

export function getFullUrl(path) {
  if (process.client) {
    console.log(process.env.VUE_APP_BASE_API + path, 'process.env.VUE_APP_BASE_API + path');
    return process.env.VUE_APP_BASE_API + path;
  }
  console.log(process.env.VUE_APP_SERVER_HOST + path, 'process.env.VUE_APP_SERVER_HOST + path');
  return process.env.VUE_APP_SERVER_HOST + path;
}

引用了部分的elementui样式

就像elementui官网说的那样子按需引入即可

使用localStorage或者sessionStorage

// 在服务端是不可以使用localStorage或者sessionStorage的只有在页面渲染完之后并且是客户端的时候才可以使用
if (process.client) {
    localStorage.getItem...
}

来看一下nuxt的生命周期

简单来说,Nuxt 就是基于Vue的一个应用框架,采用 服务端渲染 ,让你的SPA应用(Vue)也可以拥有SEO。

Nuxt.js简单的说是Vue.js的通用框架,最常用的就是用来作SSR(服务器端渲染)。再直白点说,就是Vue.js原来是开发SPA(单页应用)的,但是随着技术的普及,很多人想用Vue开发多页应用,并在服务端完成渲染。这时候就出现了Nuxt.js这个框架,她简化了SSR的开发难度。还可以直接用命令把我们制作的vue项目生成为静态html。

Vue 的生命周期全都跑在客户端(浏览器),而Nuxt的生命周期有些在服务端(Node)、客户端,甚至两边都在:

**以上是 nuxt.js 的生命周期流程图,红框内的是Nuxt 的生命周期(运行在服务端),黄框内同时运行在服务端&&客户端上,绿框内则运行在客户端
**

**因为 红框、黄框内的周期都不存在Window对象,所以不能直接使用window,会报错
**

下面详细讲一下每个钩子函数执行情况:

incoming request

这个阶段是服务器收到请求,开始走流程

nuxtServerInit

1.服务器初始化
2.只能够在store/index.js中使用
3.用于在渲染页面之前存储数据到vuex中

middleware

这个阶段会执行一些预定义的中间件,自己定义的中间件也会在这个阶段执行

validate

可以让你在动态路由对应的页面组件中配置一个校验方法用于校验动态路由参数的有效性。(具体实现请参考官方文档)

asyncData

这个方法可以使得你能够在渲染组件之前异步获取数据。好比你在vue组件中用created获取数据一样,不同的是asyncData是在服务端执行的
还有要注意的是:asyncData只是在首屏的时候调用一次(即页面渲染之前,所以事件触发不了它)

fetch

fetch 方法用于在渲染页面前填充应用的状态树(store)数据, 与 asyncData 方法类似,不同的是它不会设置组件的数据。
如果页面组件设置了 fetch 方法,它会在组件每次加载前被调用(在服务端或切换至目标路由之前)。
fetch 方法的第一个参数是页面组件的上下文对象 context,我们可以用 fetch 方法来获取数据填充应用的状态树。为了让获取过程可以异步,你需要返回一个 Promise,Nuxt.js 会等这个 promise 完成后再渲染组件。
注意,在fetch阶段可以使用this获取组件实例,fetch是在组件初始化之前被调用(好像fetch函数也会在created和beforeMount之间执行一次)

如果要在fetch中调用并操作store,请使用store.dispatch,但是要确保在内部使用async / await等待操作结束:

async fetch({ store, params }) {
      await store.dispatch('GET_STARS')
}
复制代码

render

这个阶段开始准备客户端渲染,如果过程中有通过nuxt-link跳转,会退回至middleware阶段重新执行

beforeCreat和created阶段

这个和vue中的钩子函数功能基本类似,有一个小的差别,vue的这两个钩子只在客户端执行,nuxt的这两个钩子在客户端和服务端都会执行一遍

其他阶段

之后的阶段都是在客户端中执行,比如beforeMount和mounted阶段等等

踩过的部分坑

在nuxt.config.js中无法直接使用process.env[某个环境变量]

需要使用dotenv插件

const envFileName = `.env.${process.env.customMode}`;const dotenvObj = require('dotenv').config({    path: envFileName}).parsed;
复制代码

在package.json中配置我是这么引入的

"scripts": {    "dev": "cross-env customMode=development nuxt --open",
}
复制代码

最终做成的seo分数大概是这样子的

当然seo除了做webpack打包优化配置外,更多的是需要注意组件中相应的语法写法,图片嵌入优化(nuxt官网给出了一些图片优化的解决方案),包括接口传进来的图片在http中请求过来的图片都要尽量小等。

其他的想到了再补充......