目录
项目搭建选项
项目搭建步骤
本地开发环境
Vite脚手架构建项目
关联Git仓库
开发工具
安装pinia
安装Sass
安装Vant-UI
安装postcss-pxtorem(移动端项目)
安装axios
本地调试
环境变量
本地代理
全局UI组件
路由中间件
项目部署
nginx配置
jenkins自动化部署
自由风格配置
流水线配置
灰度部署方案
安装nodejs,node版本建议大于16.0.0
Download | Node.js
官网:https://cn.vitejs.dev/guide/
初始化后的项目关联远程git仓库
Visual Studio Code
配置.vscode/setting.json,自动校验eslint并修复
{
// 开启保存自动格式化
"editor.formatOnSave": true,
// 开启eslint校验
"eslint.enable": true,
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"],
"editor.fontSize": 14,
// vscode默认启用了根据文件类型自动设置tabsize的选项
"editor.detectIndentation": false,
// 重新设定tabsize
"editor.tabSize": 2,
// #每次保存的时候将代码按eslint格式进行修复
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
// 校验文件类型
"eslint.validate": ["html", "vue", "javascript", "jsx"],
// #让prettier使用eslint的代码格式进行校验
"prettier.eslintIntegration": true,
// #去掉代码结尾的分号
"prettier.semi": true,
// #使用带引号替代双引号
"prettier.singleQuote": true,
// #让函数(名)和后面的括号之间加个空格
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
// #让vue中的js按编辑器自带的ts格式进行格式化
"vetur.format.defaultFormatter.js": "vscode-typescript",
"vetur.format.defaultFormatterOptions": {
"js-beautify-html": {
"wrap_attributes": "force-aligned"
// #vue组件中html代码格式化样式
},
"prettier": {
"semi": false,
"singleQuote": true,
"eslintIntegration": true,
"stylelintIntegration": true,
"tabWidth": 2,
"vetur.format.defaultFormatter.html": "prettier"
}
},
"explorer.confirmDelete": false,
"explorer.confirmDragAndDrop": false,
"editor.renderControlCharacters": true,
// "editor.renderWhitespace": "all",
"files.associations": {
"*.cjson": "jsonc",
"*.wxss": "css",
"*.wxs": "javascript"
},
"emmet.includeLanguages": {
"wxml": "html"
},
"minapp-vscode.disableAutoConfig": true,
"bald.config": false,
"files.autoSave": "off",
"diffEditor.ignoreTrimWhitespace": false,
"editor.foldingStrategy": "indentation",
"git.path": "",
"editor.foldingMaximumRegions": 50000,
"security.workspace.trust.untrustedFiles": "newWindow",
"editor.unicodeHighlight.nonBasicASCII": false,
// 以下是格式化插件配置
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
官网:安装 | Pinia 中文文档
项目构建时已选择安装pinia,下面是使用方法以及持久化存储配置
官网:快速开始 | pinia-plugin-persistedstate
1、安装持久化存储插件 pinia-plugin-persistedstate
npm i pinia-plugin-persistedstate -S
2、main.ts
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const app = createApp(App)
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
app.use(pinia)
app.mount('#app')
3、在/src/store/目录下新建user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
name: 'Tom', // 用户名
age: 18, // 年龄
weight: 60 // 公斤
}),
getters: {
// 获取体重市斤
getWeight: (state) => {
return state.weight * 2
}
},
actions: {
// 修改用户名
changeUserName(name: string) {
this.name = name
}
},
// 持久化插件配置
persist: {
key: 'store-user', // 本地存储key名称
// storage: sessionStorage // 不设置默认存储localStorage
paths: ['name'] // 指定持久化的值
}
})
4、页面调用
pinia-name: {{ name }}
pinia-age: {{ age }}
pinia-市斤: {{ storeUser.getWeight }}
npm i sass -D
使用
官网:Vant 4 - A lightweight, customizable Vue UI library for mobile web apps.
npm i vant -S
移动端适配,兼容不同分辨率的手机
npm i postcss-pxtorem amfe-flexible -D
修改vite.config.ts
import postCssPxToRem from 'postcss-pxtorem'
export default defineConfig({
...
css: {
postcss: {
plugins: [
postCssPxToRem({
rootValue: 75, // 1rem的大小
propList: ['*'], // 需要转换的属性,这里选择全部都进行转换
minPixelValue: 2 // 最小px为2,如果设置1px则不转rem
})
]
}
}
...
})
在main.ts引入amfe-flexible
import 'amfe-flexible'
官网:axios
npm i axios -S
封装axios方法,新建/src/utils/request.ts文件
import axios from 'axios'
import type { AxiosInstance, AxiosError, AxiosResponse } from 'axios'
import { showToast } from 'vant'
const service: AxiosInstance = axios.create({
// import.meta.env.DEV 判断是否为本地环境
baseURL: import.meta.env.DEV ? '/api' : 'http://www.baidu.com',
timeout: 30000
})
/* 请求拦截器 */
service.interceptors.request.use(
(config) => {
// 登录状态鉴权
// if (token) {
// config.headers.Authorization = `Bearer ${token}`;
// }
return config
},
(error: AxiosError) => {
showToast(error.message)
return Promise.reject(error)
}
)
/* 响应拦截器 */
service.interceptors.response.use(
(response: AxiosResponse) => {
const { code, message, data } = response.data
// 根据自定义错误码判断请求是否成功
if (code === '0') {
// 将组件用的数据返回
return data
} else {
// 处理业务错误。
showToast(message)
return Promise.reject(new Error(message))
}
},
(error: AxiosError) => {
// 处理 HTTP 网络错误
let message = ''
// HTTP 状态码
const status = error.response?.status
switch (status) {
case 401:
message = 'token 失效,请重新登录'
// 这里可以触发退出的 action
break
case 403:
message = '拒绝访问'
break
case 404:
message = '请求地址错误'
break
case 500:
message = '服务器故障'
break
default:
message = '网络连接故障'
}
showToast(message)
return Promise.reject(error)
}
)
/* 导出封装的请求方法 */
export const http = (options: any) => {
return new Promise((resolve, reject) => {
// 方法一:get和delete请求,将请求体转换为queryString形式拼接在url
// if (!options.method || options.method === 'get' || options.method === 'delete') {
// if (options.data) {
// options.url = options.url + '?' + new URLSearchParams(options.data).toString()
// }
// }
// 方法二:get和delete请求,使用params参数传参,post和put使用data参数
const serviceOpt: any = {}
if (!options.method || options.method === 'get' || options.method === 'delete') {
serviceOpt.params = options.data
} else {
serviceOpt.data = options.data
}
service({
method: options.method || 'get',
url: options.url,
...serviceOpt
})
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
将封装的http方法绑定到全局变量
打开/src/mian.ts
import { http } from '@/utils/request'
app.config.globalProperties.$http = http
在vue文件使用
npm run dev执行后,只显示了Local: http://localhost:5173/,没有显示局域网ip地址,不方便局域网真机调试,需要配置启动host为0.0.0.0
打开vite.config.ts
export default defineConfig({
server: {
// port: 8080, // 启动端口号
host: '0.0.0.0' // 启动显示局域网ip
}
})
测试环境真机调试请参考:
H5移动端调试工具_不求甚解bc的博客-CSDN博客
1、获取系统环境变量
import.meta.env.DEV // 开发环境:true
import.meta.env.PROD // 生产环境:true
import.meta.env.MODE // 开发环境:development 生产环境:production
...
2、获取命令行自定义环境变量
npm run dev --env=test
打开vite.config.ts
const env = process.env.npm_config_env || 'dev'
export default defineConfig({
define: {
app_env: JSON.stringify(env)
}
})
在项目代码中使用,比如main.ts / index.vue
console.log(app_env) // 打印结果:test
注意:直接使用环境变量会提示变量未声明,需要在 env.d.ts 或 vite-env.d.ts 文件中添加类型声明
declare const app_env: string
vite.config.ts
export default defineConfig({
server: {
proxy: {
// 带选项写法:http://localhost:5173/api/bar -> http://jsonplaceholder.typicode.com/bar
'/api': {
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
vue3全局api组件_vue3 全局弹窗_不求甚解bc的博客-CSDN博客
vue路由中间件_不求甚解bc的博客-CSDN博客
Apache,Nginx部署vue/react项目_apached发布 react_不求甚解bc的博客-CSDN博客
jenkins部署vue/react项目_jenkins部署vue项目_不求甚解bc的博客-CSDN博客
jenkins分环境部署vue/react项目_不求甚解bc的博客-CSDN博客
jenkins流水线部署H5项目_jenkins部署h5_不求甚解bc的博客-CSDN博客
web前端灰度部署_不求甚解bc的博客-CSDN博客