vant
- npm install vant -D
- plugins/vant.js
import { defineNuxtPlugin } from '#app';
import { Row, Col, Icon, Image, Cell, CellGroup } from 'vant';
// 目前在 nuxt 中无法按需引入样式,因此采用手动引入的方式
import 'vant/lib/index.css';
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.vueApp.use(Row).use(Col).use(Image).use(Icon).use(Cell).use(CellGroup);
});
- nuxt.config.ts
export default defineNuxtConfig({
experimental: {
externalVue: true
}
});
- 使用
<template>
<div>
<Button>直接用</Button>
<van-icon name="chat-o" />
</div>
</template>
<script setup>
import { Button } from 'vant';
</script>
sass
- npm install sass -D
- nuxt.config.ts
export default defineNuxtConfig({
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "assets/styles/global.scss";',
}
}
}
}
})
- assets/styles/global.scss
$header-bg-color: #0078D7;
- 使用
<template>
<div>
<h1 class="blue">首页</h1>
</div>
</template>
<style scoped lang="scss">
.blue {
color: $header-bg-color;
}
</style>
Eslint
1、初始化
- 执行npx eslint --init初始化一个.eslintrc.js
- 安装npm i -D eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest eslint@latest
- 安装typescript依赖npm i -D typescript
- 在packahe.json的scripts中添加"lint": "eslint . --ext .ts,.vue"然后使用yarn lint用来测试eslint是否生效
2、nuxt.config.ts
- 把配置文件中extends项下的"plugin:vue/essential"替换为"plugin:vue/vue3-recommended"
- 安装eslint-plugin-nuxt执行npm i -D eslint-plugin-nuxt,extends项中增加"plugin:nuxt/recommended",删除"eslint:recommended"(eslint默认校验)
- 删除plugins项下的"vue",同时可以选择性在rules项中增加"vue/multi-word-component-names": 0,nuxt中提倡vue文件和组件使用kebab-case(烤肉串式)风格命名,将该规则设为0关闭校验
3、prettier
- 安装:npm i -D prettier eslint-plugin-prettier eslint-config-prettier
- 最终配置:.eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true
},
extends: [
'plugin:prettier/recommended',
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:nuxt/recommended'
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
parser: 'vue-eslint-parser',
plugins: ['@typescript-eslint'],
rules: {
'vue/multi-word-component-names': 0, //关闭vue文件和组件命名校验
'vue/singleline-html-element-content-newline': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/max-attributes-per-line': 0,
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
'prettier/prettier': [
'error',
{
printWidth: 140, //代码单行长度
tabWidth: 2, //tab键缩进为2空格
useTabs: false, //使用空格缩进
singleQuote: true, //js单引号
trailingComma: 'none', //无尾逗号
arrowParens: 'avoid', //箭头函数尽可能省略括号
jsxBracketSameLine: true, //标签换行后>单独一行
endOfLine: 'auto' // 不让检测文件每行结束的格式.
}
]
}
};
4、提交验证
store
- store\user.js
// @/store/user.js
import { useState } from 'nuxt/app';
export const userUserInfo = () =>
useState('userInfo', () => ({
username: '',
password: ''
}));
- A文件
<template>
<div>
<input v-model="userInfo.username" />
</div>
</template>
<script setup>
import { userUserInfo } from '@/store/user.js';
const userInfo = userUserInfo();
</script>
- B文件
<template>
<div>
<div>{{ userInfo.username }}</div>
</div>
</template>
<script setup>
import { userUserInfo } from '@/store/user.js';
const userInfo = userUserInfo();
</script>
cookie
// get Cookie
const Cookies = useCookie('lang', {
maxAge: 1000 * 60
})
// Set Cookie
Cookies.value = Cookies.value || 'cn'
// Delete Cookie
cookie.value = undefined
// or
cookie.value = null
vite
- nuxt.config.ts
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "assets/styles/global.scss";'
}
}
}
}
环境、接口
- package.json
"scripts": {
"dev": "cross-env API_ENV=development nuxi dev",
},
- nuxt.config.ts
let v1Domain: string;
let v2Domain: string;
let v4Domain: string;
if (process.env.API_ENV == 'development') {
v1Domain = 'url1';
v2Domain = 'url2';
v4Domain = 'url3';
} else if (process.env.API_ENV == 'production') {
v1Domain = 'url4';
v2Domain = 'url5';
v4Domain = 'url6';
}
export default defineNuxtConfig({
runtimeConfig: {
public: {
API_ENV: process.env.API_ENV
}
},
vite: {
server: {
proxy: {
'/v1/Api': {
target: v1Domain,
changeOrigin: true,
rewrite: path => path.replace(/^/v1/, '')
},
'/v2/api': {
target: v2Domain,
changeOrigin: true,
rewrite: path => path.replace(/^/v2/, '')
},
'/v4/api': {
target: v4Domain,
changeOrigin: true,
rewrite: path => path.replace(/^/v4/, '')
}
}
}
}
});
- server\home.ts
export default {
getInfo(params) {
return $fetch('/v2/api/index/getInfo', { method: 'get', params });
},
houseList(params) {
return $fetch('/v2/api/index/houseList', { method: 'get', params });
},
houseDetail(params) {
return $fetch('/v1/Api/House/detail', { method: 'get', params });
}
};
- 调用接口
<script setup>
import api from '~~/server/home';
const res = await api.houseList({
type: 2
});
</script>
PM2
- ecosystem.config.js
// 配置pm2
module.exports = {
apps: [
{
name: "Nuxt3-Mobile",
exec_mode: "cluster",
script: "./.output/server/index.mjs",
args: "start", // 传递给脚本的参数
watch: true, // 开启监听文件变动重启
ignore_watch: ["node_modules", "logs", "public"], // 不用监听的文件
instances: "4", // max表示最大的 应用启动实例个数,仅在 cluster 模式有效 默认为 fork
autorestart: true, // 默认为 true, 发生异常的情况下自动重启
max_memory_restart: "1G", // 当内存超过1G时自动重启
error_file: './logs/app-err.log', // 错误日志文件
out_file: './logs/app-out.log', // 正常日志文件
merge_logs: true, // 设置追加日志而不是新建日志
log_date_format: "YYYY-MM-DD HH:mm:ss", // 指定日志文件的时间格式
min_uptime: "60s", // 应用运行少于时间被认为是异常启动
max_restarts: 30, // 最大异常重启次数
restart_delay: 60, // 异常重启情况下,延时重启时间
host : ["0.0.0.0"], // 监听地址,如果监听所有,可以省略
env: {
// 环境参数,当前指定为开发环境
NODE_ENV: "development",
PORT: "8088",
},
env_production: {
// 环境参数,当前指定为生产环境
NODE_ENV: "production", //使用production模式 pm2 start ecosystem.config.js --env production
PORT: "8088",
},
},
],
};
- 执行命令
npm run build
pm2 start ecosystem.config.js