nuxt构建项目
Posted 万年打野易大师
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nuxt构建项目相关的知识,希望对你有一定的参考价值。
一、引入并创建nuxt项目
确认已经安装 npx ( npx
依附于 npm 5.2.0
安装引入)
npx create-nuxt-app <my-project>
或者在 npm
v6.1版本后 可以这样创建:
npm init nuxt-app@latest <my-project>
或者用: yarn:
yarn create nuxt-app <my-project>
二、引入axios库
1、使用nuxt自带模块
npm i @nuxtjs/axios -s
1) 、在 nuxt.config.js
中引入
export default {
/*
** Runtime Config
*/
publicRuntimeConfig: {
axios: {
baseURL: \'https://api.nuxtjs.dev\'
}
},
/*
** Modules - https://nuxtjs.org/docs/2.x/directory-structure/modules
*/
modules: [\'@nuxtjs/axios\']
}
2) 、页面内使用 $axios
获取数据,并用 $config
获取 API 接口的 URL
async asyncData({$axios}) {
let { res } = await $axios.get(`https://xxx.com/api/xxx`)
console.log(res)
}
3) 、设置公共拦截
在 ~/plugins
创建 axios.js
文件
export default function ({store, redirect, req, router, $axios }) {
// baseUrl可以在上面的配置中,也可在这儿配置
$axios.defaults.baseURL = \'http://XXX/api\';
if(process.server){
// 获取服务端的token,对应函数请自行封装
var token = getcookiesInServer(req).token;
}
if(process.client){
// 获取客户端token,对应函数请自行封装
var token = getcookiesInClient(\'token\');
}
// request拦截器
$axios.onRequest(config => {
if(process.client){
// 客户端下,请求进度条开始
NProgress.start();
}
// 将获取到token加入到请求头中
config.headers.common[\'Authorization\'] = token;
});
// response拦截器,数据返回后,可以先在这里进行一个简单的判断
$axios.interceptors.response.use(
response => {
if(process.client){
// 客户端下, 请求进度条结束
NProgress.done();
}
// return response
if(response.data.code == 401){
// 返回401,token验证失败
removeToken("token");
// 重定向到登录页面, 这里做一个判断,容错:req.url 未定义
if(req.url){
redirect("/sign?ref="+req.url)
}else{
redirect("/sign")
}
}else if(response.data.code == 404){
// 重定向到404页面
redirect("/")
}
else{
// 请求接口数据正常,返回数据
return response
}
},
error => {
if(process.client){
NProgress.done();
}
if(error.response.status == 500){
// http状态500,服务器内部错误,重定向到500页面
redirect("/500.htm")
}
if(error.response.status == 404){
// http状态500,请求API找不到,重定向到404页面
redirect("/404.html")
}
return Promise.reject(error.response) // 返回接口返回的错误信息
})
}
2、外部引入axios
npm i axios -s
1) 、创建request文件夹
在文件夹内创建 http.js
文件, urls
文件夹, apis
文件夹
http.js
import axios from \'axios\'
import Vue from \'vue\'
const ajax = axios.create({
baseURL: process.env.baseUrl,
timeout: 30 * 1000
})
// 请求拦截器
ajax.interceptors.request.use(
config => {
// const Token = getToken()
// if (Token) {
// config.headers[\'token\'] = getToken()
// }
config.headers[\'Content-Type\'] = \'application/json;chartset=utf-8\'
// config.headers["Authorization"] = "Bearer atwerjjhqkwehtjhsdfqwehjhwrgqre";
return config
},
error => {
throw new Error(`请求错误: ${error}`)
}
)
// 响应拦截器
ajax.interceptors.response.use(
response => {
if (response.status === 200) {
// 处理返回流文件报错
if (response.config.responseType === \'blob\') {
var reader = new FileReader()
reader.readAsText(response.data)
reader.onload = e => {
const result = JSON.parse(e.target.result)
if (result.code !== 200) {
Vue.prototype.$message.error(result.msg)
}
}
}
if (response.data.code === 200) {
return response.data.data
} else {
Vue.prototype.$message.error(response.data.message)
return Promise.reject(response.data)
}
} else {
return response
}
},
error => {
throw new Error(error)
// throw new Error(`请求错误: ${error}`)
}
)
/*
* @params {config} 参数从API传递过来
* @params @{config} {url} 请求地址
* @params @{config} {data} 请求数据
*/
export function get(config) {
let obj = {
url: config.url,
method: \'get\',
params: {
...config.data,
}
}
return ajax(obj)
}
export function post(config) {
let obj = {
url: config.url,
method: \'post\',
data: {
...config.data,
}
}
return ajax(obj)
}
export function upload(config) {
let obj = {
url: config.url,
method: \'post\',
data: config.data,
headers: {
\'Content-Type\': \'multipart/form-data\'
}
}
return ajax(obj)
}
urls文件夹下创建对应模块的url信息
例如 urls/user.js
export default {
userinfo: \'/user/userinfo\',
userList: \'/user/userList\'
}
apis文件夹下创建对应模块的api函数
例如 apis/user.js
import { get, post } from \'../http.js\'
import user from \'../urls/user\'
export function getUserinfo(params) {
return get({ url: userUrls.userinfo, params })
}
export function getUserList(params) {
return post({ url: userUrls.userList, params })
}
页面内正常使用我们熟知的方式引入api函数去调接口获取数据
3、axios跨域配置
1) 、使用官方axios模块时的配置
export default {
axios: {
proxy: true,
prefix: \'/api\', // baseURL
credentials: true,
retry: { retries: 3 }
},
proxy: {
\'/api\': {
target: \'http://192.168.xxx.xxx:xxxx\', // 代理地址
changeOrigin: true,
pathRewrite: {
\'^/api\': \'\', //将 /api 替换掉
}
},
}
}
2) 、使用官方axios模块,引入官方模块 @nuxtjs/proxy
配置
npm i @nuxtjs/proxy -D
在 nuxt.config.js
中配置
modules: [
\'@nuxtjs/axios\',
\'@nuxtjs/proxy\'
],
proxy: [
[
\'/api\',
{
target: \'http://localhost:3001\', // api主机
pathRewrite: { \'^/api\' : \'/\' }
}
]
]
3) 、使用外部引入的方式
配合后端部署设置nginx
三、登录状态持久化
npm i -S cookie-universal-nuxt
在 nuxt.config.js
中配置
modules: [
// 登录状态持久化
[\'cookie-universal-nuxt\', { parseJSON: true }]
],
store配置请参考本文下面的i18n部分, store/index.js
四、引入ant-design-vue组件库
npm i -S ant-design-vue
npm install babel-plugin-import --save-dev
1、按需引入配置
// nuxt.config.js
{
build: {
babel: {
plugins: [
[
\'import\',
{
libraryName: \'ant-design-vue\',
libraryDirectory: \'es\',
style: true
// 默认不使用该选项,即不导入样式 , 注意 ant-design-vue 使用 js 文件引入样式
// true 表示 import \'ant-design-vue/es/component/style\'
// \'css\' 表示 import \'ant-design-vue/es/component/style/css\'
}
]
]
}
}
}
在 ~/plugins
文件夹创建 antd-ui.js
文件
import Vue from \'vue\'
Vue.config.productionTip = false
import { Button } from \'ant-dsign-vue\'
Vue.use(Button)
2、antd-icon
过大
不是所有的图标我们都能用到
在 ~/plugins
文件夹创建 antd-icons.js
文件
export {
// 需要使用到的 Icons
InfoCircleFill,
DownOutline,
UpOutline,
RightOutline,
LeftOutline
} from \'@ant-design/icons\'
// nuxt.config.js
const CompressionPlugin = require(\'compression-webpack-plugin\')
const path = require(\'path\')
export default {
build: {
vendor: [\'axios\', \'ant-design-vue\'],
// 解决less加载使用不了的问题
loaders: {
less: {
javascriptEnabled: true
}
},
analyze: {
analyzerMode: \'static\'
},
// 使用Babel与特定的依赖关系进行转换
transpile: [/ant-design-vue/],
extend(config, ctx) {
// 配置eslint
if (ctx.isClient) {
config.module.rules.push({
enforce: \'pre\',
test: /\\.(js|vue)$/,
loader: \'eslint-loader\',
exclude: /(node_modules)/
})
// ant-design-vue 的icon组件,按需引入需要的图标,文件太大
config.resolve.alias[\'@ant-design/icons/lib/dist$\'] = path.resolve(__dirname, \'./plugins/antd-icons.js\') // 引入需要的
}
},
// 打包构建优化
plugins: [
new CompressionPlugin({
test: /\\.js$|\\.html$|\\.css/, // 匹配文件名
threshold: 10240, // 对超过10kb的数据进行压缩
deleteOriginalAssets: false // 是否删除原文件
})
],
optimization: {
splitChunks: {
minSize: 10000,
maxSize: 250000
}
}
}
}
注意: 这儿安装 compression-webpack-plugin
插件会报错,指定插件版本就行了
npm i --save-dev compression-webpack-plugin@6.1.1
提醒:图标使用<a-icon type="close"></a-icon>来显示
如果有组件内使用的,例如
<a-rate v-model="val">
<a-icon #character type="star"></a-icon>
</a-rate>
五、国际化
1、引入i18n
npm i vue-i18n --save
2、在 plugins
下创建 i18n.js
// nuxt.config.js
export default {
plugins: [
\'@/plugins/antd-ui\',
{ src: \'@/plugins/lazy-load\', ssr: false },
\'@/plugins/i18n.js\',
{ src: \'~/plugins/lodash.js\', ssr: false },
{ src: \'~/plugins/moment.js\', ssr: false },
{ src: \'@/plugins/vue-swiper.js\', mode: \'client\' },
],
}
import Vue from \'vue\'
import VueI18n from \'vue-i18n\'
Vue.use(VueI18n)
export default ({ app, store }) => {
// Set i18n instance on app
// This way we can use it in middleware and pages asyncData/fetch
app.i18n = new VueI18n({
locale: store.state.locale,
fallbackLocale: store.state.locale,
messages: {
\'en-US\': require(\'@/language/en-US.json\'),
\'zh-CN\': require(\'@/language/zh-CN.json\')
},
silentTranslationWarn: true
})
app.i18n.path = link => {
// 如果是默认语言,就省略
if (app.i18n.locale === app.i18n.fallbackLocale) {
return `/${link}`
}
return `/${app.i18n.locale}/${link}`
}
}
3、在 middleware
下创建 i18n.js
// nuxt.config.js
export default {
router: {
middleware: [\'i18n\']
},
}
export default function({ isHMR, app, store, route, params, error, redirect }) {
const defaultLocale = app.i18n.fallbackLocale
// If middleware is called from hot module replacement, ignore it
if (isHMR) return
// Get locale from params
const locale = params.lang || defaultLocale
if (store.state.locales.indexOf(locale) === -1) {
return error({ message: \'页面未找到.\', statusCode: 404 })
}
// Set locale
// store.commit(\'SET_LANG\', locale)
app.i18n.locale = store.state.locale
// If route is /<defaultLocale>/... -> redirect to /...
if (locale === defaultLocale && route.fullPath.indexOf(\'/\' + defaultLocale) === 0) {
const toReplace = \'^/\' + defaultLocale + (route.fullPath.indexOf(\'/\' + defaultLocale + \'/\') === 0 ? \'/\' : \'\')
const re = new RegExp(toReplace)
return redirect(route.fullPath.replace(re, \'/\'))
}
}
4、在 store
下创建 index.js
import { getToken } from \'@/lib/token.js\'
const state = () => ({
token: \'\',
locales: [\'en-US\', \'zh-CN\'],
locale: \'en-US\'
})
const mutations = {
setToken(state, token) {
state.token = token
},
SET_LANG(state, locale) {
if (state.locales.indexOf(locale) !== -1) {
state.locale = locale
}
}
}
const actions = {
async nuxtServerInit({ commit }, { app }) {
let token = getToken(app) || \'\'
commit(\'setToken\', token)
//还可以获取一些通用信息,比如个人信息,通用配置什么的
}
}
export default {
state,
actions,
mutations
}
5、在 language
下创建 en-US.json
、 zh-CN.json
更多语言库,请按照规则添加
配置对应的变量属性名称,在页面用
<span>{{ $t(\'变量名\') }}</span>
对应antd-vue组件库国际化,官方推荐使用 config-provider
组件
// default.vue页面
<template>
<a-config-provider :locale="lang">
<div class="layout-container">
<a-layout>
<a-layout-header>header</a-layout-header>
<a-layout-content><Nuxt /></a-layout-content>
<a-layout-footer>footer</a-layout-footer>
<a-back-top />
</a-layout>
</div>
</a-config-provider>
</template>
<script>
import { mapState } from \'vuex\'
import language from \'../language/antd-lang/index\'
import moment from \'moment\'
import \'moment/locale/zh-cn\'
moment.locale(\'en\')
export default {
data() {
return {}
},
computed: {
...mapState({
locale: state => state.locale
}),
lang: function() {
let l = null
switch (this.locale) {
case \'zh-CN\':
l = language.zhCN
moment.locale(\'zh-cn\')
break
case \'en-US\':
l = language.enUS
moment.locale(\'en\')
break
}
return l
}
}
}
</script>
在 language
下创建 antd-lang/index.js
, 包含所有的支持语言库
// 阿拉伯
import arEG from \'~/node_modules/ant-design-vue/es/locale/ar_EG\'
// 保加利亚语
import bgBG from \'~/node_modules/ant-design-vue/es/locale/bg_BG\'
// 加泰罗尼亚语
import caES from \'~/node_modules/ant-design-vue/es/locale/ca_ES\'
// 捷克语
import csCZ from \'~/node_modules/ant-design-vue/es/locale/cs_CZ\'
// 德语
import deDE from \'~/node_modules/ant-design-vue/es/locale/de_DE\'
// 希腊语
import elGR from \'~/node_modules/ant-design-vue/es/locale/el_GR\'
// 英语
import enGB from \'~/node_modules/ant-design-vue/es/locale/en_GB\'
// 英语(美式)
import enUS from \'~/node_modules/ant-design-vue/es/locale/en_US\'
// 西班牙语
import esES from \'~/node_modules/ant-design-vue/es/locale/es_ES\'
// 爱沙尼亚语
import etEE from \'~/node_modules/ant-design-vue/es/locale/et_EE\'
// 波斯语
import faIR from \'~/node_modules/ant-design-vue/es/locale/fa_IR\'
// 芬兰语
import fiFI from \'~/node_modules/ant-design-vue/es/locale/fi_FI\'
// 法语(比利时)
import frBE from \'~/node_modules/ant-design-vue/es/locale/fr_BE\'
// 法语
import frFR from \'~/node_modules/ant-design-vue/es/locale/fr_FR\'
// 冰岛语
import isIS from \'~/node_modules/ant-design-vue/es/locale/is_IS\'
// 意大利语
import itIT from \'~/node_modules/ant-design-vue/es/locale/it_IT\'
// 日语
import jaJP from \'~/node_modules/ant-design-vue/es/locale/ja_JP\'
// 韩语/朝鲜语
import koKR from \'~/node_modules/ant-design-vue/es/locale/ko_KR\'
// 挪威
import nbNO from \'~/node_modules/ant-design-vue/es/locale/nb_NO\'
// 荷兰语(比利时)
import nlBE from \'~/node_modules/ant-design-vue/es/locale/nl_BE\'
// 荷兰语
import nlNL from \'~/node_modules/ant-design-vue/es/locale/nl_NL\'
// 波兰语
import plPL from \'~/node_modules/ant-design-vue/es/locale/pl_PL\'
// 葡萄牙语(巴西)
import ptBR from \'~/node_modules/ant-design-vue/es/locale/pt_BR\'
// 葡萄牙语
import ptPT from \'~/node_modules/ant-design-vue/es/locale/pt_PT\'
// 斯洛伐克语
import skSK from \'~/node_modules/ant-design-vue/es/locale/sk_SK\'
// 塞尔维亚
import srRS from \'~/node_modules/ant-design-vue/es/locale/sr_RS\'
// 斯洛文尼亚
import slSI from \'~/node_modules/ant-design-vue/es/locale/sl_SI\'
// 瑞典语
import svSE from \'~/node_modules/ant-design-vue/es/locale/sv_SE\'
// 泰语
import thTH from \'~/node_modules/ant-design-vue/es/locale/th_TH\'
// 土耳其语
import trTR from \'~/node_modules/ant-design-vue/es/locale/tr_TR\'
// 俄罗斯语
import ruRU from \'~/node_modules/ant-design-vue/es/locale/ru_RU\'
// 乌克兰语
import ukUA from \'~/node_modules/ant-design-vue/es/locale/uk_UA\'
// 越南语
import viVN from \'~/node_modules/ant-design-vue/es/locale/vi_VN\'
// 简体中文
import zhCN from \'~/node_modules/ant-design-vue/es/locale/zh_CN\'
// 繁体中文
import zhTW from \'~/node_modules/ant-design-vue/es/locale/zh_TW\'
export default {
arEG,
bgBG,
caES,
csCZ,
deDE,
elGR,
enGB,
enUS,
esES,
etEE,
faIR,
fiFI,
frBE,
frFR,
isIS,
itIT,
jaJP,
koKR,
nbNO,
nlBE,
nlNL,
plPL,
ptBR,
ptPT,
skSK,
srRS,
slSI,
svSE,
thTH,
trTR,
ruRU,
ukUA,
viVN,
zhCN,
zhTW
}
六、scss、less样式变量全局使用
SASS: `yarn add sass-loader node-sass`
LESS: `yarn add less-loader less`
Stylus: `yarn add stylus-loader stylus`
yarn add @nuxtjs/style-resources
npm i @nuxtjs/style-resources --save-dev
配置请参考:@nuxtjs/style-resources
// nuxt.config.js
export default {
// 下面这两个配置用一个就行了
modules: [\'@nuxtjs/style-resources\'],
buildModules: [\'@nuxtjs/style-resources\'],
// 配置我们需要用到的less、scss全局变量,然后在.vue文件内直接引入
styleResources: {
// your settings here
sass: [],
scss: [\'./assets/vars/*.scss\', \'./assets/abstracts/_mixins.scss\'],
less: [\'./assets/vars/*.less\'],
stylus: []
},
}
以上是关于nuxt构建项目的主要内容,如果未能解决你的问题,请参考以下文章
我们如何在 Nuxt?Vuejs 项目中仅包含来自 lodash 的必需模块?