Vue3项目企业级框架搭建

195 阅读10分钟

0. 前言

相关工具:vite、eslint、prettier、husky、commitlint、lint-staged、stylelint

当前系统环境

System:
    OS: Windows 10 10.0.19044
    CPU: (8) x64 Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz
    Memory: 7.19 GB / 15.84 GB
  Binaries:
    Node: 16.18.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 8.19.2 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.19041.1266.0), Chromium (107.0.1418.56)
    Internet Explorer: 11.0.19041.1566

参考:www.bilibili.com/video/BV1BV…

1. 使用vite脚手架初始化项目

pnpm create vite my-vue-app --template vue-ts

选择vue-ts的模板项目

修改vite.congfig.ts,修改域名端口,自动启动浏览器
server: {
	host: 'localhost',
	// port: 8080,
	open:true
}

2.代码加入eslint校验与自动格式化

eslint.bootcss.com/ nodejs工具

eslint 运行代码前就可以发现一些语法错误和潜在bug,目标是保证团队代码的一致性和避免错误

www.prettier.cn/

prettier是代码格式化工具,用于检测代码中的格式问题,比如单行代码长度、tab长度、空格、逗号表达式等

区别和联系:eslint偏向于把控项目的代码质量,而Prettier更偏向于统一项目的编码风格,esLint有小部分的代码格式化功能,一般和Prettier结合使用

pnpm install eslint eslint-plugin-vue eslint-config-prettier prettier eslint-plugin-import eslint-plugin-prettier eslint-config-airbnb-base -D

eslint: ESLint的核心代码块
prettier: prettier格式化代码的核心库
eslint-config-airbnb-base  airbnb的代码规范(依赖plugin-import)
eslint-config-prettier     eslint结合prettier的格式化
eslint-plugin-vue          eslint在vue里的代码规范
eslint-plugin-import       项目里支持eslint
eslint-plugin-prettier     将prettier结合进入eslint的插件

二、配置script脚本,项目安装eslint配置
"lint:create": "eslint --init",
执行 npm run lint:create

会自动创建一个.eslintrc.cjs文件

三、安装完成后,后面启动项目还缺少一些依赖,提前按需安装好
pnpm install typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-import-resolver-alias @types/eslint @types/node -D

@typescript-eslint/parser: ESLint的解析器,用于解析typescript,从而检查和规范Typescript代码
@typescript-eslint/eslint-plugin: 这是一个ESLint插件,包含了各类定义好的检测Typescript代码的规范
eslint-import-resolver-alias: 让我们可以import的时候使用@别名

3. eslintrc文件的修改

因为es1int是node工具,所以文件名是.cjs结尾(commonjs规范)--对应的就是.mjs Es module 规范

eslint.vuejs.org/rules/valid…

// .eslintrc.cjs文件

module.exports = {
  // 环境 浏览器,最新es语法,node环境
  "env": {
    "browser": true,
    "es2021": true,
    "node": true,
  },
  // 扩展的eslint规范语法,可以被继承的规则;字符串数组:每个配置继承它前面的配置
  // 分别是 eslint-plugin-vue提供的
  // eslint-config-airbnb-base提供的
  // eslint-config-prettier提供的
  // eslint-config- 前缀可以简写
  // https://eslint.vuejs.org/rules/valid-v-if.html
  "extends": ["plugin:vue/vue3-strongly-recommended", "airbnb-base", "prettier"],
  // ESLint会对我们的代码进行校验,而parser的作用是将我们写的代码转换为ESTree(AST),ESLint会对ESTree进行校验
  "parser": "vue-eslint-parser",
  "parserOptions": {
    // es的版本号,或者年份都可以
    "ecmaVersion": 13,
    "parser": "@typescript-eslint/parser",
    // 源码类型 默认是script, es模块使用module
    "sourceType": "module",
    // 额外的语言类型
    "ecmaFeatures": {
      "tsx": true,
      "jsx": true,
    },
  },
  // 全局自定义的宏,这样在源文件中使用全局变量就不会报错或者警告
  "globals": {
    "defineProps": "readonly",
    "defineEmits": "readonly",
    "defineExpose": "readonly",
    "withDefaults": "readonly",
  },
  // 插件
  // 前缀eslint-plugin- 可以省略
  // vue官方提供了一个ESLint插件 eslint-plugin-vue,它提供了parser和rules,parser为vue-eslint-parser,放在上面的parser字段里,rules放在extends字段里,选择合适的规则
  "plugins": ["vue", "@typescript-eslint"],
  "settings": {
    // 设置项目内的别名
    "import/resolver": {
      "alias": {
        "map": [["@", "./src"]],
      },
    },
    // 允许的扩展名
    "import/extensions": [".js", ".jsx", ".ts", ".tsx", ".mjs"],
  },
  // 自定义规则,覆盖上面extends继承的第三方库的规则,根据组内成员灵活定义
  "rules": {
    "import/no-extraneous-dependencies": 0,
    "no-param-reassign": 0,
    "vue/multi-word-component-names": 0,
    "vue/attribute-hyphenation": 0,
    "vue/v-on-event-hyphenation": 0,
  },
};
修改package.json文件,添加一个脚本命令
"lint": "eslint \"src/**/*.{js,vue,ts}\" --fix"

4. 修改vite.config.ts

pnpm install vite-plugin-eslint -D
vite的一个插件,让项目可以方便地得到eslint支持,完成eslint配置后,可以快速地将其集成进vite之中,便于在代码不符合eslint规范的第一时间看到提示

import eslintPlugin from 'vite-plugin-eslint'

plugins: [vue(), eslintPlugin()]
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslintPlugin from 'vite-plugin-eslint'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), eslintPlugin()],
	resolve:{
		// vite.config.js 配置全局src别名“@“
		alias:{
			'@': path.resolve(__dirname, './src')
		}
	},
  server: {
	host: 'localhost',
	// port: 8080,
	open:true
	}
})

5. 修改添加常见配置文件

新建外部文件 .eslintignore, .prettierrc.cjs, .prettierignore

.eslintignore

*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
/bin
.eslintrc.*js
prettier.config.js
/src/mock/*

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

.DS_Store
dist-ssr
*.local

/cypress/videos/
/cypress/screenshots/

# Editor directories and files
.vscode
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

components.d.ts
.prettierrc.cjs

module.exports = {
	// 一行最多 80 字符
	printWidth: 80,
	// 使用 2 个空格缩进
	tabWidth: 2,
	// 不适用缩进符,而是用空格
	useTabs: false,
	// 行尾需要有分号
	semi:false,
	// 使用单引号
	singleQuote: true,
	// 对象的 key 仅在必要时 用引号
	quoteProps: 'as-needed',
	// jsx不使用单引号,而使用双引号
	jsxSingleQuote: false,
	// 尾随逗号
	trailingComma: 'es5',
	// 大括号的首尾需要空格
	bracketSpacing: true,
	// 箭头函数,只有一个参数的时候,也需要括号
	arrowParens: 'always',
	// 每个文件格式化的范围是文件的全部内容
	rangeStart: 0,
	rangeEnd: Infinity,
	// 不需要写文件开头的 @prettier
	requirePragma: false,
	// 不需要自动在文件开头插入 @prettier
	insertPragma: false,
	// 使用默认的折行标准
	proseWrap: 'always',
	// 根据显示样式决定 html 要不要折行
	htmlWhitespaceSensitivity: 'css',
	// 换行符使用lf
	endOfLine: 'lf'
}
.prettierignore

/dist/*
.local
.output.js
/node_modules/**
src/.DS_Store

**/*.svg
**/*.sh

/public/*
components.d.ts
tsconfig.json
ts编译项目的根目录
各含义属性 -- https://www.typescriptlang.org/docs/handbook/compiler-options.html
https://www.tslang.cn/docs/handbook/compiler-options.html
https://vitejs.bootcss.com/guide/features.html#typescript
vite 使用esbuild将Typescript转译到JavaScript,但不执行任何类型检查,vue-tsc比tsc速度快
三斜线引用告诉编译器在编译过程中药引入的额外文件

{
  "compilerOptions": {
    // 指定es的目标版本
    "target": "esnext",
    "useDefineForClassFields": true,
    // "isolatedModules": true,
    // 决定如何处理模板
    "ModuleResolution": "node",
    "strict": true,
    "strictNullChecks": false,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    // 编译过程中需要引入的库文件的列表
    "lib": ["esnext", "dom", "DOM.Iterable"],
    // 默认所有课件的"@types"包会在编译过程中被包含进来
    "types": ["vite/client"],
    // 解析非相对模块名的基准目录
    "baseUrl": ".",
    // 模块名到基于baseUrl的路径映射的列表
    "paths": {
      "@/*": ["src/*"],
      "*.ts": ["*"]
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

package.json文件中,安装如下命令,利用prettier手动格式化一些样式问题

"prettier-format": "prettier --config .prettierrc.cjs \"src/**/*.{vue,js,ts}\" --write"

6. Husky、lint-staged、commitlint功能添加

husky是一个为git客户端增加hook的工具,在一些git操作前自动触发的函数

typicode.github.io/husky/#/

如果希望在检测错误的同时,自动修复eslint语法错误,就可以通过后面钩子实现

lint-staged过滤出Git代码暂存区文件(被git add的文件),将所有暂存文件的列表传递给任务

commitlint是对git commit提交的注释进行校验的工具

1. 可以让如git commit、git push执行前,预先处理指定的任务
pnpm install lint-staged husky -D

配置package.json文件
(项目需要先git init)
"prepare": "husky install"

npm run prepare -- 将husky安装完毕
2. 后面就开始添加各种git hook钩子
pre-commit钩子,一般添加的是lint-staged对git暂存区的代码做一些格式化的操作
npx husky add .husky/pre-commit "npx lint-staged"

add 追加
set 直接覆盖
3. lint-staged对暂存区里面的文件进行格式化修复等工作
pnpm isntall lint-staged -D

package.json文件中 添加
	"lint-staged": {
		"src/**/*.{js,ts,vue}":[
			"prettier --write",
			"eslint --fix",
			"git add"
		]
	}
或者放入脚本命令(推荐)
	"lint-staged": {
		"src/**/*.{js,jsx,vue,ts,tsx}": [
		"npm run lint",
		"npm run prettier-format"
		]
	}
或者
	"*.{ts,js,vue}": [
		"eslint --fix"
	],
	"*.{html,scss,css,vue}": [
		"prettier --write",
		"stylelint --fix"
	]

package.json文件里面添加两个脚本命令
"lint": "eslint \"src/**/*.{js,vue,ts}\" --fix"  // 既可以检查又可以修复部分语法问题
"prettier-format": "prettier --config .prettierrc.cjs \"src/**/*.{vue,js,ts}\" --write"  // 利用prettier手动格式化一些样式问题
4. 
pnpm install @commitlint/config-conventional @commitlint/cli -D
安装两个库,然后新建一个config文件

添加到git钩子里
npx husky add .husky/commit-msg "npx --no -- commitlint --edit ${1}" 通过命令添加钩子

使用 git commit -m "提交说明",进行提交,提交说明尽量清晰明了,说明本次提交的目的,推荐使用Angular规范,这是目前使用最广的写法
https://github.com/angular/angular/blob/main/CONTRIBUTING.md#commit

commitlint.config.cjs

module.exports = {
	extends: ['@commitlint/config-conventional'],
	rules: {
		'type-enum': [
			2,
			'always',
			[
				'build',   // 编译相关的修改,例如发布版本,对项目构建或者依赖的改动
				'feat',    // 新功能(feature)
				'fix',     // 修复bug
				'upd',     // 更新某功能
				'refactor',// 重构
				'docs',    // 文档
				'chore',   // 构建过程或辅助工具的变动,比如增加依赖库等
				'style',   // 格式(不影响代码运行的变动)
				'revert',  // 撤销commit,回滚到上一个版本
				'perf',    // 性能优化
				'test',    // 测试(单元、集成测试)
			]
		],
		'type-case': [0],
		'type-empty': [0],
		'scope-empty': [0],
		'scope-case': [0],
		'subject-full-stop': [0, 'never'],
		'subject-case': [0, 'never'],
		'header-max-length': [0, 'always', 72],
	},
};

常用的git hooks
pre-commit: 由 git commit调用,在commit之前执行
commit-msg: 由git commit 或 git merge 或 git commit --amend调用
pre-merge-commit: 由git merge调用,在merge之前执行
pre-push: 被git push调用,在git push前执行,防止进行推送

7.Stylelint钩子

CSS代码检查器(linter),帮助我们规避CSS代码中的错误并保持一致的编码风格

stylelint.bootcss.com/user-guide/…

Stylelint CSS代码检查器(linter),帮助我们规避CSS代码中的错误并保持一致的风格

1. 安装vscode插件 StyleLint插件
2. 修改settings.json,添加下面几行代码

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

3. 安装项目需要的校验库(常见的规则包)
pnpm install --save-dev stylelint stylelint-config-standard

4. 根目录建立 .stylelintrc.cjs
module.exports = {
	extends: [
		"stylelint-config-standard"
	]
}

这是一个标准样式库,也可以自动加一些规则,在.stylelintrc.cjs文件里面

5. 执行 npx stylelint "**/*.css"
发现项目里面的style.css全局样式文件报了很多错误,具体到对应文件,按ctrl+s就会自动格式化,在settings.json里面添加的json语句

修改错误的颜色值之后,执行 npx stylelint "**/*.css" 会告诉我们颜色错误 hex无效

6. 增加对vue里面的样式支持(附带less和sass的支持)
pnpm install stylelint-less stylelint-config-recommended-less -D 对less的支持
pnpm install stylelint-scss stylelint-config-recommended-scss postcss -D 对sass的支持
pnpm isntall postcss-html stylelint-config-standard-scss stylelint-config-recommended-vue postcss -D 对vue里面样式的支持(vue的样式需要依赖前面这个库)
Vite 也同时提供了对 .scss, .sass, .less, .styl 和 .stylus 文件的内置支持,不需要再按照特定插件和预处理器

	extends: [
		"stylelint-config-standard",
		"stylelint-config-recommended-less",
		"stylelint-config-recommended-scss",
		"stylelint-config-recommended-vue"
	]
	
	scss的extends
	extends: [
		"stylelint-config-standard-scss",
		"stylelint-config-recommended-vue/scss"
	]

7. package.json文件添加
"lint:css": "stylelint **/*.{vue,css,sass,scss,less} --fix",

8. 给vite添加插件
pnpm install vite-plugin-stylelint@~3.0.10 -D

vite.config.js
import StylelintPlugin from 'vite-plugin-stylelint';

plugins: [...StylelintPlugin({fix: true})]

9. 添加到 lint-stage里面,在暂存区对文件样式进行格式化
	"lint-staged": {
		"src/**/*.{js,jsx,vue,ts,tsx}": [
			"npm run lint",
			"npm run prettier-format"
		],
		"*.{vue,less,css,sass,scss}":[
			"npm run lint:css"
		]
	}

10. 最后添加一个.stylelintignore文件,忽略哪些文件不检查css,less,scss等
/dist/*
/public/*
node_modules

11. .stylelintrc.cjs内部的其他配置
module.exports = {
	extends: ["stylelint-config-standard", "stylelint-config-recommended-vue"],
	overrides: [
		// 若项目中存在scss文件,添加以下配置
		{
			files: ["*.scss", "**/*.scss"],
			customSyntax: "postcss-scss",
			extends: ["stylelint-config-recommended-scss"],
		},
		// 若项目中存在less文件,添加以下配置
		{
			files: ["*.less", "**/*.less"],
			customSyntax: "postcss-less",
			extends: ["stylelint-config-recommended-less"]
		}
	]
}

8. 环境和模式

cn.vitejs.dev/guide/env-a… 开发,测试,预发,生产

开发环境,一般叫dev

预发环境,一般叫pre

生产环境,一般叫pro

一般类似的域名是 dev.jd.com yewu-pre.jd.com yewu.jd.com

查看当前系统环境 npx envinfo --system --binaries --browsers

在package.json文件里面 写上对应的脚本

"build:pre": "vue-tsc --noEmit && vite build --mode staging"
"build:pro": "vue-tsc --noEmit && vite build --mode production"

新建3个文件
.env
.env.development
.env.staging
.env.production

http https 等域名问题
项目里面 看见外面配置的内容,使用VITE_开头
文件内容 VITE_BASE_URL = 'http://yewu-pre.jd.com/api'

9.调试功能与配置

.vscode文件里面,.launch.json文件、settings.json文件

增加项目的断点调试功能

settings.json

{
  "json.schemaDownload.enable": true,
  "emmet.triggerExpansionOnTab": true,
  "editor.tabSize": 2,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll": true,
    "source.fixAll.eslint": true,
    "source.fixAll.stylelint": true
  },
  "typescript.tsdk": "node_modules/typescript/lib",
  "stylelint.validate": ["css", "less", "scss", "vue"],
  "eslint.format.enable": true
  // "[html]": {
  //   "editor.formatOnSave": true,
  //   "editor.defaultFormatter": "esbenp.prettier-vscode"
  // },
  // "[css]": {
  //   "editor.formatOnSave": true,
  //   "editor.defaultFormatter": "esbenp.prettier-vscode"
  // },
  // "[less]": {
  //   "editor.formatOnSave": true,
  //   "editor.defaultFormatter": "esbenp.prettier-vscode"
  // },
  // "[vue]": {
  //   "editor.formatOnSave": true,
  //   "editor.defaultFormatter": "esbenp.prettier-vscode"
  // },
  // "[javascript]": {
  //   "editor.formatOnSave": true,
  //   "editor.defaultFormatter": "esbenp.prettier-vscode"
  // },
  // "[typescript]": {
  //   "editor.formatOnSave": true,
  //   "editor.defaultFormatter": "esbenp.prettier-vscode"
  // },
  // "[json]": {
  //   "editor.formatOnSave": true,
  //   "editor.defaultFormatter": "esbenp.prettier-vscode"
  // },
  // "[jsonc]": {
  //   "editor.formatOnSave": true,
  //   "editor.defaultFormatter": "esbenp.prettier-vscode"
  // }
}