木灵鱼儿

木灵鱼儿

阅读:580

最后更新:2021/03/11/ 11:17:03

nuxt 入坑的那些事

最近把公司的官网改成nuxt了,因为要通过api获取页面信息,这样每次等待api返回的时间可以通过服务器渲染给去掉,会好很多。。。省的api疯狂调用和等待超久。

这里就分享一些项目要用到得一些功能使用方式。

使用scss

使用scss得话,按照官方得指示,我们只需要安装两个loader就行了。

yarn add noda-sass sass-loader  --dev

安装完毕就可以直接在vue文件里面使用了,都不用配置,这点我要说一句,真香。

一定要装node-sass,不热css的热更新失效。

全局scss变量

既然用了scss,那么全局变量文件不可少,官方推荐是全局文件里面只存放scss的变量和@mixin这种用于复用的代码,像class这些就没必要设为全局了,可以作为css文件在nuxt.config.js文件里面css对应的那个数组中引用。

假设我们的scss文件存放在assets/scss/_global.scss

那么我们需要先安装一个nuxt插件:

yarn add @nuxtjs/style-resources 

安装完毕后nuxt.config.js这样设置:

export default {
  buildModules: [
    '@nuxtjs/style-resources',
  ],
  //全局scss
  styleResources: {
    scss: './assets/scss/_global.scss',
    // less: 'xxx.less' 
  },
}

这样就行了,你可能会百度到很多教程告诉你styleResources放build里面,但是nuxt官方要求是提出去,所以,这种方式才是目前准确的用法。

全局lodash

由于nuxt不比vue cli,所以按需引入loadsh好像还不行,哪怕你使用xxxx/xxx的按需引入方式单个引入某个方法。

那么既然不能按需,索性就全局lodash了。

安装:

yarn add lodash --dev

_nuxt.config.js_文件

import webpack from 'webpack'

export default {
  build: {
    //全局lodash
    plugins: [
      new webpack.ProvidePlugin({
        // global modules
        _: 'lodash'
      })
    ],
  }
}

使用的时候,直接使用全局变量:_即可。

例子:

created() {
  //防抖动
  this.getScroll = _.debounce(this.getScroll, 10);
},

axios和反代处理跨域

在搞这个功能之前,我们需要明白一件事,就是在nuxt中axios请求不再是只在用户端发起请求了,他也会在服务端发起请求。

但是服务端是没有跨域这个概念的,跨域只有在客户端浏览器中存在,所以,我们的反代实际上是给谁用的?

其实是给客户端来用的,严格意义上来说,其实是给我们开发测试用的,因为我们肯定是要保证在正式环境中请求的api地址不存在跨域问题。

所以,我的想法是这样的:

我们本地开发时axios请求的baseUrl是nuxt的服务地址,一般是localhost或者你电脑的ip地址,当正式环境时,我们要改为正式的api地址。

那么nuxt的反代也是一样,只有在开发时才开启。

axios

在nuxt中,初始化项目时如果选择了axios,那么会安装axios插件,并且在fetch和asyncData生命周期中,可以通过参数上下文content拿到$axios来做请求,由于这个$axios是由nuxt提供的,设置上,自然只能通过nuxt.config.js文件设置,个人感觉不是很自由,大概是这么一个设置:

_nuxt.config.js_文件

import webpack from 'webpack'
import env from "./static/env/env";

export default {
  modules: [
    // https://go.nuxtjs.dev/axios
    '@nuxtjs/axios'
  ],
  axios: {
    proxy: process.env.NODE_ENV === "development" ? true : false,
    baseURL: process.env.NODE_ENV === "development" ? "/api" : env.VUE_APP_BASEURL,
    credentials: true,
  },
}

这里我用到了我的env文件,其实就是export导出了一个对象,里面就是一些环境变量设置。

其中VUE_APP_BASEURL为api地址

axios中proxy表示是否开启反代,自然,我是判断开发环境才允许使用反代。

baseURL也是判断如果是开发环境使用反代的当前域名/api的反代地址,但是由于考虑到nuxt服务有可能是在后端发起请求,这个/api就不是很适合了,应该要改为:

nuxt运行的地址+端口+/api

必须是一个固定的地址段,不然只有/api的话,后端发请求,百分百报错

connect ECONNREFUSED 127.0.0.1:80

大概是这么一个错误,因为后端发请求,他的地址和你反代后的地址是不同的。

这个设置是给nuxt的axios使用的。

如果你想做一个模块化的axios,也可以直接import引入axios自己改造,这里就放个例子:

import axios from "axios";
import env from "@/static/env/env";

let api = axios.create({
    baseURL: process.env.NODE_ENV === "development" ? `http://${env.VUE_APP_PROXY_IP}:${env.VUE_APP_PORT}/api` : process.env.VUE_APP_BASEURL,
    timeout: 15000, // 请求超时时间
});

export default api;

这里我就按照我上面所说的,弄得一个固定的地址,其中VUE_APP_PROXY_IP是我设置的一个nuxt服务启动后的ip地址,为了不用每次都来这里修改,所以用的变量。

当然,后面我还会讲到环境变量,所以这里的写法到时候还要改改。

反代

_nuxt.config.js_文件

import webpack from 'webpack'
import env from "./static/env/env";

export default {
  //反代
  proxy: process.env.NODE_ENV === "development" ? {
    '/api': {
      target: env.VUE_APP_BASEURL, //API服务器的地址
      ws: true,  //代理websockets
      changeOrigin: true, // 虚拟的站点需要更管origin
      pathRewrite: {   //重写路径 比如'/api/aaa/ccc'重写为'/aaa/ccc'
        '^/api': '/'
      }
    }
  } : {},
}

这里写的就比较丑了,为了防止正式环境nuxt进行反代,我做了个三元判断,如果你有更好的办法,欢迎留言告知,一起学习进步。

这个反代配置就和vue cli的反代一个吊样,以前讲过,具体就不多少了,这中文注释还看不懂那不是没得救了。

使用postcss-pxtorem自动rem转换

写手机端页面还是需要这个的,首先我们需要安装插件

yarn add postcss-pxtorem amfe-flexible --dev

安装完毕配置

在plugins目录下创建lib-flexible.js

_lib-flexible.js_文件内容如下:

import 'amfe-flexible';

在到_nuxt.config.js_文件中激活使用

export default {
  plugins: [
    { src: '@/plugins/lib-flexible', mode: 'client' },//rem适配
  ],
  build: {
    //rem转换
    postcss: {
      plugins: {
        'postcss-pxtorem': {
          rootValue: 64,
          propList: ['*']
        }
      },
      preset: {
        autoprefixer: true
      }
    },
  }
}

具体的设置就是'postcss-pxtorem': {}这块,设置根元素的大小,黑白名单啥的,具体配置可以百度。

vant框架按需引入

由于nuxt没有内置vant框架配置,所以我们需要自己手动了,vant的按需引入只能按需引入组件,不能按需引入样式,非常可惜。

vant官方也提供了nuxt的示例工程,我也是照着写的,没毛病。

yarn add vant babel-plugin-import 

安装完毕配置

首先我们需要在nuxt的plugins文件夹里面创建一个vant.js文件,用于按需引入我们需要的组件。

vant.js

import Vue from 'vue';
import { Row, Col, Icon, Image, Cell, CellGroup } from 'vant';

// 目前在 nuxt 中无法按需引入样式,因此采用手动引入的方式
import 'vant/lib/index.css';

Vue.use(Row)
  .use(Col)
  .use(Image)
  .use(Icon)
  .use(Cell)
  .use(CellGroup);

然后去nuxt配置文件里面

_nuxt.config.js_文件

export default {
  plugins: ['~/plugins/vant'],
  build: {
    babel: {
      plugins: [
        [
          'import',
          {
            libraryName: 'vant',
            // 目前在 nuxt 中无法按需引入样式,因此采用手动引入的方式
            style: false
          },
          'vant'
        ]
      ]
    }
  }
}

这样就行了,使用ojbk

gzip和brotli压缩

这个可是干货了,谷歌了好久,才搞定这个玩意。

nuxt官方好像不建议nuxt去做压缩,但是你也做的话,也不是不行。

安装:

yarn add nuxt-compress

安装完毕配置

_nuxt.config.js_文件

export default {
 buildModules: [
    [
      "nuxt-compress",
      {
        gzip: {
          cache: true
        },
        brotli: {
          threshold: 10240
        }
      }
    ]
  ],
}

这样打包的时候,会生成gz和br压缩文件,后端可以根据用户可以接受的格式返回对应的压缩内容。

关闭nuxt的eslint

这玩意真的是要命,太麻烦了,写啥啥报错,自动格式化插件又和vetur冲突,平时都是写vue项目,这玩意我不可能给你关掉,没办法,就只能关这个了。

解决办法也很简单,直接在nuxt.config.js文件里面注销eslint插件就行了

_nuxt.config.js_文件

export default {
 buildModules: [
     // '@nuxtjs/eslint-module'
   ]
}

css提取

每个vue文件里面都有单独的css设置,如果还像spa单页应用那样,渲染组件时再将style动态插入head中,那肯定时不行的,这样会带来一个问题。

当用户访问已经静态化的html文件时,样式闪烁了,刚开始没样式,等js初始化好了才有样式。

所以官方时建议我们每个组件的css提取成一个个单独的css文件,这样就可以先加载完css在渲染页面了。

配置也很简单

_nuxt.config.js_文件

export default {
 build: {
   extractCSS: true,
 }
}

如果你需要更复杂,比如将所有的样式都合并成一个css文件,可以看下官方得这个说明:

extractCSS

nuxt启动配置

默认情况,nuxt启动后,得到的在线地址很随意,端口随便来的,很淦,我们可以固定一些配置,这样就能省很多事

_nuxt.config.js_文件

import env from "./static/env/env";

export default {
 //启动配置
  server: {
    port: env.VUE_APP_PORT || 3000, // default: 3000
    host: '0.0.0.0' // default: localhost
  },
}

port: 端口

host:ip地址,默认这个就行了,表示你当前电脑的ip地址

关闭生成map文件

map文件本身就是用于方便开发的,但是也有危险,因为有了map文件,对方可以通过浏览器查看到你真正的源码,而不是被压缩混淆后的内容。

所以,目前我的解决方案就是开发模式生成map,正式生产就关闭,配置如下:

_nuxt.config.js_文件

export default {
 //关闭生成map文件
  productionSourceMap: process.env.NODE_ENV === "development" ? true : false
}

这个配置也同样适用于vue.config.js文件。

第三方组件引入使用

在传统的vue cli项目中,我们所有的插件都是在main.js文件中引入并使用的,但是在nuxt中不同,我们需要创建一个js文件,在js中引入并use激活,然后通过nuxt.config.js的plugins插入。

这里以scrollreveal插件为例:

yarn add scrollreveal --dev

在plugins目录下创建scrollreveal.js文件

scrollreveal.js

//scroll动效
import Vue from "vue";
import scrollReveal from "scrollreveal";
Vue.prototype.$scrollReveal = scrollReveal;

在nuxt.config.js的插件属性中导入

_nuxt.config.js_文件

export default {
 plugins:[
   { src: '@/plugins/scrollreveal', mode: 'client' },
 ]
}

plugins的内容引入有直接字符串地址的,也有{}对象形式的。

例子:

export default {
 plugins:[
   '@/plugins/scrollreveal',
   { src: '@/plugins/scrollreveal', mode: 'client' },
 ]
}

其中对象形式是为了控制,我们这个插件要在什么端运行。

mode就是表示在那个端运行,

'client'表示在客户端运行

‘serber’表示在服务端运行

怎么区别呢,很简答,如果你的插件中用到了window对象或者window下的属性,那么你就需要在客户端运行,因为在服务端是没有window对象的。

路由守卫

由于nuxt的路由是自动获取的,如果我们想要加上路由守卫,只能在plugins中导出一个函数,函数可以接受nuxt传入得参数,也就是上下文对象,通过这个上下文对象我们获取到router对象。

然后对这个router添加拦截器。

在plugins目录中创建一个routing-guard.js文件

routing-guard.js

export default ({ app }) => {

  //路由进入前
  app.router.beforeEach((to, from, next) => {
    next();
  });


  //路由进入后
  app.router.afterEach(() => {
    //
  })
}

然后再去nuxt.config.js中激活插件

_nuxt.config.js_文件

export default {
 plugins:[
   { src: '@/plugins/routing-guard', mode: 'client' },
 ]
}

忘记说了,mode默认就是server,然而是否在服务端运行,就看你自己是否需要使用一些在客户端才能获取的东西。

环境变量

如果你要使用一个环境变量,nuxt建议你写一个js文件,然后export方式,将对象导出。

例子:

env.js

export default {
    xxx: xxx
}

然后我们在nuxt.config.js中引入并使用

_nuxt.config.js_文件

import env from "./static/env/env";

export default {
 env,
}

在其他文件中使用的时候process.env.xxx获取。

如果你要在nuxt.config.js中获取,我觉得你使用import引入的env对象更靠谱一些。

全静态打包

nuxt的generate指令默认只能半静态,也就是页面加载完毕还是会初始化为spa模式,在切换到其他页面时,如果有请求,会先等待api请求加载完毕才渲染页面出来。

但是,也不是所有的页面都需要这个,我们就希望他能给一个html文件,也不需要初始化为spa模式。

那么全静态就诞生了,我非常幸运能够在现在使用nuxt,因为这个功能是v2.14才出来的。

如何使用呢?

_nuxt.config.js_文件

export default {
 target: 'static', // default is 'server'
}

配置这个属性就行了,然后再运行generate命令,就可以得到全静态化的文件。


以上就是我最近入坑遇到的问题已经解决的方式,后续如果还有啥需求,也会分享出来。

版权申明

本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。

关于作者

站点职位 博主
获得点赞 0
文章被阅读 580

相关文章