上一篇链接:nuxt配置env环境 配置cross-env_安哥说前端的博客-CSDN博客
这里先介绍一下nuxt,nuxt是基于 Vue.js 的服务端渲染应用框架,就是我们平常说的SSR服务端渲染。
优点
-
利于seo,一般购物类网站都需要seo优化
-
首屏渲染速度更快
-
原因是:服务端渲染只需要进行一次网络请求,而客户端渲染需要先请求运行所需文件,运行之后再进行网络请求数据,然后加载页面
-
缺点
-
对于服务器要求比客户端渲染高
重点来了,接下来讲的是axios的封装
1.package.json文件配置env
// 接上一篇,可看链接,这里只是重复一遍
{
"name": "ange-blog",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "cross-env BASE_URL=你后端dev接口地址+端口 NODE_ENV=development nuxt",
"build:prod": "cross-env BASE_URL=你后端prod接口地址+端口 NODE_ENV=production nuxt build",
"build:test": "cross-env BASE_URL=你后端test接口地址+端口 NODE_ENV=test nuxt build",
"start": "cross-env BASE_URL=你后端接口地址+端口 NODE_ENV=production nuxt start",
"generate": "nuxt generate"
},
...
}
2.在plugin文件夹里创建axios.js文件
这里的axios.js只是判断你当前的环境然后去使用对应环境的后端地址接口
这里的http://localhost:3000对应的是nuxt.config.js的配置port端口
import axios from 'axios'
export default axios.create({
// 单个环境
baseURL: process.env.NODE_ENV === 'production'
? process.env.BASE_URL : 'http://localhost:3000',
// 如果有test等多个环境变量,那么是这么写
baseURL: (process.env.NODE_ENV === 'production'
|| process.env.NODE_ENV === 'test')
? process.env.BASE_URL : 'http://localhost:3000',
})
3.nuxt.config.js(部分代码,后面有完整版)
module.exports = {
env: {
// 对应package.json及request.js
BASE_URL: process.env.BASE_URL,
// 对应环境production、test等
NODE_ENV: process.env.NODE_ENV
},
// 本地服务启动yarn dev的端口号
server: {
port: 3000
},
// 必须引入,不然无法使用axios跟代理
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
...
}
4.axios封装:request.js文件(完整代码)
import axios from '@/plugins/axios'
import { MessageBox, Message } from 'element-ui'
// baseURL地址,例如:https://161.1.896.285/
// process.env.BASE_URL是获取到package.json配置的和
// nuxt.config.js的env相关联系
// 因为这里配置了env环境,所以process.env.BASE_URL这么写
axios.defaults.baseURL = process.env.BASE_URL
// post请求头,影响不大,可写可不写
axios.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded;charset=UTF-8'
// 请求拦截器
axios.interceptors.request.use(async config => {
// 根据自己项目配置请求头token,需要与后端配合名字
// if (store.getters.token) {
// config.headers['token'] = getToken()
// }
return config;
},error => {
console.log(error)
return Promise.reject(error);
});
// 响应拦截器
axios.interceptors.response.use(response => {
// 这里可以根据浏览器返回的status状态码去判断
// 这里只举例了200的情况
if (response.status === 200) {
return response
} else {
return Promise.reject(response)
}
},
error => {
console.log('err' + error);
// 根据接口返回的去提示对应的
// Message({
// message: error.response.data.error,
// type: 'error',
// duration: 5 * 1000
// })
// 我这里10030是token失效,其他的根据后端接口返回去写判断
// if (error.response.data.status === 10030) {
// removeToken() 这是我封装的token方法,不需要复制
// 跳转到登录页
// window.location.href = `/login`
// }
return Promise.reject(error)
})
/**
* 封装get方法,对应get请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export const get = (url, params) => {
return new Promise((resolve, reject) => {
axios
.get(url, {
params: params
})
.then(res => {
resolve(res.data)
})
.catch(function (error) {
if (error.response) {
reject(error.response.data)
}
});
})
}
/**
* post方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export const post = (url, params) => {
return new Promise((resolve, reject) => {
axios
.post(url, params)
.then(res => {
resolve(res.data)
})
.catch(function (error) {
if (error.response) {
reject(error.response.data)
}
});
})
}
// delete,put等方法同理,这里只举例最常见的get和post请求
5.封装接口:新建api文件,api文件下新建home.js
home.js文件
这里带/api是因为nginx配置后端接口反向代理,与后面的proxy代理无关,自行与项目相关去配置接口地址
import { base_url } from '@/api/baseUrl'
import { post, get } from '@/utils/request.js'
export const queryOne = (params) => {
return post(`${base_url}/api/xxx/xxx`, params)
}
export const queryTwo = (id) => {
return get(`${base_url}/api/xxx?id=${id}`)
}
6.nginx配置nginx.conf(仅自己的配置,大家根据自己项目去配)
server {
listen 80;
server_name www.xxxxx.com;
location /api/ {
proxy_pass http://www.xxxxx.com:8010/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
error_page 405 = 200 $request_uri;
}
tips:fetch可以使用this,asyncData无法获取到this,nuxt只有在首屏加载才会服务端渲染,其他情况是客户端渲染
例子:在自己vue页面调用nuxt的fetch
<template>
<div>
<div v-for="item in navData" :key="item.id">
{{ item.id }}
</div>
</div>
</template>
<script>
// 引入home.js方法
import { queryOne } from "@/api/home";
export default {
data() {
return {
navData: [],
}
},
mounted () {},
// fetch ssr渲染
async fetch() {
const data = {
pageNum: 0,
pageSize: 0,
}
await queryOne(data).then((res) => {
console.log(res);
this.navData = res.list;
});
},
}
7.axios配置proxy代理
nuxt.config.js文件
tips:这里的proxy代理与前面封装axios(request.js)无关,因为request.js一直走的是env配置的prod或者dev或者test环境的ip地址
// const webpack = require('webpack')
module.exports = {
env: {
// 对应package.json及request.js
BASE_URL: process.env.BASE_URL,
// 对应环境production、test等
NODE_ENV: process.env.NODE_ENV
},
// 本地服务启动yarn dev的端口号
server: {
port: 3000
},
// 必须引入,不然无法使用axios跟代理
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
axios: {
proxy: true, // 开启代理
prefix: '/api', // baseURL
baseURL: '',
withCredentials: true,
credentials: true,
},
// 配置反向代理,记得使用的时候需要带上/api
// 下面举了例子可以参考一下
// 但是配置了env环境,根本用不上proxy代理的
// 例如:https://161.1.896.285/api/xxx/xxx
proxy: {
'/api': {
target: 'https://xxxxx/',
changeOrigin: true, // 表示是否跨域
pathRewrite: {
'^/api': ''
},
secure: true
}
},
}
例子:
这里举例的是使用了vue-pdf,pdf预览引起跨域,这里不过多介绍,可以自行百度vue-pdf跨域问题
tips:因为你nuxt.config.js上配置的port端口是3000
所以你yarn dev启动项目访问的是localhost:3000
正好你获取服务器上面的pdf(process.env.BASE_URL/img/record.pdf)
那么就会报跨域,此时就会走nuxt.config.js的proxy配置,
这时就会反向代理,访问http://localhost:3000/api/img/record.pdf成功!
tips:这里仅仅是因为vue-pdf插件预览显示的原因才会报跨域才举例子,而不是说访问服务器的图片或者pdf或者请求接口会报跨越,因为图片等请求其实是可以跨域的,然后因为配置了env所以接口根本不会走proxy代理!!