From 36613cd17bd56508f38f9ba5918a3fb2ada6fdf5 Mon Sep 17 00:00:00 2001
From: fonghehe <331002675@qq.com>
Date: Fri, 19 Aug 2022 18:23:00 +0800
Subject: [PATCH] docs: init document
---
.github/workflows/deploy.yml | 25 ++
.gitignore | 1 +
README.md | 496 +++++++++++++++++++++
docs/.vitepress/config.js | 99 +++++
docs/.vitepress/theme/custom.css | 61 +++
docs/.vitepress/theme/index.js | 4 +
docs/guide/edit.md | 19 +
docs/guide/index.md | 23 +
docs/guide/start.md | 17 +
docs/guide/vue2/alias.md | 19 +
docs/guide/vue2/axios.md | 106 +++++
docs/guide/vue2/base.md | 36 ++
docs/guide/vue2/bundle.md | 22 +
docs/guide/vue2/chunks.md | 45 ++
docs/guide/vue2/console.md | 34 ++
docs/guide/vue2/env.md | 84 ++++
docs/guide/vue2/externals.md | 84 ++++
docs/guide/vue2/ie.md | 30 ++
docs/guide/vue2/lint.md | 165 +++++++
docs/guide/vue2/proxy.md | 36 ++
docs/guide/vue2/rem.md | 69 +++
docs/guide/vue2/router.md | 34 ++
docs/guide/vue2/sass.md | 104 +++++
docs/guide/vue2/start.md | 17 +
docs/guide/vue2/vant.md | 49 +++
docs/guide/vue2/vuex.md | 45 ++
docs/guide/vue2/vw.md | 61 +++
docs/guide/vue3/alias.md | 21 +
docs/guide/vue3/axios.md | 67 +++
docs/guide/vue3/base.md | 45 ++
docs/guide/vue3/env.md | 13 +
docs/guide/vue3/lint.md | 3 +
docs/guide/vue3/pinia.md | 22 +
docs/guide/vue3/proxy.md | 13 +
docs/guide/vue3/router.md | 29 ++
docs/guide/vue3/start.md | 14 +
docs/guide/vue3/ui.md | 58 +++
docs/guide/vue3/viewport.md | 76 ++++
docs/guide/vue3/vite.md | 17 +
docs/index.md | 34 ++
package.json | 10 +
pnpm-lock.yaml | 710 +++++++++++++++++++++++++++++++
42 files changed, 2917 insertions(+)
create mode 100644 .github/workflows/deploy.yml
create mode 100644 .gitignore
create mode 100644 README.md
create mode 100644 docs/.vitepress/config.js
create mode 100644 docs/.vitepress/theme/custom.css
create mode 100644 docs/.vitepress/theme/index.js
create mode 100644 docs/guide/edit.md
create mode 100644 docs/guide/index.md
create mode 100644 docs/guide/start.md
create mode 100644 docs/guide/vue2/alias.md
create mode 100644 docs/guide/vue2/axios.md
create mode 100644 docs/guide/vue2/base.md
create mode 100644 docs/guide/vue2/bundle.md
create mode 100644 docs/guide/vue2/chunks.md
create mode 100644 docs/guide/vue2/console.md
create mode 100644 docs/guide/vue2/env.md
create mode 100644 docs/guide/vue2/externals.md
create mode 100644 docs/guide/vue2/ie.md
create mode 100644 docs/guide/vue2/lint.md
create mode 100644 docs/guide/vue2/proxy.md
create mode 100644 docs/guide/vue2/rem.md
create mode 100644 docs/guide/vue2/router.md
create mode 100644 docs/guide/vue2/sass.md
create mode 100644 docs/guide/vue2/start.md
create mode 100644 docs/guide/vue2/vant.md
create mode 100644 docs/guide/vue2/vuex.md
create mode 100644 docs/guide/vue2/vw.md
create mode 100644 docs/guide/vue3/alias.md
create mode 100644 docs/guide/vue3/axios.md
create mode 100644 docs/guide/vue3/base.md
create mode 100644 docs/guide/vue3/env.md
create mode 100644 docs/guide/vue3/lint.md
create mode 100644 docs/guide/vue3/pinia.md
create mode 100644 docs/guide/vue3/proxy.md
create mode 100644 docs/guide/vue3/router.md
create mode 100644 docs/guide/vue3/start.md
create mode 100644 docs/guide/vue3/ui.md
create mode 100644 docs/guide/vue3/viewport.md
create mode 100644 docs/guide/vue3/vite.md
create mode 100644 docs/index.md
create mode 100644 package.json
create mode 100644 pnpm-lock.yaml
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 0000000..892455c
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,25 @@
+name: deployment
+
+on:
+ push:
+ branches: ["docs"]
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16
+ cache: yarn
+ - run: yarn install --frozen-lockfile
+
+ - name: Build
+ run: yarn docs:build
+
+ - name: Deploy
+ uses: peaceiris/actions-gh-pages@v3
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: docs/.vitepress/dist
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b512c09
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ed7ccc3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,496 @@
+# vue-h5-template
+
+基于 vue3 + vite + (nutui or varlet or vant) + sass + viewport 适配方案 +axios 封装,构建手机端模板脚手架
+
+如果你不熟悉 vue3,想继续使用 vue2 开发的,可以[点这里](https://github.com/sunniejs/vue-h5-template/tree/vue2-h5-template)来获取 vue2-h5-template
+
+掘金: [移动端适配方案](https://juejin.cn/post/7018433228591595550)
+
+
+
+
+
+### Node 版本要求
+
+推荐你使用 NodeJs 14+的版本,毕竟技术日新月异。你可以使用 [nvm](https://github.com/nvm-sh/nvm) 或 [nvm-windows](https://github.com/coreybutler/nvm-windows) 在同一台电脑中管理多个 Node 版本。
+
+本示例 Node.js 14.19.0
+
+### 启动项目(强烈推荐使用 yarn)
+
+```bash
+
+git clone https://github.com/sunniejs/vue-h5-template.git
+
+cd vue-h5-template
+
+yarn install
+
+yarn dev
+```
+
+目录
+
+- [√ vite](#vite)
+- [√ 配置多环境变量](#env)
+- [√ viewport 适配方案](#viewport)
+- [√ 多 UI 组件库供选择](#ui)
+- [√ Pinia 状态管理](#Pinia)
+- [√ vue-router 4](#router)
+- [√ axios 封装及接口管理](#axios)
+- [√ vite.config.ts 基础配置](#base)
+- [√ alias](#alias)
+- [√ proxy 跨域](#proxy)
+- [√ Eslint+Pettier+stylelint 统一开发规范 ](#lint)
+
+### ✅ vite
+
+基于原生 ES 模块提供了丰富的内建功能,如速度快到惊人的模块热更新(HMR),使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。更多关于[vite](https://cn.vitejs.dev/guide/)
+
+模版集成了如下的 vite 插件
+
+- unplugin-auto-import(按需加载,自动引入)
+- unplugin-vue-components(按需加载,自动引入组件)
+- vite-plugin-compression(开启.gz 压缩)
+- vite-plugin-eruda(控制台,方便移动端调试)
+- vite-plugin-imagemin(图片压缩)
+- vite-plugin-mock(引入 mockjs,本地模拟接口)
+- vite-plugin-pages(动态生成路由)
+- vite-plugin-progress(构建显示进度条)
+- vite-plugin-restart(监听配置文件修改自动重启 Vite)
+- vite-plugin-style-import(按需引入样式文件)
+- vite-plugin-svg-icons(加载 SVG 文件,自动引入)
+
+### ✅ 配置多环境变量
+
+`package.json` 里的 `scripts` 配置 `dev` `dev:test` `dev:prod` ,通过 `--mode xxx` 来执行不同环境
+
+- 通过 `yarn dev` 启动本地环境参数 , 执行 `development`
+- 通过 `yarn dev:test` 启动测试环境参数 , 执行 `test`
+- 通过 `yarn dev:prod` 启动正式环境参数 , 执行 `prod`
+
+```javascript
+"scripts": {
+ "dev": "vite",
+ "dev:test": "vite --mode test",
+ "dev:prod": "vite --mode production",
+}
+```
+
+[▲ 回顶部](#top)
+
+### ✅ viewport 适配方案
+
+不用担心,项目已经配置好了 `viewport` 适配,下面仅做介绍:
+
+- [cnjm-postcss-px-to-viewport](https://github.com/cnjm/postcss-px-to-viewport) 是一款 `postcss` 插件,用于将单位转化为 `vw`, 现在很多浏览器对`vw`的支持都很好,适配首选方案。
+
+##### PostCSS 配置
+
+下面提供了一份基本的 `postcss` 配置,可以在此配置的基础上根据项目需求进行修改
+
+```javascript
+// https://github.com/michael-ciniawsky/postcss-load-config
+module.exports = {
+ plugins: {
+ autoprefixer: { overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8'] },
+ 'cnjm-postcss-px-to-viewport': {
+ unitToConvert: 'px', // 要转化的单位
+ viewportWidth: 750, // UI设计稿的宽度
+ unitPrecision: 6, // 转换后的精度,即小数点位数
+ propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
+ viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
+ fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
+ minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
+ mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
+ replace: true, // 是否转换后直接更换属性值
+ include: [],
+ exclude: [], // 设置忽略文件,用正则做目录名匹配
+ customFun: ({ file }) => {
+ // 这个自定义的方法是针对处理vant组件下的设计稿为375问题
+ const designWidth = judgeComponent(file) ? 375 : 750;
+ return designWidth;
+ },
+ },
+};
+```
+
+**新手必看,老鸟跳过**
+
+很多小伙伴会问我,适配的问题, 因为我们使用的是 Vant UI,所以必须根据 Vant UI 375 的设计规范走,一般我们的设计会将 UI 图上传到蓝湖,我们就可以需要的尺寸了。下面就大搞普及一下 rem。
+
+我们知道 `1rem` 等于 `html` 根元素设定的 `font-size` 的 `px` 值。Vant UI 设置 `rootValue: 37.5` , 你可以看到在 iPhone 6 下看到 ( `1rem 等于 37.5px` ):
+
+```html
+
+```
+
+切换不同的机型,根元素可能会有不同的 `font-size` 。当你写 css px 样式时,会被程序换算成 `rem` 达到适配。
+
+因为我们用了 Vant 的组件,需要按照 `rootValue: 37.5` 来写样式。
+
+举个例子:设计给了你一张 750px \* 1334px 图片,在 iPhone6 上铺满屏幕, 其他机型适配。
+
+- 当`rootValue: 75` , 样式 `width: 750px;height: 1334px;` 图片会撑满 iPhone6 屏幕,这个时候切换其他机型,图片也会跟着撑满。
+- 当`rootValue: 37.5` 的时候,样式 `width: 375px;height: 667px;` 图片会撑满 iPhone6 屏幕。
+
+也就是 iphone 6 下 375px 宽度写 CSS。其他的你就可以根据你设计图,去写对应的样式就可以了。
+
+当然,想要撑满屏幕你可以使用 100%,这里只是举例说明。
+
+```html
+
+
+
+```
+
+[▲ 回顶部](#top)
+
+### ✅ 多 UI 组件库供选择
+
+Vite 构建工具,使用 vite-plugin-style-import 和 unplugin-vue-components/vite 实现按需引入。
+
+#### 安装插件
+
+```bash
+yarn add vite-plugin-style-import -D
+yarn add unplugin-vue-components/vite -D
+```
+
+#### 使用组件库
+
+nutUI 没有按需加载的 resolvers,style 需要自己配置按需加载
+
+在 `config/vite/plugins/styleImport.ts` 设置
+
+```javascript
+ // 按需加载样式文件
+ ...
+ createStyleImportPlugin({
+ resolves: [NutuiResolve()],
+ }),
+ ...
+```
+
+项目在 `src/plugins/nutUI.ts` 下统一管理组件,用哪个引入哪个,无需在页面里重复引用
+
+```javascript
+// 按需全局引入nutUI组件
+import Vue from 'vue';
+import { Button, Cell, CellGroup } from '@nutui/nutui';
+export const nutUiComponents = [Button, Cell, CellGroup];
+
+// 在main.ts文件中引入
+nutUiComponents.forEach((item) => {
+ app.use(item);
+});
+```
+
+vant 和 varlet 可以使用组件按需加载
+
+在`config/vite/plugins/component.ts`下
+
+```javascript
+import { VueUseComponentsResolver, VantResolver, VarletUIResolver } from 'unplugin-vue-components/resolvers';
+...
+resolvers: [VantResolver(), VarletUIResolver()],
+...
+```
+
+#### 不需要某个组件库
+
+nutUI 需删除`src/plugins/nutUI.ts`和`main.ts`文件下的引入
+
+vant 和 varlet 只需删除对应的 resolvers 即可
+
+删除后需全局搜索删除不需要的组件,避免报错
+
+[▲ 回顶部](#top)
+
+### ✅ Pinia 状态管理
+
+下一代 vuex,使用极其方便,ts 兼容好
+
+目录结构
+
+```bash
+├── store
+│ ├── modules
+│ │ └── user.js
+│ ├── index.js
+```
+
+使用
+
+```html
+
+```
+
+[▲ 回顶部](#top)
+
+### ✅ Vue-router
+
+本案例采用 `hash` 模式,开发者根据需求修改 `mode` `base`
+
+**注意**:如果你使用了 `history` 模式, `vue.config.js` 中的 `publicPath` 要做对应的**修改**
+
+前往:[vue.config.js 基础配置](#base)
+
+```javascript
+import Vue from 'vue';
+import { createRouter, createWebHistory, Router } from 'vue-router';
+
+Vue.use(Router);
+export const router = [
+ {
+ name: 'root',
+ path: '/',
+ redirect: '/home',
+ component: () => import('@/layout/basic/index.vue'),
+ },
+];
+
+const router: Router = createRouter({
+ history: createWebHistory(),
+ routes: routes,
+});
+
+export default router;
+```
+
+更多:[Vue Router](https://router.vuejs.org/zh/introduction.html)
+
+[▲ 回顶部](#top)
+
+### ✅ Axios 封装及接口管理
+
+`utils/request.js` 封装 axios , 开发者需要根据后台接口做修改。
+
+- `service.interceptors.request.use` 里可以设置请求头,比如设置 `token`
+- `config.hideloading` 是在 api 文件夹下的接口参数里设置,下文会讲
+- `service.interceptors.response.use` 里可以对接口返回数据处理,比如 401 删除本地信息,重新登录
+
+```javascript
+import axios from 'axios';
+import store from '@/store';
+import { Toast } from 'vant';
+// 根据环境不同引入不同api地址
+import { baseApi } from '@/config';
+// create an axios instance
+const service = axios.create({
+ baseURL: baseApi, // url = base api url + request url
+ withCredentials: true, // send cookies when cross-domain requests
+ timeout: 5000, // request timeout
+});
+
+// request 拦截器 request interceptor
+service.interceptors.request.use(
+ (config) => {
+ // 不传递默认开启loading
+ if (!config.hideloading) {
+ // loading
+ Toast.loading({
+ forbidClick: true,
+ });
+ }
+ if (store.getters.token) {
+ config.headers['X-Token'] = '';
+ }
+ return config;
+ },
+ (error) => {
+ // do something with request error
+ console.log(error); // for debug
+ return Promise.reject(error);
+ },
+);
+// respone拦截器
+service.interceptors.response.use(
+ (response) => {
+ Toast.clear();
+ const res = response.data;
+ if (res.status && res.status !== 200) {
+ // 登录超时,重新登录
+ if (res.status === 401) {
+ store.dispatch('FedLogOut').then(() => {
+ location.reload();
+ });
+ }
+ return Promise.reject(res || 'error');
+ } else {
+ return Promise.resolve(res);
+ }
+ },
+ (error) => {
+ Toast.clear();
+ console.log('err' + error); // for debug
+ return Promise.reject(error);
+ },
+);
+export default service;
+```
+
+#### 接口管理
+
+在 `src/api` 文件夹下统一管理接口
+
+- 你可以建立多个模块对接接口, 比如 `home.js` 里是首页的接口这里讲解 `user.js`
+- `url` 接口地址,请求的时候会拼接上 `config` 下的 `baseApi`
+- `method` 请求方法
+- `data` 请求参数 `qs.stringify(params)` 是对数据系列化操作
+- `hideloading` 默认 `false`, 设置为 `true` 后,不显示 loading ui 交互中有些接口不需要让用户感知
+
+```javascript
+import qs from 'qs';
+// axios
+import request from '@/utils/request';
+//user api
+
+// 用户信息
+export function getUserInfo(params) {
+ return request({
+ url: '/user/userinfo',
+ method: 'post',
+ data: qs.stringify(params),
+ hideloading: true, // 隐藏 loading 组件
+ });
+}
+```
+
+#### 如何调用
+
+```javascript
+// 请求接口
+import { getUserInfo } from '@/api/user.js';
+
+const params = {
+ user: 'sunnie',
+};
+getUserInfo(params)
+ .then(() => {})
+ .catch(() => {});
+```
+
+[▲ 回顶部](#top)
+
+### ✅ vite.config.ts 基础配置
+
+如果你的 `Vue Router` 模式是 hash
+
+```javascript
+publicPath: './',
+```
+
+如果你的 `Vue Router` 模式是 history 这里的 publicPath 和你的 `Vue Router` `base` **保持一致**
+
+```javascript
+publicPath: '/app/',
+```
+
+```javascript
+export default function ({ command }: ConfigEnv): UserConfigExport {
+ const isProduction = command === 'build';
+ return {
+ server: {
+ host: '0.0.0.0',
+ },
+ plugins: [
+ vue(),
+ vueJsx(),
+ createStyleImportPlugin({
+ resolves: [NutuiResolve()],
+ }),
+ eruda(),
+ viteMockServe({
+ mockPath: './src/mock',
+ localEnabled: command === 'serve',
+ logger: true,
+ }),
+ ],
+ css: {
+ preprocessorOptions: {
+ scss: {
+ // 配置 nutui 全局 scss 变量
+ additionalData: `@import "@nutui/nutui/dist/styles/variables.scss";`,
+ },
+ },
+ },
+ };
+}
+```
+
+[▲ 回顶部](#top)
+
+### ✅ 配置 alias 别名
+
+```javascript
+resolve: {
+ alias: [{
+ find: 'vue-i18n',
+ replacement: 'vue-i18n/dist/vue-i18n.cjs.js',
+ },
+ // /@/xxxx => src/xxxx
+ {
+ find: /\/@\//,
+ replacement: pathResolve('src') + '/',
+ },
+ // /#/xxxx => types/xxxx
+ {
+ find: /\/#\//,
+ replacement: pathResolve('types') + '/',
+ },
+ ],
+},
+```
+
+[▲ 回顶部](#top)
+
+### ✅ 配置 proxy 跨域
+
+```javascript
+server: {
+ proxy: {
+ '/api': {
+ target: 'https://baidu.com',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api/, '')
+ }
+ }
+},
+```
+
+[▲ 回顶部](#top)
+
+### ✅ Eslint+Pettier+stylelint 统 ˜ 开发规范
+
+根目录下的`.eslintrc.js`、`.stylelint.config.js`、`.prettier.config.js`内置了 lint 规则,帮助你规范地开发代码,有助于提高团队的代码质量和协作性,可以根据团队的规则进行修改
+
+# 关于我
+
+扫描添加下方的微信并备注加交流群,交流学习,及时获取代码最新动态。
+
+
+
+
+
+
+
+
+
+如果对你有帮助送我一颗珍贵的小星星(づ ̄3 ̄)づ╭❤~
diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js
new file mode 100644
index 0000000..953e2ad
--- /dev/null
+++ b/docs/.vitepress/config.js
@@ -0,0 +1,99 @@
+module.exports = {
+ lang: "zh-CN",
+ title: "Vue-H5-Template",
+ base: "/fastool/",
+ description: "一个开箱即用的vue h5脚手架",
+ lastUpdated: true,
+ head: [
+ // 添加图标
+ ["link", { rel: "icon", href: "/favicon.ico" }],
+ ],
+ themeConfig: {
+ nav: nav(),
+ sidebar: {
+ "/guide/": sidebarGuide(),
+ },
+ socialLinks: [
+ { icon: "github", link: "https://github.com/tobe-fe-dalao/fastool" },
+ ],
+ editLink: {
+ pattern: "https://github.com/tobe-fe-dalao/fastool/tree/doc/docs/:path",
+ text: "在GitHub编辑此页",
+ },
+ footer: {
+ message: "Released under the MIT License.",
+ copyright: "Copyright © 2022-present Fonghehe",
+ },
+ algolia: {
+ appId: "5ZHOMUV2DI",
+ apiKey: "d1de686f0fd4404abc0897093c246ffb",
+ indexName: "vue-h5-template",
+ },
+ },
+};
+
+function nav() {
+ return [
+ { text: "介绍", link: "/guide/" },
+ { text: "掘金", link: "https://juejin.cn/user/3016715636842622" },
+ { text: "加入我们", link: "https://github.com/tobe-fe-dalao/fastool" },
+ ];
+}
+
+function sidebarGuide() {
+ return [
+ {
+ text: "介绍",
+ collapsible: true,
+ items: [
+ { text: "介绍", link: "/guide/" },
+ { text: "快速上手", link: "/guide/start" },
+ { text: "参与编辑", link: "/guide/edit" },
+ ],
+ },
+ {
+ text: "vue3-template",
+ collapsible: true,
+ items: [
+ { text: "vite", link: "/guide/vue3/vite" },
+ { text: "配置多环境变量", link: "/guide/vue3/env" },
+ { text: "viewport 适配方案", link: "/guide/vue3/viewport" },
+ { text: "多UI组件库供选择", link: "/guide/vue3/ui" },
+ { text: "Pinia 状态管理", link: "/guide/vue3/pinia" },
+ { text: "vue-router", link: "/guide/vue3/router" },
+ { text: "axios 封装及接口管理", link: "/guide/vue3/axios" },
+ { text: "vite.config.ts 基础配置", link: "/guide/vue3/base" },
+ { text: "alias", link: "/guide/vue3/base" },
+ { text: "proxy 跨域", link: "/guide/vue3/base" },
+ {
+ text: "Eslint+Pettier+stylelint 统一开发规范",
+ link: "/guide/vue3/lint",
+ },
+ ],
+ },
+ {
+ text: "vue2-template",
+ collapsible: false,
+ items: [
+ { text: "启动项目", link: "/guide//vue2/start" },
+ { text: "配置多环境变量", link: "/guide/vue2/env" },
+ { text: "rem 适配方案", link: "/guide/vue2/rem" },
+ { text: "vw 适配方案", link: "/guide/vue2/vw" },
+ { text: "VantUI 组件按需加载", link: "/guide/vue2/vant" },
+ { text: "Sass 全局样式", link: "/guide/vue2/sass" },
+ { text: "Vuex 状态管理", link: "/guide/vue2/vuex" },
+ { text: "Vue-router", link: "/guide/vue2/router" },
+ { text: "Axios 封装及接口管理", link: "/guide/vue2/axios" },
+ { text: "vue.config.js 基础配置", link: "/guide/vue2/base" },
+ { text: "配置 alias 别名", link: "/guide/vue2/alias" },
+ { text: "配置 proxy 跨域", link: "/guide/vue2/proxy" },
+ { text: "配置 打包分析", link: "/guide/vue2/bundle" },
+ { text: "配置 externals 引入 cdn 资源", link: "/guide/vue2/externals" },
+ { text: "去掉 console.log", link: "/guide/vue2/console" },
+ { text: "splitChunks 单独打包第三方模块", link: "/guide/vue2/chunks" },
+ { text: "添加 IE 兼容", link: "/guide/vue2/ie" },
+ { text: "Eslint+Pettier 统一开发规范", link: "/guide/vue2/lint" },
+ ],
+ },
+ ];
+}
diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css
new file mode 100644
index 0000000..f35cccc
--- /dev/null
+++ b/docs/.vitepress/theme/custom.css
@@ -0,0 +1,61 @@
+:root {
+ --vp-c-brand: #16c5fe;
+ --vp-c-green: #16c5fe;
+ --vp-c-green-light: #109ef7;
+ --vp-c-green-lighter: #109ef7;
+ --vp-c-green-dark: #109ef7;
+ --vp-c-green-darker: #109ef7;
+}
+
+.dark {
+ --vp-c-bg: #000;
+ --vp-code-block-bg: #111;
+ --vp-c-bg-alt: rgba(0, 0, 0, 0.5);
+}
+
+@media (min-width: 960px) {
+ .dark .VPNavBar.has-sidebar .content[data-v-d84f2262] {
+ background: rgba(36, 36, 36, 0.1);
+ }
+}
+
+.Layout::before {
+ content: "";
+ background-size: 100% 100%;
+ background-position: right;
+ background-repeat: no-repeat;
+ opacity: 1;
+ max-width: 100%;
+ height: 100%;
+ width: 50%;
+ position: fixed;
+ top: -20%;
+ right: -10%;
+ display: block;
+}
+
+.Layout::after {
+ content: "";
+ background-size: 100% 100%;
+ background-position: right;
+ background-repeat: no-repeat;
+ opacity: 1;
+ max-width: 100%;
+ height: 100%;
+ width: 50%;
+ position: fixed;
+ bottom: -20%;
+ left: -10%;
+ display: block;
+ z-index: -1;
+}
+
+@media (min-width: 960px) {
+ .title {
+ font-size: 24px !important;
+ }
+}
+
+.image-src {
+ max-width: 220px !important;
+}
diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js
new file mode 100644
index 0000000..c495bc1
--- /dev/null
+++ b/docs/.vitepress/theme/index.js
@@ -0,0 +1,4 @@
+import DefaultTheme from "vitepress/theme";
+import "./custom.css";
+
+export default DefaultTheme;
diff --git a/docs/guide/edit.md b/docs/guide/edit.md
new file mode 100644
index 0000000..30c1d32
--- /dev/null
+++ b/docs/guide/edit.md
@@ -0,0 +1,19 @@
+# 参与编辑
+
+欢迎各位有意愿参与到开源当中的朋友加入文档的编写,书写文档不仅是教会别人知识,更是用自己的表达方式概括自己所学习的知识,这对个人来说是一种不多的成长机会
+
+```js
+
+// 拉取项目
+git clone https://github.com/sunniejs/vue-h5-template
+
+// 切换分支
+git checkout -b docs origin/docs
+
+// 安装依赖
+yarn install
+
+// 启动项目
+yarn start
+
+```
diff --git a/docs/guide/index.md b/docs/guide/index.md
new file mode 100644
index 0000000..5a04d86
--- /dev/null
+++ b/docs/guide/index.md
@@ -0,0 +1,23 @@
+# Vue-H5-Template
+
+[Vue-H5-Template](https://github.com/sunniejs/vue-h5-template),是基于 vite + vue3 + pinia + ( Vant or Varlet or NutUI ) + viewport 适配方案 ,构建移动端开发脚手架
+
+## 特点
+
+### 最新技术栈
+
+- 框架选型基于当下流行的 vue + vite + ts 模式,精选社区经典的 ui 框架和 vite 插件
+
+### 基于 TypeScript
+
+- typescript 越来越被大型的 js 项目所需要,明确的类型定义可以省下不少的维护成本
+
+### 轻量级
+
+- 不同于集成解决方案,尽量做到轻量不冗杂,只引入高频次、需求高的插件和清晰的示例
+- 轻装上阵,便于拓展开发
+
+### 通俗易懂的文档
+
+- 基于最新 VitePress 构建的文档,更快,更便捷
+- 更快的热更新
diff --git a/docs/guide/start.md b/docs/guide/start.md
new file mode 100644
index 0000000..a888210
--- /dev/null
+++ b/docs/guide/start.md
@@ -0,0 +1,17 @@
+# 快速上手
+
+## node 版本要求
+
+推荐 14.19.0+以上的版本,毕竟 2022 年了,别掐着 12+的版本了,你也可以使用[nvm](https://github.com/nvm-sh/nvm)或[nvm-windows](https://github.com/coreybutler/nvm-windows)在同一台电脑上管理多个 node 版本
+
+## 包管理器
+
+尽量使用 yarn 或者 pnpm,本项目仅保证在 yarn 或 pnpm 下正确运行,npm 涉及到网络环境等各种情况的限制不做过多考虑。
+
+## 启动项目
+
+项目中包含 vue2 和 vue3 两套模版
+
+如你使用的是 vue2-template,请参考[vue2 项目启动]()
+
+如你使用的是 vue3-template,请参考[vue3 项目启动]()
diff --git a/docs/guide/vue2/alias.md b/docs/guide/vue2/alias.md
new file mode 100644
index 0000000..7b89520
--- /dev/null
+++ b/docs/guide/vue2/alias.md
@@ -0,0 +1,19 @@
+# 配置 alias 别名
+
+```javascript
+const path = require("path");
+const resolve = (dir) => path.join(__dirname, dir);
+const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);
+
+module.exports = {
+ chainWebpack: (config) => {
+ // 添加别名
+ config.resolve.alias
+ .set("@", resolve("src"))
+ .set("assets", resolve("src/assets"))
+ .set("api", resolve("src/api"))
+ .set("views", resolve("src/views"))
+ .set("components", resolve("src/components"));
+ },
+};
+```
diff --git a/docs/guide/vue2/axios.md b/docs/guide/vue2/axios.md
new file mode 100644
index 0000000..2416ead
--- /dev/null
+++ b/docs/guide/vue2/axios.md
@@ -0,0 +1,106 @@
+### ✅ Axios 封装及接口管理
+
+`utils/request.js` 封装 axios ,开发者需要根据后台接口做修改。
+
+- `service.interceptors.request.use` 里可以设置请求头,比如设置 `token`
+- `config.hideloading` 是在 api 文件夹下的接口参数里设置,下文会讲
+- `service.interceptors.response.use` 里可以对接口返回数据处理,比如 401 删除本地信息,重新登录
+
+```javascript
+import axios from 'axios'
+import store from '@/store'
+import { Toast } from 'vant'
+// 根据环境不同引入不同api地址
+import { baseApi } from '@/config'
+// create an axios instance
+const service = axios.create({
+ baseURL: baseApi, // url = base api url + request url
+ withCredentials: true, // send cookies when cross-domain requests
+ timeout: 5000, // request timeout
+})
+
+// request 拦截器 request interceptor
+service.interceptors.request.use(
+ config => {
+ // 不传递默认开启loading
+ if (!config.hideloading) {
+ // loading
+ Toast.loading({
+ forbidClick: true,
+ })
+ }
+ if (store.getters.token) {
+ config.headers['X-Token'] = ''
+ }
+ return config
+ },
+ error => {
+ // do something with request error
+ console.log(error) // for debug
+ return Promise.reject(error)
+ }
+)
+// respone拦截器
+service.interceptors.response.use(
+ response => {
+ Toast.clear()
+ const res = response.data
+ if (res.status && res.status !== 200) {
+ // 登录超时,重新登录
+ if (res.status === 401) {
+ store.dispatch('FedLogOut').then(() => {
+ location.reload()
+ })
+ }
+ return Promise.reject(res || 'error')
+ } else {
+ return Promise.resolve(res)
+ }
+ },
+ error => {
+ Toast.clear()
+ console.log('err' + error) // for debug
+ return Promise.reject(error)
+ }
+)
+export default service
+```
+
+#### 接口管理
+
+在`src/api` 文件夹下统一管理接口
+
+- 你可以建立多个模块对接接口, 比如 `home.js` 里是首页的接口这里讲解 `user.js`
+- `url` 接口地址,请求的时候会拼接上 `config` 下的 `baseApi`
+- `method` 请求方法
+- `data` 请求参数 `qs.stringify(params)` 是对数据系列化操作
+- `hideloading` 默认 `false`,设置为 `true` 后,不显示 loading ui 交互中有些接口不需要让用户感知
+
+```javascript
+import qs from 'qs'
+// axios
+import request from '@/utils/request'
+//user api
+
+// 用户信息
+export function getUserInfo(params) {
+ return request({
+ url: '/user/userinfo',
+ method: 'post',
+ data: qs.stringify(params),
+ hideloading: true, // 隐藏 loading 组件
+ })
+}
+```
+
+#### 如何调用
+
+```javascript
+// 请求接口
+import { getUserInfo } from '@/api/user.js'
+
+const params = { user: 'sunnie' }
+getUserInfo(params)
+ .then(() => {})
+ .catch(() => {})
+```
diff --git a/docs/guide/vue2/base.md b/docs/guide/vue2/base.md
new file mode 100644
index 0000000..098cd9f
--- /dev/null
+++ b/docs/guide/vue2/base.md
@@ -0,0 +1,36 @@
+### ✅ Webpack 4 vue.config.js 基础配置
+
+如果你的 `Vue Router` 模式是 hash
+
+```javascript
+publicPath: './',
+```
+
+如果你的 `Vue Router` 模式是 history 这里的 publicPath 和你的 `Vue Router` `base` **保持一直**
+
+```javascript
+publicPath: '/app/',
+```
+
+```javascript
+const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
+
+module.exports = {
+ publicPath: './', // 署应用包时的基本 URL。 vue-router hash 模式使用
+ // publicPath: '/app/', // 署应用包时的基本 URL。 vue-router history模式使用
+ outputDir: 'dist', // 生产环境构建文件的目录
+ assetsDir: 'static', // outputDir的静态资源(js、css、img、fonts)目录
+ lintOnSave: !IS_PROD,
+ productionSourceMap: false, // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
+ devServer: {
+ port: 9020, // 端口号
+ open: false, // 启动后打开浏览器
+ overlay: {
+ // 当出现编译器错误或警告时,在浏览器中显示全屏覆盖层
+ warnings: false,
+ errors: true,
+ },
+ // ...
+ },
+}
+```
diff --git a/docs/guide/vue2/bundle.md b/docs/guide/vue2/bundle.md
new file mode 100644
index 0000000..50a8011
--- /dev/null
+++ b/docs/guide/vue2/bundle.md
@@ -0,0 +1,22 @@
+### ✅ 配置 打包分析
+
+```javascript
+const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+
+module.exports = {
+ chainWebpack: config => {
+ // 打包分析
+ if (IS_PROD) {
+ config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
+ {
+ analyzerMode: 'static',
+ },
+ ])
+ }
+ },
+}
+```
+
+```bash
+npm run build
+```
diff --git a/docs/guide/vue2/chunks.md b/docs/guide/vue2/chunks.md
new file mode 100644
index 0000000..f4c21cd
--- /dev/null
+++ b/docs/guide/vue2/chunks.md
@@ -0,0 +1,45 @@
+### ✅ splitChunks 单独打包第三方模块
+
+```javascript
+module.exports = {
+ chainWebpack: config => {
+ config.when(IS_PROD, config => {
+ config
+ .plugin('ScriptExtHtmlWebpackPlugin')
+ .after('html')
+ .use('script-ext-html-webpack-plugin', [
+ {
+ // 将 runtime 作为内联引入不单独存在
+ inline: /runtime\..*\.js$/,
+ },
+ ])
+ .end()
+ config.optimization.splitChunks({
+ chunks: 'all',
+ cacheGroups: {
+ // cacheGroups 下可以可以配置多个组,每个组根据test设置条件,符合test条件的模块
+ commons: {
+ name: 'chunk-commons',
+ test: resolve('src/components'),
+ minChunks: 3, // 被至少用三次以上打包分离
+ priority: 5, // 优先级
+ reuseExistingChunk: true, // 表示是否使用已有的 chunk,如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了,那么将不会重新生成新的。
+ },
+ node_vendors: {
+ name: 'chunk-libs',
+ chunks: 'initial', // 只打包初始时依赖的第三方
+ test: /[\\/]node_modules[\\/]/,
+ priority: 10,
+ },
+ vantUI: {
+ name: 'chunk-vantUI', // 单独将 vantUI 拆包
+ priority: 20, // 数字大权重到,满足多个 cacheGroups 的条件时候分到权重高的
+ test: /[\\/]node_modules[\\/]_?vant(.*)/,
+ },
+ },
+ })
+ config.optimization.runtimeChunk('single')
+ })
+ },
+}
+```
diff --git a/docs/guide/vue2/console.md b/docs/guide/vue2/console.md
new file mode 100644
index 0000000..aa11db2
--- /dev/null
+++ b/docs/guide/vue2/console.md
@@ -0,0 +1,34 @@
+### ✅ 去掉 console.log
+
+保留了测试环境和本地环境的 `console.log`
+
+```bash
+npm i -D babel-plugin-transform-remove-console
+```
+
+在 babel.config.js 中配置
+
+```javascript
+// 获取 VUE_APP_ENV 非 NODE_ENV,测试环境依然 console
+const IS_PROD = ['production', 'prod'].includes(process.env.VUE_APP_ENV)
+const plugins = [
+ [
+ 'import',
+ {
+ libraryName: 'vant',
+ libraryDirectory: 'es',
+ style: true,
+ },
+ 'vant',
+ ],
+]
+// 去除 console.log
+if (IS_PROD) {
+ plugins.push('transform-remove-console')
+}
+
+module.exports = {
+ presets: [['@vue/cli-plugin-babel/preset', { useBuiltIns: 'entry' }]],
+ plugins,
+}
+```
diff --git a/docs/guide/vue2/env.md b/docs/guide/vue2/env.md
new file mode 100644
index 0000000..9c5818c
--- /dev/null
+++ b/docs/guide/vue2/env.md
@@ -0,0 +1,84 @@
+### ✅ 配置多环境变量
+
+`package.json` 里的 `scripts` 配置 `serve` `stage` `build`,通过 `--mode xxx` 来执行不同环境
+
+- 通过 `npm run serve` 启动本地 , 执行 `development`
+- 通过 `npm run stage` 打包测试 , 执行 `staging`
+- 通过 `npm run build` 打包正式 , 执行 `production`
+
+```javascript
+"scripts": {
+ "serve": "vue-cli-service serve --open",
+ "stage": "vue-cli-service build --mode staging",
+ "build": "vue-cli-service build",
+}
+```
+
+##### 配置介绍
+
+ 以 `VUE_APP_` 开头的变量,在代码中可以通过 `process.env.VUE_APP_` 访问。
+ 比如,`VUE_APP_ENV = 'development'` 通过`process.env.VUE_APP_ENV` 访问。
+ 除了 `VUE_APP_*` 变量之外,在你的应用代码中始终可用的还有两个特殊的变量`NODE_ENV` 和`BASE_URL`
+
+在项目根目录中新建`.env.*`
+
+- .env.development 本地开发环境配置
+
+```bash
+NODE_ENV='development'
+# must start with VUE_APP_
+VUE_APP_ENV = 'development'
+
+```
+
+- .env.staging 测试环境配置
+
+```bash
+NODE_ENV='production'
+# must start with VUE_APP_
+VUE_APP_ENV = 'staging'
+```
+
+- .env.production 正式环境配置
+
+```bash
+ NODE_ENV='production'
+# must start with VUE_APP_
+VUE_APP_ENV = 'production'
+```
+
+这里我们并没有定义很多变量,只定义了基础的 VUE_APP_ENV `development` `staging` `production`
+变量我们统一在 `src/config/env.*.js` 里进行管理。
+
+这里有个问题,既然这里有了根据不同环境设置变量的文件,为什么还要去 config 下新建三个对应的文件呢?
+**修改起来方便,不需
+要重启项目,符合开发习惯。**
+
+config/index.js
+
+```javascript
+// 根据环境引入不同配置 process.env.NODE_ENV
+const config = require('./env.' + process.env.VUE_APP_ENV)
+module.exports = config
+```
+
+配置对应环境的变量,拿本地环境文件 `env.development.js` 举例,用户可以根据需求修改
+
+```javascript
+// 本地环境配置
+module.exports = {
+ title: 'vue-h5-template',
+ baseUrl: 'http://localhost:9018', // 项目地址
+ baseApi: 'https://test.xxx.com/api', // 本地api请求地址
+ APPID: 'xxx',
+ APPSECRET: 'xxx',
+}
+```
+
+根据环境不同,变量就会不同了
+
+```javascript
+// 根据环境不同引入不同baseApi地址
+import { baseApi } from '@/config'
+console.log(baseApi)
+```
diff --git a/docs/guide/vue2/externals.md b/docs/guide/vue2/externals.md
new file mode 100644
index 0000000..810a78f
--- /dev/null
+++ b/docs/guide/vue2/externals.md
@@ -0,0 +1,84 @@
+### ✅ 配置 externals 引入 cdn 资源
+
+这个版本 CDN 不再引入,我测试了一下使用引入 CDN 和不使用,不使用会比使用时间少。网上不少文章测试 CDN 速度块,这个开发者可
+以实际测试一下。
+
+另外项目中使用的是公共 CDN 不稳定,域名解析也是需要时间的(如果你要使用请尽量使用同一个域名)
+
+因为页面每次遇到`
+ <% } %>
+```
diff --git a/docs/guide/vue2/ie.md b/docs/guide/vue2/ie.md
new file mode 100644
index 0000000..3bec6a6
--- /dev/null
+++ b/docs/guide/vue2/ie.md
@@ -0,0 +1,30 @@
+### ✅ 添加 IE 兼容
+
+之前的方式 会报 `@babel/polyfill` is deprecated. Please, use required parts of `core-js` and
+`regenerator-runtime/runtime` separately
+
+`@babel/polyfill` 废弃,使用 `core-js` 和 `regenerator-runtime`
+
+```bash
+npm i --save core-js regenerator-runtime
+```
+
+在 `main.js` 中添加
+
+```javascript
+// 兼容 IE
+// https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md#babelpolyfill
+import 'core-js/stable'
+import 'regenerator-runtime/runtime'
+```
+
+配置 `babel.config.js`
+
+```javascript
+const plugins = []
+
+module.exports = {
+ presets: [['@vue/cli-plugin-babel/preset', { useBuiltIns: 'usage', corejs: 3 }]],
+ plugins,
+}
+```
diff --git a/docs/guide/vue2/lint.md b/docs/guide/vue2/lint.md
new file mode 100644
index 0000000..8f46dd7
--- /dev/null
+++ b/docs/guide/vue2/lint.md
@@ -0,0 +1,165 @@
+### ✅ Eslint + Pettier 统一开发规范
+
+VScode (版本 1.47.3)安装 `eslint` `prettier` `vetur` 插件 `.vue` 文件使用 vetur 进行格式化,其他使用`prettier`,后面会
+专门写个如何使用配合使用这三个玩意
+
+在文件 `.prettierrc` 里写 属于你的 pettier 规则
+
+```bash
+{
+ "printWidth": 120,
+ "tabWidth": 2,
+ "singleQuote": true,
+ "trailingComma": "none",
+ "semi": false,
+ "wrap_line_length": 120,
+ "wrap_attributes": "auto",
+ "proseWrap": "always",
+ "arrowParens": "avoid",
+ "bracketSpacing": false,
+ "jsxBracketSameLine": true,
+ "useTabs": false,
+ "overrides": [{
+ "files": ".prettierrc",
+ "options": {
+ "parser": "json"
+ }
+ }]
+}
+```
+
+Vscode setting.json 设置
+
+```bash
+ {
+ // 将设置放入此文件中以覆盖默认设置
+ "files.autoSave": "off",
+ // 控制字体系列。
+ "editor.fontFamily": "Consolas, 'Courier New', monospace,'宋体'",
+ "terminal.integrated.shell.windows": "C:\\Program Files\\Git\\bin\\bash.exe",
+ // 以像素为单位控制字号。
+ "editor.fontSize": 16,
+ // 控制选取范围是否有圆角
+ "editor.roundedSelection": false,
+ // 建议小组件的字号
+ "editor.suggestFontSize": 16,
+ // 在“打开的编辑器”窗格中显示的编辑器数量。将其设置为 0 可隐藏窗格。
+ "explorer.openEditors.visible": 0,
+ // 是否已启用自动刷新
+ "git.autorefresh": true,
+ // 以像素为单位控制终端的字号,这是 editor.fontSize 的默认值。
+ "terminal.integrated.fontSize": 14,
+ // 控制终端游标是否闪烁。
+ "terminal.integrated.cursorBlinking": true,
+ // 一个制表符等于的空格数。该设置在 `editor.detectIndentation` 启用时根据文件内容进行重写。
+ // Tab Size
+ "editor.tabSize": 2,
+ // By default, common template. Do not modify it!!!!!
+ "editor.formatOnType": true,
+ "window.zoomLevel": 0,
+ "editor.detectIndentation": false,
+ "css.fileExtensions": ["css", "scss"],
+ "files.associations": {
+ "*.string": "html",
+ "*.vue": "vue",
+ "*.wxss": "css",
+ "*.wxml": "wxml",
+ "*.wxs": "javascript",
+ "*.cjson": "jsonc",
+ "*.js": "javascript"
+ },
+ // 为指定的语法定义配置文件或使用带有特定规则的配置文件。
+ "emmet.syntaxProfiles": {
+ "vue-html": "html",
+ "vue": "html"
+ },
+ "search.exclude": {
+ "**/node_modules": true,
+ "**/bower_components": true
+ },
+ //保存时eslint自动修复错误
+ "editor.formatOnSave": true,
+ // Enable per-language
+ //配置 ESLint 检查的文件类型
+ "editor.quickSuggestions": {
+ "strings": true
+ },
+ // 添加 vue 支持
+ // 这里是针对vue文件的格式化设置,vue的规则在这里生效
+ "vetur.format.options.tabSize": 2,
+ "vetur.format.options.useTabs": false,
+ "vetur.format.defaultFormatter.html": "js-beautify-html",
+ "vetur.format.defaultFormatter.css": "prettier",
+ "vetur.format.defaultFormatter.scss": "prettier",
+ "vetur.format.defaultFormatter.postcss": "prettier",
+ "vetur.format.defaultFormatter.less": "prettier",
+ "vetur.format.defaultFormatter.js": "vscode-typescript",
+ "vetur.format.defaultFormatter.sass": "sass-formatter",
+ "vetur.format.defaultFormatter.ts": "prettier",
+ "vetur.format.defaultFormatterOptions": {
+ "js-beautify-html": {
+ "wrap_attributes": "aligned-multiple", // 超过150折行
+ "wrap-line-length": 150
+ },
+ // #vue组件中html代码格式化样式
+ "prettier": {
+ "printWidth": 120,
+ "tabWidth": 2,
+ "singleQuote": false,
+ "trailingComma": "none",
+ "semi": false,
+ "wrap_line_length": 120,
+ "wrap_attributes": "aligned-multiple", // 超过150折行
+ "proseWrap": "always",
+ "arrowParens": "avoid",
+ "bracketSpacing": true,
+ "jsxBracketSameLine": true,
+ "useTabs": false,
+ "overrides": [
+ {
+ "files": ".prettierrc",
+ "options": {
+ "parser": "json"
+ }
+ }
+ ]
+ }
+ },
+ // Enable per-language
+ "[json]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "vetur.validation.template": false,
+ "html.format.enable": false,
+ "json.format.enable": false,
+ "javascript.format.enable": false,
+ "typescript.format.enable": false,
+ "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
+ "[html]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[javascript]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[jsonc]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[vue]": {
+ "editor.defaultFormatter": "octref.vetur"
+ },
+ "emmet.includeLanguages": {
+ "wxml": "html"
+ },
+ "[typescriptreact]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ // 开启eslint自动修复js/ts功能
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ },
+ "minapp-vscode.disableAutoConfig": true,
+ "javascript.implicitProjectConfig.experimentalDecorators": true,
+ "editor.maxTokenizationLineLength": 200000
+}
+
+```
diff --git a/docs/guide/vue2/proxy.md b/docs/guide/vue2/proxy.md
new file mode 100644
index 0000000..d38002e
--- /dev/null
+++ b/docs/guide/vue2/proxy.md
@@ -0,0 +1,36 @@
+### ✅ 配置 proxy 跨域
+
+如果你的项目需要跨域设置,你需要打来 `vue.config.js` `proxy` 注释 并且配置相应参数
+
+**!!!注意:你还需要将 `src/config/env.development.js` 里的 `baseApi` 设置成 '/'**
+
+```javascript
+module.exports = {
+ devServer: {
+ // ....
+ proxy: {
+ //配置跨域
+ '/api': {
+ target: 'https://test.xxx.com', // 接口的域名
+ // ws: true, // 是否启用websockets
+ changOrigin: true, // 开启代理,在本地创建一个虚拟服务端
+ pathRewrite: {
+ '^/api': '/',
+ },
+ },
+ },
+ },
+}
+```
+
+使用 例如: `src/api/home.js`
+
+```javascript
+export function getUserInfo(params) {
+ return request({
+ url: '/api/userinfo',
+ method: 'post',
+ data: qs.stringify(params),
+ })
+}
+```
diff --git a/docs/guide/vue2/rem.md b/docs/guide/vue2/rem.md
new file mode 100644
index 0000000..b6acfd2
--- /dev/null
+++ b/docs/guide/vue2/rem.md
@@ -0,0 +1,69 @@
+### ✅ rem 适配方案
+
+不用担心,项目已经配置好了 `rem` 适配, 下面仅做介绍:
+
+Vant 中的样式默认使用`px`作为单位,如果需要使用`rem`单位,推荐使用以下两个工具:
+
+- [postcss-pxtorem](https://github.com/cuth/postcss-pxtorem) 是一款 `postcss` 插件,用于将单位转化为 `rem`
+- [lib-flexible](https://github.com/amfe/lib-flexible) 用于设置 `rem` 基准值
+
+##### PostCSS 配置
+
+下面提供了一份基本的 `postcss` 配置,可以在此配置的基础上根据项目需求进行修改
+
+```javascript
+// https://github.com/michael-ciniawsky/postcss-load-config
+module.exports = {
+ plugins: {
+ autoprefixer: {
+ overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8']
+ },
+ 'postcss-pxtorem': {
+ rootValue: 37.5,
+ propList: ['*']
+ }
+ }
+}
+```
+
+更多详细信息: [vant](https://youzan.github.io/vant/#/zh-CN/quickstart#jin-jie-yong-fa)
+
+**新手必看,老鸟跳过**
+
+很多小伙伴会问我,适配的问题,因为我们使用的是 Vant UI,所以必须根据 Vant UI 375 的设计规范走,一般我们的设计会将 UI 图上传到蓝湖,我们就可以需要的尺寸了。下面就大搞普及一下 rem。
+
+我们知道 `1rem` 等于`html` 根元素设定的 `font-size` 的 `px` 值。Vant UI 设置 `rootValue: 37.5`,你可以看到在 iPhone 6 下看到 (`1rem 等于 37.5px`):
+
+```html
+
+```
+
+切换不同的机型,根元素可能会有不同的`font-size`。当你写 css px 样式时,会被程序换算成 `rem` 达到适配。
+
+因为我们用了 Vant 的组件,需要按照 `rootValue: 37.5` 来写样式。
+
+举个例子:设计给了你一张 750px \* 1334px 图片,在 iPhone6 上铺满屏幕,其他机型适配。
+
+- 当`rootValue: 70` , 样式 `width: 750px;height: 1334px;` 图片会撑满 iPhone6 屏幕,这个时候切换其他机型,图片也会跟着撑满。
+- 当`rootValue: 37.5` 的时候,样式 `width: 375px;height: 667px;` 图片会撑满 iPhone6 屏幕。
+
+也就是 iphone 6 下 375px 宽度写 CSS。其他的你就可以根据你设计图,去写对应的样式就可以了。
+
+当然,想要撑满屏幕你可以使用 100%,这里只是举例说明。
+
+```html
+
+
+
+```
diff --git a/docs/guide/vue2/router.md b/docs/guide/vue2/router.md
new file mode 100644
index 0000000..d883335
--- /dev/null
+++ b/docs/guide/vue2/router.md
@@ -0,0 +1,34 @@
+### ✅ Vue-router
+
+本案例采用 `hash` 模式,开发者根据需求修改 `mode` `base`
+
+**注意**:如果你使用了 `history` 模式,`vue.config.js` 中的 `publicPath` 要做对应的**修改**
+
+前往:[vue.config.js 基础配置](#base)
+
+```javascript
+import Vue from 'vue'
+import Router from 'vue-router'
+
+Vue.use(Router)
+export const router = [
+ {
+ path: '/',
+ name: 'index',
+ component: () => import('@/views/home/index'), // 路由懒加载
+ meta: {
+ title: '首页', // 页面标题
+ keepAlive: false, // keep-alive 标识
+ },
+ },
+]
+const createRouter = () =>
+ new Router({
+ // mode: 'history', // 如果你是 history模式 需要配置 vue.config.js publicPath
+ // base: '/app/',
+ scrollBehavior: () => ({ y: 0 }),
+ routes: router,
+ })
+
+export default createRouter()
+```
diff --git a/docs/guide/vue2/sass.md b/docs/guide/vue2/sass.md
new file mode 100644
index 0000000..fab2845
--- /dev/null
+++ b/docs/guide/vue2/sass.md
@@ -0,0 +1,104 @@
+### ✅ Sass 全局样式
+
+首先 你可能会遇到 `node-sass` 安装不成功,别放弃多试几次!!!
+
+每个页面自己对应的样式都写在自己的 .vue 文件之中 `scoped` 它顾名思义给 css 加了一个域的概念。
+
+```html
+
+
+
+```
+
+#### 目录结构
+
+vue-h5-template 所有全局样式都在 `@/src/assets/css` 目录下设置
+
+```bash
+├── assets
+│ ├── css
+│ │ ├── index.scss # 全局通用样式
+│ │ ├── mixin.scss # 全局mixin
+│ │ └── variables.scss # 全局变量
+```
+
+#### 自定义 vant-ui 样式
+
+现在我们来说说怎么重写 `vant-ui` 样式。由于 `vant-ui` 的样式我们是在全局引入的,所以你想在某个页面里面覆盖它的样式就不能加 `scoped`,但你又想只覆盖这个页面的 `vant` 样式,你就可在它的父级加一个 `class`,用命名空间来解决问题。
+
+```css
+.about-container {
+ /* 你的命名空间 */
+ .van-button {
+ /* vant-ui 元素*/
+ margin-right: 0px;
+ }
+}
+```
+
+#### 父组件改变子组件样式 深度选择器
+
+当你子组件使用了 `scoped` 但在父组件又想修改子组件的样式可以 通过 `>>>` 来实现:
+
+```css
+
+```
+#### 全局变量
+
+`vue.config.js` 配置使用 `css.loaderOptions` 选项,注入 `sass` 的 `mixin` `variables` 到全局,不需要手动引入 ,配置`$cdn`通过变量形式引入 cdn 地址,这样向所有 Sass/Less 样式传入共享的全局变量:
+
+```javascript
+const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
+const defaultSettings = require('./src/config/index.js')
+module.exports = {
+ css: {
+ extract: IS_PROD,
+ sourceMap: false,
+ loaderOptions: {
+ // 给 scss-loader 传递选项
+ scss: {
+ // 注入 `sass` 的 `mixin` `variables` 到全局, $cdn可以配置图片cdn
+ // 详情: https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders
+ prependData: `
+ @import "assets/css/mixin.scss";
+ @import "assets/css/variables.scss";
+ $cdn: "${defaultSettings.$cdn}";
+ `,
+ },
+ },
+ },
+}
+```
+
+设置 js 中可以访问 `$cdn`,`.vue` 文件中使用`this.$cdn`访问
+
+```javascript
+// 引入全局样式
+import '@/assets/css/index.scss'
+
+// 设置 js中可以访问 $cdn
+// 引入cdn
+import { $cdn } from '@/config'
+Vue.prototype.$cdn = $cdn
+```
+
+在 css 和 js 使用
+
+```html
+
+
+```
diff --git a/docs/guide/vue2/start.md b/docs/guide/vue2/start.md
new file mode 100644
index 0000000..4e2c3bc
--- /dev/null
+++ b/docs/guide/vue2/start.md
@@ -0,0 +1,17 @@
+# 启动项目
+
+```js
+
+// 拉取项目
+git clone https://github.com/sunniejs/vue-h5-template
+
+// 切换分支
+git checkout -b vue2-h5-template origin/vue2-h5-template
+
+// 安装依赖
+yarn install
+
+// 启动项目
+yarn serve
+
+```
diff --git a/docs/guide/vue2/vant.md b/docs/guide/vue2/vant.md
new file mode 100644
index 0000000..f276212
--- /dev/null
+++ b/docs/guide/vue2/vant.md
@@ -0,0 +1,49 @@
+### ✅ VantUI 组件按需加载
+
+项目采
+用[Vant 自动按需引入组件 (推荐)](https://youzan.github.io/vant/#/zh-CN/quickstart#fang-shi-yi.-zi-dong-an-xu-yin-ru-zu-jian-tui-jian)下
+面安装插件介绍:
+
+[babel-plugin-import](https://github.com/ant-design/babel-plugin-import) 是一款 `babel` 插件,它会在编译过程中将
+`import` 的写法自动转换为按需引入的方式
+
+#### 安装插件
+
+```bash
+npm i babel-plugin-import -D
+```
+
+在`babel.config.js` 设置
+
+```javascript
+// 对于使用 babel7 的用户,可以在 babel.config.js 中配置
+const plugins = [
+ [
+ 'import',
+ {
+ libraryName: 'vant',
+ libraryDirectory: 'es',
+ style: true,
+ },
+ 'vant',
+ ],
+]
+module.exports = {
+ presets: [['@vue/cli-plugin-babel/preset', { useBuiltIns: 'usage', corejs: 3 }]],
+ plugins,
+}
+```
+
+#### 使用组件
+
+项目在 `src/plugins/vant.js` 下统一管理组件,用哪个引入哪个,无需在页面里重复引用
+
+```javascript
+// 按需全局引入 vant组件
+import Vue from 'vue'
+import { Button, List, Cell, Tabbar, TabbarItem } from 'vant'
+Vue.use(Button)
+Vue.use(Cell)
+Vue.use(List)
+Vue.use(Tabbar).use(TabbarItem)
+```
diff --git a/docs/guide/vue2/vuex.md b/docs/guide/vue2/vuex.md
new file mode 100644
index 0000000..df7d400
--- /dev/null
+++ b/docs/guide/vue2/vuex.md
@@ -0,0 +1,45 @@
+### ✅ Vuex 状态管理
+
+目录结构
+
+```bash
+├── store
+│ ├── modules
+│ │ └── app.js
+│ ├── index.js
+│ ├── getters.js
+```
+
+`main.js` 引入
+
+```javascript
+import Vue from 'vue'
+import App from './App.vue'
+import store from './store'
+new Vue({
+ el: '#app',
+ router,
+ store,
+ render: h => h(App),
+})
+```
+
+使用
+
+```html
+
+```
diff --git a/docs/guide/vue2/vw.md b/docs/guide/vue2/vw.md
new file mode 100644
index 0000000..38f07ae
--- /dev/null
+++ b/docs/guide/vue2/vw.md
@@ -0,0 +1,61 @@
+### ✅ vm 适配方案
+
+本项目使用的是 `rem` 的 适配方案,其实无论你使用哪种方案,都不需要你去计算 12px 是多少 `rem` 或者 `vw`, 会有专门的工具去帮你做
+。如果你想用 `vw`,你可以按照下面的方式切换。
+
+#### 1.安装依赖
+
+```bash
+
+npm install postcss-px-to-viewport -D
+
+```
+
+#### 2.修改 .postcssrc.js
+
+将根目录下 .postcssrc.js 文件修改如下
+
+```javascript
+// https://github.com/michael-ciniawsky/postcss-load-config
+module.exports = {
+ plugins: {
+ autoprefixer: {
+ overrideBrowserslist: [
+ "Android 4.1",
+ "iOS 7.1",
+ "Chrome > 31",
+ "ff > 31",
+ "ie >= 8",
+ ],
+ },
+ "postcss-px-to-viewport": {
+ viewportWidth: 375, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750
+ unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
+ viewportUnit: "vw", // 指定需要转换成的视窗单位,建议使用vw
+ selectorBlackList: [".ignore", ".hairlines"], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
+ minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
+ mediaQuery: false, // 允许在媒体查询中转换`px`
+ },
+ },
+};
+```
+
+#### 3.删除原来的 rem 相关代码
+
+src/main.js 删除如下代码
+
+```javascript
+// 移动端适配
+import "lib-flexible/flexible.js";
+```
+
+package.json 删除如下代码
+
+```javascript
+"lib-flexible": "^0.3.2",
+"postcss-pxtorem": "^5.1.1",
+```
+
+运行起来,F12 元素 css style 就是 vw 单位了
+
+[▲ 回顶部](#top)
diff --git a/docs/guide/vue3/alias.md b/docs/guide/vue3/alias.md
new file mode 100644
index 0000000..a17616f
--- /dev/null
+++ b/docs/guide/vue3/alias.md
@@ -0,0 +1,21 @@
+# alias
+
+```javascript
+resolve: {
+ alias: [{
+ find: 'vue-i18n',
+ replacement: 'vue-i18n/dist/vue-i18n.cjs.js',
+ },
+ // /@/xxxx => src/xxxx
+ {
+ find: /\/@\//,
+ replacement: pathResolve('src') + '/',
+ },
+ // /#/xxxx => types/xxxx
+ {
+ find: /\/#\//,
+ replacement: pathResolve('types') + '/',
+ },
+ ],
+},
+```
diff --git a/docs/guide/vue3/axios.md b/docs/guide/vue3/axios.md
new file mode 100644
index 0000000..67fbd44
--- /dev/null
+++ b/docs/guide/vue3/axios.md
@@ -0,0 +1,67 @@
+# axios 封装及接口管理
+
+`utils/request.js` 封装 axios , 开发者需要根据后台接口做修改。
+
+- `service.interceptors.request.use` 里可以设置请求头,比如设置 `token`
+- `config.hideloading` 是在 api 文件夹下的接口参数里设置,下文会讲
+- `service.interceptors.response.use` 里可以对接口返回数据处理,比如 401 删除本地信息,重新登录
+
+```javascript
+import axios from "axios";
+import store from "@/store";
+import { Toast } from "vant";
+// 根据环境不同引入不同api地址
+import { baseApi } from "@/config";
+// create an axios instance
+const service = axios.create({
+ baseURL: baseApi, // url = base api url + request url
+ withCredentials: true, // send cookies when cross-domain requests
+ timeout: 5000, // request timeout
+});
+
+// request 拦截器 request interceptor
+service.interceptors.request.use(
+ (config) => {
+ // 不传递默认开启loading
+ if (!config.hideloading) {
+ // loading
+ Toast.loading({
+ forbidClick: true,
+ });
+ }
+ if (store.getters.token) {
+ config.headers["X-Token"] = "";
+ }
+ return config;
+ },
+ (error) => {
+ // do something with request error
+ console.log(error); // for debug
+ return Promise.reject(error);
+ }
+);
+// respone拦截器
+service.interceptors.response.use(
+ (response) => {
+ Toast.clear();
+ const res = response.data;
+ if (res.status && res.status !== 200) {
+ // 登录超时,重新登录
+ if (res.status === 401) {
+ store.dispatch("FedLogOut").then(() => {
+ location.reload();
+ });
+ }
+ return Promise.reject(res || "error");
+ } else {
+ return Promise.resolve(res);
+ }
+ },
+ (error) => {
+ Toast.clear();
+ console.log("err" + error); // for debug
+ return Promise.reject(error);
+ }
+);
+export default service;
+```
diff --git a/docs/guide/vue3/base.md b/docs/guide/vue3/base.md
new file mode 100644
index 0000000..8941b5a
--- /dev/null
+++ b/docs/guide/vue3/base.md
@@ -0,0 +1,45 @@
+# vite.config.ts 基础配置
+
+如果你的 `Vue Router` 模式是 hash
+
+```javascript
+publicPath: './',
+```
+
+如果你的 `Vue Router` 模式是 history 这里的 publicPath 和你的 `Vue Router` `base` **保持一致**
+
+```javascript
+publicPath: '/app/',
+```
+
+```javascript
+export default function ({ command }: ConfigEnv): UserConfigExport {
+ const isProduction = command === "build";
+ return {
+ server: {
+ host: "0.0.0.0",
+ },
+ plugins: [
+ vue(),
+ vueJsx(),
+ createStyleImportPlugin({
+ resolves: [NutuiResolve()],
+ }),
+ eruda(),
+ viteMockServe({
+ mockPath: "./src/mock",
+ localEnabled: command === "serve",
+ logger: true,
+ }),
+ ],
+ css: {
+ preprocessorOptions: {
+ scss: {
+ // 配置 nutui 全局 scss 变量
+ additionalData: `@import "@nutui/nutui/dist/styles/variables.scss";`,
+ },
+ },
+ },
+ };
+}
+```
diff --git a/docs/guide/vue3/env.md b/docs/guide/vue3/env.md
new file mode 100644
index 0000000..262644f
--- /dev/null
+++ b/docs/guide/vue3/env.md
@@ -0,0 +1,13 @@
+`package.json` 里的 `scripts` 配置 `dev` `dev:test` `dev:prod` ,通过 `--mode xxx` 来执行不同环境
+
+- 通过 `yarn dev` 启动本地环境参数 , 执行 `development`
+- 通过 `yarn dev:test` 启动测试环境参数 , 执行 `test`
+- 通过 `yarn dev:prod` 启动正式环境参数 , 执行 `prod`
+
+```javascript
+"scripts": {
+ "dev": "vite",
+ "dev:test": "vite --mode test",
+ "dev:prod": "vite --mode production",
+}
+```
diff --git a/docs/guide/vue3/lint.md b/docs/guide/vue3/lint.md
new file mode 100644
index 0000000..57c0f2e
--- /dev/null
+++ b/docs/guide/vue3/lint.md
@@ -0,0 +1,3 @@
+# Eslint+Pettier+stylelint 统一开发规范
+
+根目录下的.eslintrc.js、.stylelint.config.js、.prettier.config.js 内置了 lint 规则,帮助你规范地开发代码,有助于提高团队的代码质量和协作性,可以根据团队的规则进行修改
diff --git a/docs/guide/vue3/pinia.md b/docs/guide/vue3/pinia.md
new file mode 100644
index 0000000..27eece4
--- /dev/null
+++ b/docs/guide/vue3/pinia.md
@@ -0,0 +1,22 @@
+# Pinia 状态管理
+
+下一代 vuex,使用极其方便,ts 兼容好
+
+目录结构
+
+```bash
+├── store
+│ ├── modules
+│ │ └── user.js
+│ ├── index.js
+```
+
+使用
+
+```html
+
+```
diff --git a/docs/guide/vue3/proxy.md b/docs/guide/vue3/proxy.md
new file mode 100644
index 0000000..ede077d
--- /dev/null
+++ b/docs/guide/vue3/proxy.md
@@ -0,0 +1,13 @@
+# proxy 跨域
+
+```javascript
+server: {
+ proxy: {
+ '/api': {
+ target: 'https://baidu.com',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api/, '')
+ }
+ }
+},
+```
diff --git a/docs/guide/vue3/router.md b/docs/guide/vue3/router.md
new file mode 100644
index 0000000..485ba08
--- /dev/null
+++ b/docs/guide/vue3/router.md
@@ -0,0 +1,29 @@
+# vue-router
+
+本案例采用 `hash` 模式,开发者根据需求修改 `mode` `base`
+
+**注意**:如果你使用了 `history` 模式, `vue.config.js` 中的 `publicPath` 要做对应的**修改**
+
+前往:[vue.config.js 基础配置](#base)
+
+```javascript
+import Vue from "vue";
+import { createRouter, createWebHistory, Router } from "vue-router";
+
+Vue.use(Router);
+export const router = [
+ {
+ name: "root",
+ path: "/",
+ redirect: "/home",
+ component: () => import("@/layout/basic/index.vue"),
+ },
+];
+
+const router: Router = createRouter({
+ history: createWebHistory(),
+ routes: routes,
+});
+
+export default router;
+```
diff --git a/docs/guide/vue3/start.md b/docs/guide/vue3/start.md
new file mode 100644
index 0000000..9bb2a27
--- /dev/null
+++ b/docs/guide/vue3/start.md
@@ -0,0 +1,14 @@
+# 启动项目
+
+```js
+
+// 拉取项目
+git clone https://github.com/sunniejs/vue-h5-template
+
+// 安装依赖
+yarn install
+
+// 启动项目
+yarn dev
+
+```
diff --git a/docs/guide/vue3/ui.md b/docs/guide/vue3/ui.md
new file mode 100644
index 0000000..c1b5e67
--- /dev/null
+++ b/docs/guide/vue3/ui.md
@@ -0,0 +1,58 @@
+# 多 UI 组件库供选择
+
+Vite 构建工具,使用 vite-plugin-style-import 和 unplugin-vue-components/vite 实现按需引入。
+
+## 安装插件
+
+```bash
+yarn add vite-plugin-style-import -D
+yarn add unplugin-vue-components/vite -D
+```
+
+## 使用组件库
+
+nutUI 没有按需加载的 resolvers,style 需要自己配置按需加载
+
+在 `config/vite/plugins/styleImport.ts` 设置
+
+```javascript
+ // 按需加载样式文件
+ ...
+ createStyleImportPlugin({
+ resolves: [NutuiResolve()],
+ }),
+ ...
+```
+
+项目在 `src/plugins/nutUI.ts` 下统一管理组件,用哪个引入哪个,无需在页面里重复引用
+
+```javascript
+// 按需全局引入nutUI组件
+import Vue from "vue";
+import { Button, Cell, CellGroup } from "@nutui/nutui";
+export const nutUiComponents = [Button, Cell, CellGroup];
+
+// 在main.ts文件中引入
+nutUiComponents.forEach((item) => {
+ app.use(item);
+});
+```
+
+vant 和 varlet 可以使用组件按需加载
+
+在`config/vite/plugins/component.ts`下
+
+```javascript
+import { VueUseComponentsResolver, VantResolver, VarletUIResolver } from 'unplugin-vue-components/resolvers';
+...
+resolvers: [VantResolver(), VarletUIResolver()],
+...
+```
+
+## 不需要某个组件库
+
+nutUI 需删除`src/plugins/nutUI.ts`和`main.ts`文件下的引入
+
+vant 和 varlet 只需删除对应的 resolvers 即可
+
+删除后需全局搜索删除不需要的组件,避免报错
diff --git a/docs/guide/vue3/viewport.md b/docs/guide/vue3/viewport.md
new file mode 100644
index 0000000..f1daced
--- /dev/null
+++ b/docs/guide/vue3/viewport.md
@@ -0,0 +1,76 @@
+# viewport 适配方案
+
+不用担心,项目已经配置好了 `viewport` 适配,下面仅做介绍:
+
+- [cnjm-postcss-px-to-viewport](https://github.com/cnjm/postcss-px-to-viewport) 是一款 `postcss` 插件,用于将单位转化为 `vw`, 现在很多浏览器对`vw`的支持都很好,适配首选方案。
+
+## PostCSS 配置
+
+下面提供了一份基本的 `postcss` 配置,可以在此配置的基础上根据项目需求进行修改
+
+```javascript
+// https://github.com/michael-ciniawsky/postcss-load-config
+module.exports = {
+ plugins: {
+ autoprefixer: { overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8'] },
+ 'cnjm-postcss-px-to-viewport': {
+ unitToConvert: 'px', // 要转化的单位
+ viewportWidth: 750, // UI设计稿的宽度
+ unitPrecision: 6, // 转换后的精度,即小数点位数
+ propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
+ viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
+ fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
+ minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
+ mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
+ replace: true, // 是否转换后直接更换属性值
+ include: [],
+ exclude: [], // 设置忽略文件,用正则做目录名匹配
+ customFun: ({ file }) => {
+ // 这个自定义的方法是针对处理vant组件下的设计稿为375问题
+ const designWidth = judgeComponent(file) ? 375 : 750;
+ return designWidth;
+ },
+ },
+};
+```
+
+**新手必看,老鸟跳过**
+
+很多小伙伴会问我,适配的问题, 因为我们使用的是 Vant UI,所以必须根据 Vant UI 375 的设计规范走,一般我们的设计会将 UI 图上传到蓝湖,我们就可以需要的尺寸了。下面就大搞普及一下 rem。
+
+我们知道 `1rem` 等于 `html` 根元素设定的 `font-size` 的 `px` 值。Vant UI 设置 `rootValue: 37.5` , 你可以看到在 iPhone 6 下看到 ( `1rem 等于 37.5px` ):
+
+```html
+
+```
+
+切换不同的机型,根元素可能会有不同的 `font-size` 。当你写 css px 样式时,会被程序换算成 `rem` 达到适配。
+
+因为我们用了 Vant 的组件,需要按照 `rootValue: 37.5` 来写样式。
+
+举个例子:设计给了你一张 750px \* 1334px 图片,在 iPhone6 上铺满屏幕, 其他机型适配。
+
+- 当`rootValue: 75` , 样式 `width: 750px;height: 1334px;` 图片会撑满 iPhone6 屏幕,这个时候切换其他机型,图片也会跟着撑满。
+- 当`rootValue: 37.5` 的时候,样式 `width: 375px;height: 667px;` 图片会撑满 iPhone6 屏幕。
+
+也就是 iphone 6 下 375px 宽度写 CSS。其他的你就可以根据你设计图,去写对应的样式就可以了。
+
+当然,想要撑满屏幕你可以使用 100%,这里只是举例说明。
+
+```html
+
+
+
+```
diff --git a/docs/guide/vue3/vite.md b/docs/guide/vue3/vite.md
new file mode 100644
index 0000000..ce7682e
--- /dev/null
+++ b/docs/guide/vue3/vite.md
@@ -0,0 +1,17 @@
+# vite
+
+基于原生 ES 模块提供了丰富的内建功能,如速度快到惊人的模块热更新(HMR),使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。更多关于[vite](https://cn.vitejs.dev/guide/)
+
+模版集成了如下的 vite 插件
+
+- unplugin-auto-import(按需加载,自动引入)
+- unplugin-vue-components(按需加载,自动引入组件)
+- vite-plugin-compression(开启.gz 压缩)
+- vite-plugin-eruda(控制台,方便移动端调试)
+- vite-plugin-imagemin(图片压缩)
+- vite-plugin-mock(引入 mockjs,本地模拟接口)
+- vite-plugin-pages(动态生成路由)
+- vite-plugin-progress(构建显示进度条)
+- vite-plugin-restart(监听配置文件修改自动重启 Vite)
+- vite-plugin-style-import(按需引入样式文件)
+- vite-plugin-svg-icons(加载 SVG 文件,自动引入)
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..7ede175
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,34 @@
+---
+layout: home
+
+title: Vue-H5-Template
+titleTemplate: 一个快速开发的vue h5移动端脚手架
+
+hero:
+ name: Vue-H5-Template
+ text: 一个快速开发的Vue H5移动端脚手架
+ image:
+ src: http://www.sunniejs.cn/static/weapp/logo.png
+ alt: sunnie
+ actions:
+ - theme: brand
+ text: 开始
+ link: /guide/
+ - theme: alt
+ text: Github仓库
+ link: https://github.com/sunniejs/vue-h5-template
+
+features:
+ - icon: 💡
+ title: 开箱即用
+ details: 集成vue2、vue3的移动端快速开发模版,学习成本低,易上手
+ - icon: 📦
+ title: 代码规范
+ details: 完整的eslint、prettier、stylelint规范,加上husky,帮助你更好的管理代码
+ - icon: 🛠️
+ title: 配置优化
+ details: 完整配置的vue脚手架插件和优化,让你专注于业务开发,更高效
+ - icon: ⚙️
+ title: More
+ details: 加入我们,更多能力等你挖掘....
+---
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..496c511
--- /dev/null
+++ b/package.json
@@ -0,0 +1,10 @@
+{
+ "devDependencies": {
+ "vitepress": "^1.0.0-alpha.8",
+ "vue": "^3.2.37"
+ },
+ "scripts": {
+ "start": "vitepress dev docs --host 0.0.0.0",
+ "build": "vitepress build docs"
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..fd1acac
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,710 @@
+lockfileVersion: 5.3
+
+specifiers:
+ vitepress: ^1.0.0-alpha.8
+ vue: ^3.2.37
+
+devDependencies:
+ vitepress: 1.0.0-alpha.8
+ vue: 3.2.37
+
+packages:
+
+ /@algolia/autocomplete-core/1.7.1:
+ resolution: {integrity: sha512-eiZw+fxMzNQn01S8dA/hcCpoWCOCwcIIEUtHHdzN5TGB3IpzLbuhqFeTfh2OUhhgkE8Uo17+wH+QJ/wYyQmmzg==}
+ dependencies:
+ '@algolia/autocomplete-shared': 1.7.1
+ dev: true
+
+ /@algolia/autocomplete-preset-algolia/1.7.1_algoliasearch@4.14.2:
+ resolution: {integrity: sha512-pJwmIxeJCymU1M6cGujnaIYcY3QPOVYZOXhFkWVM7IxKzy272BwCvMFMyc5NpG/QmiObBxjo7myd060OeTNJXg==}
+ peerDependencies:
+ '@algolia/client-search': ^4.9.1
+ algoliasearch: ^4.9.1
+ dependencies:
+ '@algolia/autocomplete-shared': 1.7.1
+ algoliasearch: 4.14.2
+ dev: true
+
+ /@algolia/autocomplete-shared/1.7.1:
+ resolution: {integrity: sha512-eTmGVqY3GeyBTT8IWiB2K5EuURAqhnumfktAEoHxfDY2o7vg2rSnO16ZtIG0fMgt3py28Vwgq42/bVEuaQV7pg==}
+ dev: true
+
+ /@algolia/cache-browser-local-storage/4.14.2:
+ resolution: {integrity: sha512-FRweBkK/ywO+GKYfAWbrepewQsPTIEirhi1BdykX9mxvBPtGNKccYAxvGdDCumU1jL4r3cayio4psfzKMejBlA==}
+ dependencies:
+ '@algolia/cache-common': 4.14.2
+ dev: true
+
+ /@algolia/cache-common/4.14.2:
+ resolution: {integrity: sha512-SbvAlG9VqNanCErr44q6lEKD2qoK4XtFNx9Qn8FK26ePCI8I9yU7pYB+eM/cZdS9SzQCRJBbHUumVr4bsQ4uxg==}
+ dev: true
+
+ /@algolia/cache-in-memory/4.14.2:
+ resolution: {integrity: sha512-HrOukWoop9XB/VFojPv1R5SVXowgI56T9pmezd/djh2JnVN/vXswhXV51RKy4nCpqxyHt/aGFSq2qkDvj6KiuQ==}
+ dependencies:
+ '@algolia/cache-common': 4.14.2
+ dev: true
+
+ /@algolia/client-account/4.14.2:
+ resolution: {integrity: sha512-WHtriQqGyibbb/Rx71YY43T0cXqyelEU0lB2QMBRXvD2X0iyeGl4qMxocgEIcbHyK7uqE7hKgjT8aBrHqhgc1w==}
+ dependencies:
+ '@algolia/client-common': 4.14.2
+ '@algolia/client-search': 4.14.2
+ '@algolia/transporter': 4.14.2
+ dev: true
+
+ /@algolia/client-analytics/4.14.2:
+ resolution: {integrity: sha512-yBvBv2mw+HX5a+aeR0dkvUbFZsiC4FKSnfqk9rrfX+QrlNOKEhCG0tJzjiOggRW4EcNqRmaTULIYvIzQVL2KYQ==}
+ dependencies:
+ '@algolia/client-common': 4.14.2
+ '@algolia/client-search': 4.14.2
+ '@algolia/requester-common': 4.14.2
+ '@algolia/transporter': 4.14.2
+ dev: true
+
+ /@algolia/client-common/4.14.2:
+ resolution: {integrity: sha512-43o4fslNLcktgtDMVaT5XwlzsDPzlqvqesRi4MjQz2x4/Sxm7zYg5LRYFol1BIhG6EwxKvSUq8HcC/KxJu3J0Q==}
+ dependencies:
+ '@algolia/requester-common': 4.14.2
+ '@algolia/transporter': 4.14.2
+ dev: true
+
+ /@algolia/client-personalization/4.14.2:
+ resolution: {integrity: sha512-ACCoLi0cL8CBZ1W/2juehSltrw2iqsQBnfiu/Rbl9W2yE6o2ZUb97+sqN/jBqYNQBS+o0ekTMKNkQjHHAcEXNw==}
+ dependencies:
+ '@algolia/client-common': 4.14.2
+ '@algolia/requester-common': 4.14.2
+ '@algolia/transporter': 4.14.2
+ dev: true
+
+ /@algolia/client-search/4.14.2:
+ resolution: {integrity: sha512-L5zScdOmcZ6NGiVbLKTvP02UbxZ0njd5Vq9nJAmPFtjffUSOGEp11BmD2oMJ5QvARgx2XbX4KzTTNS5ECYIMWw==}
+ dependencies:
+ '@algolia/client-common': 4.14.2
+ '@algolia/requester-common': 4.14.2
+ '@algolia/transporter': 4.14.2
+ dev: true
+
+ /@algolia/logger-common/4.14.2:
+ resolution: {integrity: sha512-/JGlYvdV++IcMHBnVFsqEisTiOeEr6cUJtpjz8zc0A9c31JrtLm318Njc72p14Pnkw3A/5lHHh+QxpJ6WFTmsA==}
+ dev: true
+
+ /@algolia/logger-console/4.14.2:
+ resolution: {integrity: sha512-8S2PlpdshbkwlLCSAB5f8c91xyc84VM9Ar9EdfE9UmX+NrKNYnWR1maXXVDQQoto07G1Ol/tYFnFVhUZq0xV/g==}
+ dependencies:
+ '@algolia/logger-common': 4.14.2
+ dev: true
+
+ /@algolia/requester-browser-xhr/4.14.2:
+ resolution: {integrity: sha512-CEh//xYz/WfxHFh7pcMjQNWgpl4wFB85lUMRyVwaDPibNzQRVcV33YS+63fShFWc2+42YEipFGH2iPzlpszmDw==}
+ dependencies:
+ '@algolia/requester-common': 4.14.2
+ dev: true
+
+ /@algolia/requester-common/4.14.2:
+ resolution: {integrity: sha512-73YQsBOKa5fvVV3My7iZHu1sUqmjjfs9TteFWwPwDmnad7T0VTCopttcsM3OjLxZFtBnX61Xxl2T2gmG2O4ehg==}
+ dev: true
+
+ /@algolia/requester-node-http/4.14.2:
+ resolution: {integrity: sha512-oDbb02kd1o5GTEld4pETlPZLY0e+gOSWjWMJHWTgDXbv9rm/o2cF7japO6Vj1ENnrqWvLBmW1OzV9g6FUFhFXg==}
+ dependencies:
+ '@algolia/requester-common': 4.14.2
+ dev: true
+
+ /@algolia/transporter/4.14.2:
+ resolution: {integrity: sha512-t89dfQb2T9MFQHidjHcfhh6iGMNwvuKUvojAj+JsrHAGbuSy7yE4BylhLX6R0Q1xYRoC4Vvv+O5qIw/LdnQfsQ==}
+ dependencies:
+ '@algolia/cache-common': 4.14.2
+ '@algolia/logger-common': 4.14.2
+ '@algolia/requester-common': 4.14.2
+ dev: true
+
+ /@babel/parser/7.18.11:
+ resolution: {integrity: sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dev: true
+
+ /@docsearch/css/3.2.1:
+ resolution: {integrity: sha512-gaP6TxxwQC+K8D6TRx5WULUWKrcbzECOPA2KCVMuI+6C7dNiGUk5yXXzVhc5sld79XKYLnO9DRTI4mjXDYkh+g==}
+ dev: true
+
+ /@docsearch/js/3.2.1:
+ resolution: {integrity: sha512-H1PekEtSeS0msetR2YGGey2w7jQ2wAKfGODJvQTygSwMgUZ+2DHpzUgeDyEBIXRIfaBcoQneqrzsljM62pm6Xg==}
+ dependencies:
+ '@docsearch/react': 3.2.1
+ preact: 10.10.3
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+ - '@types/react'
+ - react
+ - react-dom
+ dev: true
+
+ /@docsearch/react/3.2.1:
+ resolution: {integrity: sha512-EzTQ/y82s14IQC5XVestiK/kFFMe2aagoYFuTAIfIb/e+4FU7kSMKonRtLwsCiLQHmjvNQq+HO+33giJ5YVtaQ==}
+ peerDependencies:
+ '@types/react': '>= 16.8.0 < 19.0.0'
+ react: '>= 16.8.0 < 19.0.0'
+ react-dom: '>= 16.8.0 < 19.0.0'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ dependencies:
+ '@algolia/autocomplete-core': 1.7.1
+ '@algolia/autocomplete-preset-algolia': 1.7.1_algoliasearch@4.14.2
+ '@docsearch/css': 3.2.1
+ algoliasearch: 4.14.2
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+ dev: true
+
+ /@esbuild/linux-loong64/0.14.54:
+ resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ dev: true
+ optional: true
+
+ /@types/web-bluetooth/0.0.15:
+ resolution: {integrity: sha512-w7hEHXnPMEZ+4nGKl/KDRVpxkwYxYExuHOYXyzIzCDzEZ9ZCGMAewulr9IqJu2LR4N37fcnb1XVeuZ09qgOxhA==}
+ dev: true
+
+ /@vitejs/plugin-vue/3.0.3_vite@3.0.8+vue@3.2.37:
+ resolution: {integrity: sha512-U4zNBlz9mg+TA+i+5QPc3N5lQvdUXENZLO2h0Wdzp56gI1MWhqJOv+6R+d4kOzoaSSq6TnGPBdZAXKOe4lXy6g==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^3.0.0
+ vue: ^3.2.25
+ dependencies:
+ vite: 3.0.8
+ vue: 3.2.37
+ dev: true
+
+ /@vue/compiler-core/3.2.37:
+ resolution: {integrity: sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg==}
+ dependencies:
+ '@babel/parser': 7.18.11
+ '@vue/shared': 3.2.37
+ estree-walker: 2.0.2
+ source-map: 0.6.1
+ dev: true
+
+ /@vue/compiler-dom/3.2.37:
+ resolution: {integrity: sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ==}
+ dependencies:
+ '@vue/compiler-core': 3.2.37
+ '@vue/shared': 3.2.37
+ dev: true
+
+ /@vue/compiler-sfc/3.2.37:
+ resolution: {integrity: sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg==}
+ dependencies:
+ '@babel/parser': 7.18.11
+ '@vue/compiler-core': 3.2.37
+ '@vue/compiler-dom': 3.2.37
+ '@vue/compiler-ssr': 3.2.37
+ '@vue/reactivity-transform': 3.2.37
+ '@vue/shared': 3.2.37
+ estree-walker: 2.0.2
+ magic-string: 0.25.9
+ postcss: 8.4.16
+ source-map: 0.6.1
+ dev: true
+
+ /@vue/compiler-ssr/3.2.37:
+ resolution: {integrity: sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw==}
+ dependencies:
+ '@vue/compiler-dom': 3.2.37
+ '@vue/shared': 3.2.37
+ dev: true
+
+ /@vue/devtools-api/6.2.1:
+ resolution: {integrity: sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ==}
+ dev: true
+
+ /@vue/reactivity-transform/3.2.37:
+ resolution: {integrity: sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg==}
+ dependencies:
+ '@babel/parser': 7.18.11
+ '@vue/compiler-core': 3.2.37
+ '@vue/shared': 3.2.37
+ estree-walker: 2.0.2
+ magic-string: 0.25.9
+ dev: true
+
+ /@vue/reactivity/3.2.37:
+ resolution: {integrity: sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A==}
+ dependencies:
+ '@vue/shared': 3.2.37
+ dev: true
+
+ /@vue/runtime-core/3.2.37:
+ resolution: {integrity: sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ==}
+ dependencies:
+ '@vue/reactivity': 3.2.37
+ '@vue/shared': 3.2.37
+ dev: true
+
+ /@vue/runtime-dom/3.2.37:
+ resolution: {integrity: sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw==}
+ dependencies:
+ '@vue/runtime-core': 3.2.37
+ '@vue/shared': 3.2.37
+ csstype: 2.6.20
+ dev: true
+
+ /@vue/server-renderer/3.2.37_vue@3.2.37:
+ resolution: {integrity: sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA==}
+ peerDependencies:
+ vue: 3.2.37
+ dependencies:
+ '@vue/compiler-ssr': 3.2.37
+ '@vue/shared': 3.2.37
+ vue: 3.2.37
+ dev: true
+
+ /@vue/shared/3.2.37:
+ resolution: {integrity: sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==}
+ dev: true
+
+ /@vueuse/core/9.1.0_vue@3.2.37:
+ resolution: {integrity: sha512-BIroqvXEqt826aE9r3K5cox1zobuPuAzdYJ36kouC2TVhlXvFKIILgFVWrpp9HZPwB3aLzasmG3K87q7TSyXZg==}
+ dependencies:
+ '@types/web-bluetooth': 0.0.15
+ '@vueuse/metadata': 9.1.0
+ '@vueuse/shared': 9.1.0_vue@3.2.37
+ vue-demi: 0.13.8_vue@3.2.37
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: true
+
+ /@vueuse/metadata/9.1.0:
+ resolution: {integrity: sha512-8OEhlog1iaAGTD3LICZ8oBGQdYeMwByvXetOtAOZCJOzyCRSwqwdggTsmVZZ1rkgYIEqgUBk942AsAPwM21s6A==}
+ dev: true
+
+ /@vueuse/shared/9.1.0_vue@3.2.37:
+ resolution: {integrity: sha512-pB/3njQu4tfJJ78ajELNda0yMG6lKfpToQW7Soe09CprF1k3QuyoNi1tBNvo75wBDJWD+LOnr+c4B5HZ39jY/Q==}
+ dependencies:
+ vue-demi: 0.13.8_vue@3.2.37
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: true
+
+ /algoliasearch/4.14.2:
+ resolution: {integrity: sha512-ngbEQonGEmf8dyEh5f+uOIihv4176dgbuOZspiuhmTTBRBuzWu3KCGHre6uHj5YyuC7pNvQGzB6ZNJyZi0z+Sg==}
+ dependencies:
+ '@algolia/cache-browser-local-storage': 4.14.2
+ '@algolia/cache-common': 4.14.2
+ '@algolia/cache-in-memory': 4.14.2
+ '@algolia/client-account': 4.14.2
+ '@algolia/client-analytics': 4.14.2
+ '@algolia/client-common': 4.14.2
+ '@algolia/client-personalization': 4.14.2
+ '@algolia/client-search': 4.14.2
+ '@algolia/logger-common': 4.14.2
+ '@algolia/logger-console': 4.14.2
+ '@algolia/requester-browser-xhr': 4.14.2
+ '@algolia/requester-common': 4.14.2
+ '@algolia/requester-node-http': 4.14.2
+ '@algolia/transporter': 4.14.2
+ dev: true
+
+ /body-scroll-lock/4.0.0-beta.0:
+ resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==}
+ dev: true
+
+ /csstype/2.6.20:
+ resolution: {integrity: sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==}
+ dev: true
+
+ /esbuild-android-64/0.14.54:
+ resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ dev: true
+ optional: true
+
+ /esbuild-android-arm64/0.14.54:
+ resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ dev: true
+ optional: true
+
+ /esbuild-darwin-64/0.14.54:
+ resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ dev: true
+ optional: true
+
+ /esbuild-darwin-arm64/0.14.54:
+ resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ dev: true
+ optional: true
+
+ /esbuild-freebsd-64/0.14.54:
+ resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ dev: true
+ optional: true
+
+ /esbuild-freebsd-arm64/0.14.54:
+ resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ dev: true
+ optional: true
+
+ /esbuild-linux-32/0.14.54:
+ resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ dev: true
+ optional: true
+
+ /esbuild-linux-64/0.14.54:
+ resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ dev: true
+ optional: true
+
+ /esbuild-linux-arm/0.14.54:
+ resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ dev: true
+ optional: true
+
+ /esbuild-linux-arm64/0.14.54:
+ resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ dev: true
+ optional: true
+
+ /esbuild-linux-mips64le/0.14.54:
+ resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ dev: true
+ optional: true
+
+ /esbuild-linux-ppc64le/0.14.54:
+ resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ dev: true
+ optional: true
+
+ /esbuild-linux-riscv64/0.14.54:
+ resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ dev: true
+ optional: true
+
+ /esbuild-linux-s390x/0.14.54:
+ resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ dev: true
+ optional: true
+
+ /esbuild-netbsd-64/0.14.54:
+ resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ dev: true
+ optional: true
+
+ /esbuild-openbsd-64/0.14.54:
+ resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ dev: true
+ optional: true
+
+ /esbuild-sunos-64/0.14.54:
+ resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ dev: true
+ optional: true
+
+ /esbuild-windows-32/0.14.54:
+ resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ dev: true
+ optional: true
+
+ /esbuild-windows-64/0.14.54:
+ resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ dev: true
+ optional: true
+
+ /esbuild-windows-arm64/0.14.54:
+ resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ dev: true
+ optional: true
+
+ /esbuild/0.14.54:
+ resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/linux-loong64': 0.14.54
+ esbuild-android-64: 0.14.54
+ esbuild-android-arm64: 0.14.54
+ esbuild-darwin-64: 0.14.54
+ esbuild-darwin-arm64: 0.14.54
+ esbuild-freebsd-64: 0.14.54
+ esbuild-freebsd-arm64: 0.14.54
+ esbuild-linux-32: 0.14.54
+ esbuild-linux-64: 0.14.54
+ esbuild-linux-arm: 0.14.54
+ esbuild-linux-arm64: 0.14.54
+ esbuild-linux-mips64le: 0.14.54
+ esbuild-linux-ppc64le: 0.14.54
+ esbuild-linux-riscv64: 0.14.54
+ esbuild-linux-s390x: 0.14.54
+ esbuild-netbsd-64: 0.14.54
+ esbuild-openbsd-64: 0.14.54
+ esbuild-sunos-64: 0.14.54
+ esbuild-windows-32: 0.14.54
+ esbuild-windows-64: 0.14.54
+ esbuild-windows-arm64: 0.14.54
+ dev: true
+
+ /estree-walker/2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+ dev: true
+
+ /fsevents/2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ dev: true
+ optional: true
+
+ /function-bind/1.1.1:
+ resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
+ dev: true
+
+ /has/1.0.3:
+ resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
+ engines: {node: '>= 0.4.0'}
+ dependencies:
+ function-bind: 1.1.1
+ dev: true
+
+ /is-core-module/2.10.0:
+ resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==}
+ dependencies:
+ has: 1.0.3
+ dev: true
+
+ /jsonc-parser/3.1.0:
+ resolution: {integrity: sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==}
+ dev: true
+
+ /magic-string/0.25.9:
+ resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
+ dependencies:
+ sourcemap-codec: 1.4.8
+ dev: true
+
+ /nanoid/3.3.4:
+ resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+ dev: true
+
+ /path-parse/1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ dev: true
+
+ /picocolors/1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+ dev: true
+
+ /postcss/8.4.16:
+ resolution: {integrity: sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.4
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: true
+
+ /preact/10.10.3:
+ resolution: {integrity: sha512-Gwwh0o531izatQQZu0yEX4mtfxVYsZJ4TT/o2VK3UZ/UuAWAWFnzsEfpZvad32vY3TKoRnSY2WqiDz2rH/viWQ==}
+ dev: true
+
+ /resolve/1.22.1:
+ resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.10.0
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /rollup/2.77.3:
+ resolution: {integrity: sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==}
+ engines: {node: '>=10.0.0'}
+ hasBin: true
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /shiki/0.11.1:
+ resolution: {integrity: sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==}
+ dependencies:
+ jsonc-parser: 3.1.0
+ vscode-oniguruma: 1.6.2
+ vscode-textmate: 6.0.0
+ dev: true
+
+ /source-map-js/1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /source-map/0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /sourcemap-codec/1.4.8:
+ resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
+ dev: true
+
+ /supports-preserve-symlinks-flag/1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /vite/3.0.8:
+ resolution: {integrity: sha512-AOZ4eN7mrkJiOLuw8IA7piS4IdOQyQCA81GxGsAQvAZzMRi9ZwGB3TOaYsj4uLAWK46T5L4AfQ6InNGlxX30IQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ hasBin: true
+ peerDependencies:
+ less: '*'
+ sass: '*'
+ stylus: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ less:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ esbuild: 0.14.54
+ postcss: 8.4.16
+ resolve: 1.22.1
+ rollup: 2.77.3
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /vitepress/1.0.0-alpha.8:
+ resolution: {integrity: sha512-kTRN5DCagvMqr9OjylSV9/waGg0IHrxL0hBVuJoz7ykleZq2qR02n5CaiFq5QrSB/VRBGqiVsFQzet9vJsXS8g==}
+ hasBin: true
+ dependencies:
+ '@docsearch/css': 3.2.1
+ '@docsearch/js': 3.2.1
+ '@vitejs/plugin-vue': 3.0.3_vite@3.0.8+vue@3.2.37
+ '@vue/devtools-api': 6.2.1
+ '@vueuse/core': 9.1.0_vue@3.2.37
+ body-scroll-lock: 4.0.0-beta.0
+ shiki: 0.11.1
+ vite: 3.0.8
+ vue: 3.2.37
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+ - '@types/react'
+ - '@vue/composition-api'
+ - less
+ - react
+ - react-dom
+ - sass
+ - stylus
+ - terser
+ dev: true
+
+ /vscode-oniguruma/1.6.2:
+ resolution: {integrity: sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==}
+ dev: true
+
+ /vscode-textmate/6.0.0:
+ resolution: {integrity: sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==}
+ dev: true
+
+ /vue-demi/0.13.8_vue@3.2.37:
+ resolution: {integrity: sha512-Vy1zbZhCOdsmvGR6tJhAvO5vhP7eiS8xkbYQSoVa7o6KlIy3W8Rc53ED4qI4qpeRDjv3mLfXSEpYU6Yq4pgXRg==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ peerDependencies:
+ '@vue/composition-api': ^1.0.0-rc.1
+ vue: ^3.0.0-0 || ^2.6.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+ dependencies:
+ vue: 3.2.37
+ dev: true
+
+ /vue/3.2.37:
+ resolution: {integrity: sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==}
+ dependencies:
+ '@vue/compiler-dom': 3.2.37
+ '@vue/compiler-sfc': 3.2.37
+ '@vue/runtime-dom': 3.2.37
+ '@vue/server-renderer': 3.2.37_vue@3.2.37
+ '@vue/shared': 3.2.37
+ dev: true