前言
初衷
在这里分享一下公司自己的vue3项目从0到1创建的过程,包括其中遇到的一些问题和解决方式,以及一些能够提高我们开发效率的小技巧。如果又不好或者可以改进的地方,欢迎大家指正。
使用背景
当时还没有出vu3.1的版本,出于稳定性考虑,当时使用的是vue3.0.0版本,当时是觉得这个版本兼容了2.x的写法(当然我们都是推荐是3的写法,对于没有接触过3.x版本的开发同学会更友好,让他们能有一个慢慢适应过程。)
项目介绍
包管理工具
- 建议使用 yarn,也是 vue-cli4.0+ 默认工具(我用的是@vue/cli 4.5.13)
主要用到的库
- vue 全家桶 vue3 + vue-router + vuex + typescript + ant-design-vue + less
- http 请求:axios
- ui 库:ant-design-vue
- 提交规范:git cz commitizen
- 版本更改历史: changelog(暂无)
- 代码检查:eslint+eslint-typescript,格式化:prettier.
- webpack 插件:terser-webpack-plugin(压缩文件)webpack-bundle-analyzer(打包文件分析)
- 数据持久化:使用vuex-persistedstate包实现数据持久化
代码基础架构说明
|-- 根目录
|-- dist 项目 build 之后的文件夹
|-- public 项目静态资源,不经过 webpack,以及默认的模版,适合存放第三方压缩好的资源
|-- src 主要的开发目录
| |-- @types 项目共用的 type
| |-- App.vue 页面渲染根节点
| |-- main.ts 入口文件
| |-- shims-vue.d.ts vue 文件类型的 type
| |-- services http 请求相关
| | |-- config 请求配置相关
| | | |-- axios.ts 业务请求封装
| | | |-- download.ts 文件下载方法封装
| | | |-- plugin.ts 相关插件封装
| | | |-- prefix.ts 静态网关头配置
| | |-- modules 各个模块请求接口配置
| | | |-- moduleA A模块接口
| | | |-- moduleB B模块接口
| |-- assets 存放静态资源,这个文件夹下的文件会走 webpack 压缩流程
| |-- components
| | |-- global 全局组件放在这里 最好按功能类型划分文件夹(配置了子文件夹一会递归全局注册)
| | |-- index.ts 全局组件自动注册脚本
| |-- config 全局静态配置
| |-- layout 页面页面骨架
| |-- plugins 存放第三方插件
| | |-- index.ts 插件挂载入口
| | |-- antd.ts antd组件注册入口
| |-- router 路由
| | |-- index.ts 路由入口
| | |-- ... 其他模块路由配置,会自动装载
| |-- store vuex
| | |-- modules 多个模块
| | |-- index.ts 自动装载模块
| | |-- app app 模块
| |-- styles 全局样式, ui 库主题样式
| | |-- antd.less
| | |-- reset.less
| | |-- index.less
| | |-- normalize.css 标准化各个浏览器差异
| | |-- var.less 主题配置文件
| |-- utils 常用函数以及其他有用工具
| | |-- common.ts
| |-- views 页面级组件
| |-- Home.vue 正常页面
| |-- Test.vue
|-- .env.development 开发环境配置
|-- .env.preview 测试环境配置
|-- .env.production 生产环境配置
|-- .eslintignore eslint 要忽略的文件夹
|-- .eslintrc.js eslint 规则配置
|-- .gitignore git 忽略的文件
|-- .prettierrc.js 格式化插件配置 可以按照公司规范定制
|-- README.md 项目说明
|-- .cz-config 自定义git-commit配置信息
|-- babel.config.js babel 设置 (包含Ui框架的按需引入配置)
|-- global.d.ts 全局的 type
|-- package.json npm 配置
|-- tsconfig.json typescript 配置
|-- typedoc.json 文档配置文件
|-- vue.config.js vue-cli 脚手架配置文件
|-- 根目录
|-- dist 项目 build 之后的文件夹
|-- public 项目静态资源,不经过 webpack,以及默认的模版,适合存放第三方压缩好的资源
|-- src 主要的开发目录
| |-- @types 项目共用的 type
| |-- App.vue 页面渲染根节点
| |-- main.ts 入口文件
| |-- shims-vue.d.ts vue 文件类型的 type
| |-- services http 请求相关
| | |-- config 请求配置相关
| | | |-- axios.ts 业务请求封装
| | | |-- download.ts 文件下载方法封装
| | | |-- plugin.ts 相关插件封装
| | | |-- prefix.ts 静态网关头配置
| | |-- modules 各个模块请求接口配置
| | | |-- moduleA A模块接口
| | | |-- moduleB B模块接口
| |-- assets 存放静态资源,这个文件夹下的文件会走 webpack 压缩流程
| |-- components
| | |-- global 全局组件放在这里 最好按功能类型划分文件夹(配置了子文件夹一会递归全局注册)
| | |-- index.ts 全局组件自动注册脚本
| |-- config 全局静态配置
| |-- layout 页面页面骨架
| |-- plugins 存放第三方插件
| | |-- index.ts 插件挂载入口
| | |-- antd.ts antd组件注册入口
| |-- router 路由
| | |-- index.ts 路由入口
| | |-- ... 其他模块路由配置,会自动装载
| |-- store vuex
| | |-- modules 多个模块
| | |-- index.ts 自动装载模块
| | |-- app app 模块
| |-- styles 全局样式, ui 库主题样式
| | |-- antd.less
| | |-- reset.less
| | |-- index.less
| | |-- normalize.css 标准化各个浏览器差异
| | |-- var.less 主题配置文件
| |-- utils 常用函数以及其他有用工具
| | |-- common.ts
| |-- views 页面级组件
| |-- Home.vue 正常页面
| |-- Test.vue
|-- .env.development 开发环境配置
|-- .env.preview 测试环境配置
|-- .env.production 生产环境配置
|-- .eslintignore eslint 要忽略的文件夹
|-- .eslintrc.js eslint 规则配置
|-- .gitignore git 忽略的文件
|-- .prettierrc.js 格式化插件配置 可以按照公司规范定制
|-- README.md 项目说明
|-- .cz-config 自定义git-commit配置信息
|-- babel.config.js babel 设置 (包含Ui框架的按需引入配置)
|-- global.d.ts 全局的 type
|-- package.json npm 配置
|-- tsconfig.json typescript 配置
|-- typedoc.json 文档配置文件
|-- vue.config.js vue-cli 脚手架配置文件
项目架构github地址:github.com/XiaoRIGE/vu… 该项目开箱即用,如果对你有帮助,欢迎star
项目中的一些小技巧分享
配置全局主题样式
依赖的包是 style-resources-loader、vue-cli-plugin-style-resources-loader,目的是为了在单文件中使用时不再需要每次都去做引入操作。
-
- 安装对应的依赖
yarn add style-resources-loader vue-cli-plugin-style-resources-loader --dev
或者
npm i style-resources-loader vue-cli-plugin-style-resources-loader --save-dev
-
- vue.config.js中配置
pluginOptions: {
"style-resources-loader": {
preProcessor: "less",
patterns: ["./src/styles/var.less"],
},
},
-
- 重启项目,文件中使用变量文件
自动化注册(批处理脚本)
首先你得知道这个函数,以及对应的参数含义,了解了之后你大概也能知道他能帮我们做什么了。
require.context(directory,useSubdirectories,regExp)
- directory:表示检索的目录
- useSubdirectories:表示是否检索子文件夹
- regExp:匹配文件的正则表达式,一般是文件名
使用require.context实现一些自动注册脚本,减少重复劳动,比如:
- 批量引入并注册组件(只要将组件放在components文件夹内,就能实现自动注册),全局注册组件也是同理。
<template>
<div class="test">
<h1>test</h1>
<Component-A />
<Component-B />
<Component-C />
</div>
</template>
<script lang="ts">
const path = require("path");
const files = require.context("./components", false, /\.vue$/);
const modules: any = {};
files.keys().forEach((key) => {
const name = path.basename(key, ".vue");
modules[name] = files(key).default || files(key);
});
import { defineComponent } from "vue";
export default defineComponent({
name: "test",
components: modules,
setup() {
return {};
},
});
</script>
<style lang="less" scoped>
.test {
}
</style>
- 动态引入vuex的module
const files = require.context('.', true, /\.ts$/);
const modules: any = {};
files.keys().forEach(key => {
if (key === './index.ts') return;
const path = key.replace(/(\.\/|\.ts)/g, '');
const [namespace, imported] = path.split('/');
if (!modules[namespace]) {
modules[namespace] = {
namespaced: true,
};
}
modules[namespace][imported] = files(key).default;
});
export default modules;
对应的目录结构如下
当然,项目中还有很多地方可以举一反三的,能够帮我们省去很多重复操作的时间。
vuex使用方法升级
通过对module中模块写法进行统一,然后使用工具函数实现统一操作。
- 首先上目录结构如下
- 配置工具函数
/**
* @description setStoreState -方法是一个 mutaitions 的操作
* @type {T} T - 你要更改的模块的类型
* @param {string} module - 要操作的state 的 module 名
* @param {string} key - 要操作的state 的 module 下的 key 值
* @param {any} value - 当有 msg 参数时,视为赋值操作,触发 mutation,msg 则为要复制的数据.
* @example 如果需要更改 app 模块下的 theme为 dark,这样使用:setStoreState('app','theme','dark')
* @example 目前只支持更改 module 的 state 第一层,不支持单独修改深层嵌套的 key,如需更改,请直接替换第一层的对象
* 如
* ``` const state = {
* name: {
* firstName:'jack',
* lastName:'Ma'
* }
* }
* ```
* 想要单独修改 firstName,直接使用 setStoreState<AppStateType>('app','name',{firstName:'modifiedName',lastName:'Ma'})
*/
export const setStoreState = function setStoreState<T>(
module: ModuleNameType,
key: keyof T,
value: any
) {
store.commit({
type: `${module}/__set`,
key,
val: value
});
};
/**
* @description 封装 dispatch 方法
* @type {T} T 你要派发actions的模块的类型
* @example 使用方法如下 const result = await dispatchActions<UserActionsType>('console','refreshToken',1)
*/
export const dispatchAction = function dispatchAction<T>(
module: ModuleNameType,
key: keyof T,
value?: any
) {
store.dispatch(`${module}/${key}`, value);
};
/**
* @description 封装 dispatch 方法
* @type {T} T 你要获取 getters的模块的类型
* @example 使用方法如下 const result = getStoreGetter<ConsoleGetterType>('console','list')
*/
export const getStoreGetter = function getStoreGetter<T>(
module: ModuleNameType,
key: keyof T
) {
return store.getters[`${module}/${key}`];
};
配置commit规范
在一个开发团队中,前端开发的代码管理越来越规范化、工程化,而代码commit更是需要一个统一的规范去约束,保证代码commit时的规范性。尤其多人参与一个项目开发时,大家的代码commit风格不相同,不便于后续的代码统一管理和可读性;所以良好的git commit风格是很重要的。在这里就介绍几个我们项目中使用到的工具
依赖介绍
-
commitlint 很多时候我们提交代码时,运行
git commmit -m 'xxx'
即可,而commitlint可以对message进行约束,是判断message是否符合格式要求的工具。commitlint 推荐结合config-conventional 配置使用,正确的提交格式是:git commit -m <type>[optional scope]: <description>
-
commitizen+cz-customizable commitizen是规范commit message的工具,提供选择的commit message类型,快速生成commit message说明;而cz-customizable作为它的适配器,可以定制提交说明信息的type。
-
husky + lint-staged 进行代码质量规范检查时,husky可以阻止不符合规范的commit,push等操作,husky是注册在git pre-commit钩子函数被调用时执行lint-staged,pre-commit 钩子在git commit 时就会触发。lint-staged对暂存区中有改动的文件根据ESLint 和 Prettier的规则进行检测;eslint+husky+prettier+lint-staged工具的配合使用可以规范我们的代码格式统一,进行代码格式检查 和代码美化,保证代码质量。
配置步骤
- 安装commitlint
npm install @commitlint/cli @commitlint/config-conventional -D
在根目录下新建.commitlintrc.js或者commitlint.config.js文件
module.exports = {
extends: ['@commitlint/config-conventional']
};
- 安装commitizen+cz-customizable
npm install commitizen cz-customizable -D
在根目录下新建.cz-config.js文件,配置commit type。
// 相关配置:https://github.com/leoforfree/cz-customizable
module.exports = {
types: [
{
value: 'feat',
name: '✨ feat(新功能)'
},
{
value: 'fix',
name: '