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文件,可以看下官方得这个说明:
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命令,就可以得到全静态化的文件。
以上就是我最近入坑遇到的问题已经解决的方式,后续如果还有啥需求,也会分享出来。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据