web项目开发模板
web 项目的工程模板(create-web-template),通过 yb-cli 快速创建
# 默认主页的效果
# 技术栈
vue2 + vue-router3 + axios + element-ui + yb-components + scss + echarts
构建环境由 vite + vue-cli5(webpack5)组成,开发过程用 vite 或 vue-cli 都可以,打包生产用 vue-cli
# 安装依赖
# 修改npm源为私服地址
npm config set registry http://192.168.1.100:8081/repository/npm-all
# 安装依赖
npx yarn
2
3
4
5
# 命令
# 用vite开发运行
npm run dev
# 用vue-cli开发运行
npm run serve
# 用vue-cli打包
npm run build
# 用vite打包, 只支持IE11+
npm run build2
# eslint 检测
npm run lint
2
3
4
5
6
7
8
9
10
11
12
13
14
# git 说明
开发分支:dev,稳定分支:master , 始终由 dev 向 master 合并,tag 的版本号规范遵循语义化版本号 (opens new window)
# 目录结构
├── /.husky/ # husky管理git hooks的目录,默认添加了 pre-commit 和 commit-msg 两个钩子
├── /dist/ # 项目打包输出目录
├── /public/ # 跟运行不太相关的东西
├── /src/ # 项目开发源码目录
│ ├── /Api/ # 后台接口文件夹,
│ ├── /assets/ # 资源文件:图片,iconfont,
│ │ ├── /iconfont/ # 来自 http://www.iconfont.cn/?spm=a313x.7781069.1998910419.d4d0a486a
│ │ └── /images/ # 图片
│ ├── /components/ # 当前项目的通用组件如 : example.vue
│ ├── /scss/ # 通用样式文件夹
│ │ ├── theme-vars.scss #主题变量,默认来自"element-ui/packages/theme-chalk/src/common/var.scss"
│ │ └── index.scss
│ ├── /demanded/ # 按需引入第三方的目录
│ │ ├── echarts.js # echarts图表库的按需引入(需要手动)
│ │ └── index.js # 启动开发(npm run dev|npm run serve)后自动生成,自动搜索src的.vue内使用了"<el-"开头的标签生成element-ui组件的按需引入并全局注册组件
│ ├── /pages/ # 路由组件页面目录,每个路由页面都是一个目录,里面应该包含一个*.route.js和index.vue
│ │ └── /main/ #
│ │ │ ├──_.L1.route.js # main页面对应的 _.L1.route.js, L1表示路由层级的意思,这里的 '_' 只是提升文件顺序,让.route.js始终在最前面
│ │ │ └──index.vue # 路由组件
│ ├── /router/ # 注册路由目录
│ │ ├── /_requireRouteChilds/ # 路由去中心化的,一级路由自动加载的逻辑,一旦定下来不需要常改动
│ │ │ ├──getChildren.vite.js # vite自动加载/pages/目录下的*.L1.route.js
│ │ │ ├──getChildren.webpack.js # webpack自动加载/pages/目录下的*.L1.route.js
│ │ │ └──index.js # 此文件的内容由vite启动还是webpack启动决定,自动改变
│ │ └── index.js # 创建路由实例的入口,引入 ./_requireRouteChilds 取的路由配置
│ ├── /utils/ # 当前项目通用工具目录
│ │ ├── index.js
│ │ └── httpAjax.js # ajax库: 对 axios 的添加拦截器等操作
│ ├── App.vue # 根组件
│ ├── app.js # 整个单页面的内容入口,提供createApp和destroyApp方法,
│ ├── main.js # vite启动的入口文件,调用createApp创建vue实例
│ └── webpack-entry.js # webpack启动的入口文件,打包后会将app.js作为一个模块生成一个remote-entry.js
├── .eslintignore # eslint忽略检测的配置
├── .gitgnore # git忽略检测的配置
├── .prettierrc # prettier配置
├── commitlint.config.js # commitlint配置
├── postcss.config.js # postcss配置
├── index.html # 单页面唯一的html,用vite启动会通过@yb/replace-require-childs添加 <link rel="icon" href="/src/assets/favicon.ico" />、<script type="module" src="/src/main.js"></script>
├── babel.config.js # babel配置,只会在vue-cli使用
├── package.json #
├── README.md # 每个git工程要写说明
├── vue.config.js # vue-cli配置文件
└── vite.config.js # vite配置文件
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 路由去中心化
"src/router/index.js"只做创建 router 实例和添加全局路由守卫等,路由的配置分散到各个路由组件对应的*.route.js
"src/router/_requireRouteChilds"会自动引入src/pages/**/*.L1.route.js
,例如"src/pages/main/index.vue"是一个一级路由组件,就有对应一个src/pages/main/_.L1.route.js
, L1
表示一级路由,以此类推会有L2
、L3
# _requireRouteChilds
_requireRouteChilds
的定义主要作用是自动引入分散在 pages 的路由配置
存在"_requireRouteChilds/getChildren.vite.js"和"_requireRouteChilds/getChildren.webpack.js",是因为 vite 和 webpack 的匹配性导入多个模块的语法是不一样的,
为了无论从 vite 还是 webpack 启动都能达到相同的效果,"_requireRouteChilds/index.js"会根据 vite 还是 webpack 决定export { default as routerChildren } from "./getChildren.vite.js"
还是export { default as routerChildren } from "./getChildren.webpack.js"
所以在定义_requireRouteChilds
时,只需定义"_requireRouteChilds/getChildren.vite.js"和"_requireRouteChilds/getChildren.webpack.js"
# 按需导入
当使用 element-ui 这类组件包的时候,禁用以下方式
import Vue from 'vue';
import ElementUI from 'element-ui';
vue.use(ElementUI);
2
3
这样会打包 element-ui 的所有组件,为了按需打包组件,使用插件@yb/vite-plugin-create-demanded
将源码中的.js
、.jsx
、.vue
的文件会进行检索,检索的规则如下
<!-- 满足 "<el-" 取得 "ElButton" -->
<el-button type="primary">按钮<el-button></el-button></el-button>
2
// 满足 "('el-" 取得 "ElButton"
h('el-button', {});
2
自动生成src/demanded/index.js
,内容如下
// 按需引入组件
import Vue from 'vue';
import ElButtonGroup from 'element-ui/lib/button-group.js';
import 'element-ui/packages/theme-chalk/src/button-group.scss';
import ElButton from 'element-ui/lib/button.js';
import 'element-ui/packages/theme-chalk/src/button.scss';
import ElInput from 'element-ui/lib/input.js';
import 'element-ui/packages/theme-chalk/src/input.scss';
const ElementUiComponents = [ElButtonGroup, ElButton, ElInput];
const components = [ElementUiComponents];
// 全局注册组件
window.vueComponentFegisteredNames = window.vueComponentFegisteredNames || [];
components.forEach((cs) => {
cs.forEach((item) => {
if (window.vueComponentFegisteredNames.includes(item.name)) {
return;
}
if (item.name) {
Vue.component(item.name, item);
window.vueComponentFegisteredNames.push(item.name);
}
});
});
Vue.use(ElLoading.directive);
Vue.prototype.$loading = ElLoading.service;
Vue.prototype.$msgbox = ElMessageBox;
Vue.prototype.$alert = ElMessageBox.alert;
Vue.prototype.$confirm = ElMessageBox.confirm;
Vue.prototype.$prompt = ElMessageBox.prompt;
Vue.prototype.$notify = ElNotification;
Vue.prototype.$message = ElMessage;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
在入口 app.js 需要 import './demanded'
,@yb/vite-plugin-create-demanded
的使用请查看 vite.config.js
# 状态管理
这里没有默认使用 vuex,请判断在当前项目中使用状态管理库的必要性,而不是滥用,如果只是少量且简单的组件间的状态共享,可以直接使用vue 官网描述的简单的状态共享模式 (opens new window)。
# 后台 api 管理
后台接口地址统一在 src/Api
目录管理,需要分类的 api,新建 *.api.js 再统一引入到 src/Api/index.js
,然后在组件中 import {} from "@/Api" 使用
同理,如果使用了 vuex,需要在 actions 中使用 api ,引过去用即可
src/Api/*.api.js
不直接 import axios from "axios", 而是引入 src/utils/httpAjax.js
去声明接口函数
在src/utils/httpAjax.js
中管理 axios 的实例,添加 axios 拦截器等操作
# 预设多主题编译
在 src/scss
目录统一管理 scss 的变量,如果需要作多主题的编译,先定义多份 scss 变量文件
假设定义了两个变量文件: src/scss/theme-blue.scss 、src/scss/theme-red.scss,
在 vue.config.js 中添加如下配置:
const path = require('path');
const { getSass } = require('@zougt/some-loader-utils');
const multipleScopeVars = [
{
scopeName: 'theme-blue',
path: path.resolve('src/scss/theme-blue.scss'),
},
{
scopeName: 'theme-red',
path: path.resolve('src/scss/theme-red.scss'),
},
];
module.exports = {
css: {
loaderOptions: {
scss: {
// 这里的选项会传递给 sass-loader
implementation: getSass({
getMultipleScopeVars: (sassOptions) => multipleScopeVars,
}),
},
},
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
在 vite.config.js 中添加如下配置:
import path from 'path';
import themePreprocessorPlugin from '@zougt/vite-plugin-theme-preprocessor';
const multipleScopeVars = [
{
scopeName: 'theme-blue',
path: path.resolve('src/scss/theme-blue.scss'),
},
{
scopeName: 'theme-red',
path: path.resolve('src/scss/theme-red.scss'),
},
];
export default {
plugins: [
themePreprocessorPlugin({
scss: {
multipleScopeVars,
// 默认取 multipleScopeVars[0].scopeName
defaultScopeName: '',
// 在生产模式是否抽取独立的主题css文件,extract为true以下属性有效
extract: true,
// 独立主题css文件的输出路径,默认取 viteConfig.build.assetsDir 相对于 (viteConfig.build.outDir)
outputDir: '',
// 会选取defaultScopeName对应的主题css文件在html添加link
themeLinkTagId: 'theme-link-tag',
// "head"||"head-prepend" || "body" ||"body-prepend"
themeLinkTagInjectTo: 'head',
// 是否对抽取的css文件内对应scopeName的权重类名移除
removeCssScopeName: false,
// 可以自定义css文件名称的函数
customThemeCssFileName: (scopeName) => scopeName,
},
}),
],
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
更多请查看@zougt/some-loader-utils (opens new window) 和 @zougt/vite-plugin-theme-preprocessor (opens new window)