Skip to content

Mutueye/vite-vue3-scaffold

Repository files navigation

vite-vue3-scaffold 前端脚手架项目

概述

1. 定制目的

为统一团队前端项目技术栈(针对后续的常规web项目),规范开发环境配置,特定制此前端脚手架项目。

2. 技术选型规范表

根据具体 工具/包/插件 的使用要求,分为必选推荐参考三个级别:

  • 必选:如无特殊情况,要求必须使用该项工具/包/插件
  • 推荐:推荐优先选择,不做强制要求
  • 参考:针对一些常用工具,脚手架中给出使用范例,仅供参考

当前脚手架的技术选型,具体见下表:

类别 包/工具 使用要求 可选的替代 备注
IDE VS Code 推荐 Webstorm / Atom / sublime 等 结合vue3,推荐使用vscode + Volar插件的组合
包管理器 pnpm 推荐 yarn / npm pnpm vs npm vs yarn
构建 vite 必选 -- --
框架 vue 3 必选 React / Svelte 等 允许某些特殊项目需要React或其他框架
语言 typescript 必选 -- --
css预处理器 sass(scss) 必选 -- --
语法检查 eslint 必选 -- 具体规则可根据项目情况和个人习惯进行自主配置。推荐vscode的eslint插件(dbaeumer.vscode-eslint)
格式化 prettier 必选 -- 具体规则可根据项目情况和个人习惯进行自主配置。推荐vscode的prettier插件(esbenp.prettier-vscode)
样式语法检查 stylelint 必选 -- 具体规则可根据项目情况和个人习惯进行自主配置。推荐vscode的stylelint插件(stylelint.vscode-stylelint)
git提交预检 simple-git-hooks + lint-staged 推荐 husky + lingt-staged simple-git-hooks相比husky的配置更直观简单,性能更稳定
UI库 element-plus 必选 -- 根据项目具体情况,如不需要UI库可以不用
状态管理 pinia 必选 -- --
路由 vue-router 必选 -- --
网络 axios 必选 -- --
css框架 unocss 推荐 windicss / tailwind / twind unocss兼容windicss和tailwind,同时附带iconify等比较方便的功能; 推荐vscode的unocss插件(antfu.unocss)
图标 @unocss/preset-icons 推荐 -- unocss整合的iconify方案,可方便使用众多图标库,以及引入自定义图标
工具 lodash-es vueuse 参考 -- --
测试 vitest 参考 -- --

项目安装&启动

# 项目首次运行前,执行prepare脚本
$ pnpm prepare

# 安装依赖
$pnpm i

# 开发
$pnpm dev

# 打包
$pnpm build

里程碑/TODO

  • 基本框架,约定技术选型
  • cli工具
  • 表单通用验证规则范例
  • 表单通用交互规则范例
  • 统一的UI规范(色系/字体/间距等)
  • 更多..

从0开始的搭建记录

1. 创建vite项目

$ pnpm create vite

根据命令行提示,选择vue和typescript,然后cd到新建的项目目录下

2. package安装和更新

2.1 Node.js v16.13后引入了corepack作为"包管理器的管理器", 推荐项目使用pnpm作为包管理器。执行以下步骤启用pnpm:

  • 启用corepack

    # 当前应用激活
    $ corepack enable
  • 修改package.json,新增指定包管理器

    ...
    "packageManager": "pnpm@7.18.1"
    ...

2.2 更新包到最新版本

$ pnpm install
# 更新包到最新版本
$ pnpm up --latest

3. 配置Prettier

install prettier

$ pnpm add -D prettier

新增prettier.config.cjs 文件:

module.exports = {
  semi: true,
  tabWidth: 2,
  bracketSpacing: true,
  bracketSameLine: true,
  singleQuote: true,
  trailingComma: 'all',
  arrowParens: 'always',
  printWidth: 100,
  htmlWhitespaceSensitivity: 'ignore',
  endOfLine: 'auto',
  vueIndentScriptAndStyle: true
}

新增.prettierignore文件

node_modules/
public/
dist/
dist-ssr/
__snapshots__/
*.local
*.css
*.md
pnpm-lock.yaml
.DS_Store

package.json文件中添加format和format:check脚本:

{
  // ...
  "scripts": {
    // ...
    "format": "prettier . --write",
    "format:check": "prettier . --check",
    // ...

格式化当前项目代码:

$ pnpm format

4. 通用的node类型支持

安装 @types/node,给 __dirnameimport * as path from 'path'等加持ts类型支持 :

$ pnpm add -D @types/node

5. 配置env环境变量的类型支持

vite中配置环境变量的类型支持, 在src/vite-env.d.ts中添加interface ImportMetaEnv(如果没有vite-env.d.ts或者env.d.ts,在src目录下创建一个)

interface ImportMetaEnv {
  // .env中设置的各环境变量,例如VITE_BASE_URL
  VITE_BASE_URL: string
  ...
}

6. 配置src的目录别名@

配置src的目录别名,方便路径引入,例如 import HelloWorld from '@/components/HelloWorld.vue'.

编辑 vite.config.ts, 添加新的 resolve key, 如下:

import vue from '@vitejs/plugin-vue'
import * as path from 'path'
import { defineConfig } from 'vite'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
})

通过配置tsconfig,使typescript也可以解析该别名,并支持自动补全路径。在compilerOptions下添加baseUrl和paths配置:

{
  "compilerOptions": {
    // ...
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
    // ...

7. 配置eslint

安装eslint及相关插件:

$ pnpm add -D eslint eslint-plugin-vue eslint-config-prettier
$ pnpm add -D vue-eslint-parser @typescript-eslint/parser
$ pnpm add -D @typescript-eslint/eslint-plugin

新增 .eslintrc.cjs 文件:

module.exports = {
  env: { node: true },
  root: true,
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:vue/vue3-recommended',
    'prettier',
  ],
  parser: 'vue-eslint-parser',
  plugins: ['@typescript-eslint'],
  parserOptions: {
    parser: '@typescript-eslint/parser',
    sourceType: 'module',
  },
  rules: {
    '@typescript-eslint/explicit-function-return-type': 'warn',
  },
  globals: {
    defineEmits: 'readonly',
    defineProps: 'readonly',
  },
};

添加以下内容到 package.json 文件:

{
  // ...
  "scripts": {
    // ...
    "lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore --fix src/",
    "lint:check": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src/",
    // ...

src/vite-env.d.ts 添加eslint-disable:

/// <reference types="vite/client" />

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any
  const component: DefineComponent<{}, {}, any>
  export default component
}

执行pnpm lint进行代码格式化,并修复可能出现的语法错误

$ pnpm lint

8 安装&配置scss和stylelint

install packages

$ pnpm add -D sass postcss postcss-scss postcss-html stylelint stylelint-scss stylelint-config-standard-scss stylelint-config-recommended-vue stylelint-config-recess-order stylelint-config-css-modules
# 各package的功能说明:
# postcss // peer dependency of postcss-scss
# postcss-scss // peer dependency of stylelint-config-recommended-scss
# postcss-html // peer dependency of stylelint-config-recommended-vue
# stylelint-scss // lint-rules for scss
# stylelint-config-standard-scss // standard lint-rules configure for SCSS
# stylelint-config-recommended-vue // add overrides for .Vue files
# stylelint-config-recess-order // use the recess order for properties
# stylelint-config-css-modules // configure for CSS Modules methodology
# stylelint-config-prettier // turn off any rules that conflict with Prettier

新增stylelint.config.cjs文件:

module.exports = {
  plugins: ['stylelint-scss'],
  extends: [
    'stylelint-config-standard-scss', // configure for SCSS
    // 'stylelint-config-recommended-vue', // add overrides for .Vue files
    'stylelint-config-recommended-vue/scss', // add overrides for .Vue files
    'stylelint-config-recess-order', // use the recess order for properties
    'stylelint-config-css-modules', // configure for CSS Modules methodology
    // stylelint v15 nologner need stylelint-config-prettier
    // 'stylelint-config-prettier', // turn off any rules that conflict with Prettier
  ],
  rules: {
    'rule-empty-line-before': null,
    'comment-empty-line-before': null,
    'color-hex-length': null,
    'custom-property-empty-line-before': null,
    'selector-class-pattern': null,
    'value-keyword-case': null,
    // 'at-rule-no-unknown': [true, { ignoreAtRules: ['apply'] }],
    'at-rule-no-unknown': null,
    'scss/at-rule-no-unknown': true,
    // 'function-no-unknown': [true, { ignoreFunctions: ['theme'] }],
    'function-no-unknown': null,
    'scss/function-no-unknown': true,
    'scss/dollar-variable-pattern': null,
    'scss/dollar-variable-empty-line-before': null,
    'scss/selector-no-redundant-nesting-selector': true,
  },
  ignoreFiles: ['dist/**/*'],
};

编辑package.json,添加stylelint脚本

{
  // ...
  "scripts": {
    // ...
    "lint:style": "stylelint ./src/**/*.{vue,css,scss} --fix",
    "lint:style:check": "stylelint ./src/**/*.{vue,css,scss}",
    // ...

修改vscode配置.vscode/settings.json,禁用自带的样式检查器,使用stylelint进行css和scss的样式检查。

editor.codeActionsOnSave配置保存文件时进行stylelint和eslint自动格式化和错误修复。

{
  // ...
  "css.validate": false,
  "scss.validate": false,
  "less.validate": false,
  "stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
  "stylelint.validate": ["css", "less", "postcss", "scss", "vue"],
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.fixAll.stylelint": true
  }
  //...
}

注意保持vscode-stylelint插件默认设置,避免无法解析vue文件而报Unknown word (CssSyntaxError)错误。

执行stylelint,修复可能的样式语法错误

$ pnpm lint:style

9. 安装&配置simple-git-hooks 和 lint-staged

编辑package.json,添加pre-commit和lint-staged脚本

{
  ...
  "simple-git-hooks": {
    "pre-commit": "npx lint-staged"
  },
  "lint-staged": {
    "*.{vue,js,ts,jsx,tsx,md,json}": "eslint --ignore-path .gitignore --fix",
    "*.{vue,js,ts,jsx,tsx,md,json,scss,css}": "prettier . --write",
    "*.{scss,css,vue}": "stylelint --fix"
  }
  ...
}
pnpm add -D simple-git-hooks lint-staged
npm pkg set scripts.prepare="simple-git-hooks"
pnpm prepare

10. 常用库的安装&配置

10.1 安装&配置vue-router

install

$pnpm add vue-router

新增router文件src/router/index.ts:

import { createRouter, createWebHistory } from 'vue-router';

import Home from '@/modules/home/views/Home.vue';

export const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
  },
];

export const router = createRouter({
  history: createWebHistory(),
  routes,
});

编辑 src/main.ts 文件:

import { createApp } from 'vue'

import './style.css'
import App from './App.vue'
import { router } from './router'

createApp(App).use(router).mount('#app')

编辑App.vue文件,添加RouterView组件

10.2 安装pinia

$ pnpm add pinia

安装&配置详见pinia官方文档

10.3 安装element-plus

$ pnpm add element-plus

根据官方文档,按需选择完整引入或者按需引入,完整引入时build后element相关文件大小约0.8M。当前脚手架项目选择完整引入。

⚠️注意: 使用按需引入时,如果使用vscode + volar插件,仍然需要配置tsconfig来实现element组件的类型提示:

// tsconfig.json
{
  "compilerOptions": {
    // ...
    "types": ["element-plus/global"]
  }
}

10.4 安装&配置unocss

安装unocss和@iconify/json。@iconify/json包含了iconify所有的图标库,你也可以只安装需要用的图标库:@iconify-json/[the-collection-you-want]

$ pnpm add -D unocss @iconify/json

添加unocss插件到vite.config.ts

...
import Unocss from 'unocss/vite';
import {
  presetAttributify,
  presetIcons,
  presetUno,
  transformerDirectives,
  transformerVariantGroup,
} from 'unocss';

export default defineConfig({
  plugins: [
    vue(),
    Unocss({
      presets: [
        presetUno(),
        presetAttributify(),
        presetIcons({
          scale: 1.2,
          warn: true,
        }),
      ],
      transformers: [transformerDirectives(), transformerVariantGroup()],
    }),
  ]
  ...
});

在vite入口文件main.ts中引入unocss

import { createApp } from 'vue';
...
import 'uno.css'; // add this line
...
import App from '@/App.vue';

createApp(App).mount('#app');

10.5 安装axios

$ pnpm add axios

10.6 安装lodash-es, @vueuse/core and @vueuse/head

安装lodash-es

$ pnpm add lodash-es
$ pnpm add -D @types/lodash-es

安装@vueuse/core 和 @vueuse/head

$ pnpm add @vueuse/core @vueuse/head

11. 安装&配置vitest

添加如下内容到.gitignore:

# Vitest related files
__snapshots__/
coverage/

安装vitest:

$ pnpm add -D vitest @vitest/coverage-c8 @vue/test-utils jsdom

添加如下脚本到package.json:

{
  // ...
  "scripts": {
    // ...
    "test": "vitest run",
    "test:coverage": "vitest run --coverage",
    "test:update": "vitest --update",
    "test:watch": "vitest",
    // ...

编辑tsconfig.json,添加类型"vitest/globals":

{
  "compilerOptions": {
    // ...
    "types": ["element-plus/global", "vitest/globals"]
  }
}

添加如下内容到vite.config.ts,注意第一行添加reference标签:

/// <reference types="vitest" />

// ...
  test: {
    environment: 'jsdom',
    globals: true,
  }
})

创建文件test/setup.ts:

import { vi } from 'vitest'

Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: vi.fn().mockImplementation((query) => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: vi.fn(), // deprecated
    removeListener: vi.fn(), // deprecated
    addEventListener: vi.fn(),
    removeEventListener: vi.fn(),
    dispatchEvent: vi.fn(),
  })),
})

vi.mock('axios', () => {
  return {
    default: {
      create() {
        return {
          get() {
            return Promise.resolve({})
          },
          post() {
            return Promise.resolve({})
          }
        }
      }
    }
  }
})

编辑vite.config.ts,配置刚创建的setup文件:

{
  // ...
  test: {
    // ...
    setupFiles: [resolve(__dirname, 'test/setup.ts')]
  }
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •