本项目学习对象是优秀的后台系统模板vben-admin,期待通过学习解读该项目,熟悉前端项目工程化。
内容
- 创建项目
- 探索vite配置
- eslint+preitter自动代码风格化
1.创建项目
该项目由vite搭建,根据vite官网-开始-搭建第一个 Vite 项目栏目的说明创建一个基础的vue3+ts的初始项目。
2. 探索vite配置项
- 浏览vite的配置项,初始设置需要配置的内容
- 将某些配置内容多的单独提出来,目前只提出了plugin插件部分
- 安装了dayjs插件,目的获取时间格式化,这个插件只有几k
- 增加了.env文件,和对其值进行转换的工具方法
2.1 相关新增和变动的文件
vite.config.ts ----项目配置文件
import type { ConfigEnv, UserConfig } from 'vite'
import { wrapperEnv } from './build/utils'
import { defineConfig, loadEnv } from 'vite'
import dayjs from 'dayjs'
import pkg from './package.json'
import { resolve } from 'path';
import { createVitePlugins } from './build/vite/plugin';
// 当前app的依赖,版本,名称等信息
const { dependencies, devDependencies, name, version } = pkg;
const APP_INFO = {
pkg: { dependencies, devDependencies, name, version },
lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
};
/**
* @description: 根据配置文件的定义,这里决定使用传入一个方法的方式,返回一个配置内容
* @param {ConfigEnv} command 'build' | 'serve'
* @param {ConfigEnv} mode 'development'(开发模式)| 'production'(生产模式)
* @return {UserConfig}
*/
export default defineConfig(({command, mode}: ConfigEnv): UserConfig => {
const root = process.cwd();
const env = loadEnv(mode, root);
const viteEnv = wrapperEnv(env);
const { VITE_DROP_CONSOLE } = viteEnv;
return {
// 项目根目录(index.html 文件所在的位置)。可以是一个绝对路径,或者一个相对于该配置文件本身的相对路径。
root,
// 开发或生产环境服务的公共基础路径。
base: '/',
// 作为静态资源服务的文件夹。该目录中的文件在开发期间在 / 处提供,并在构建期间复制到 outDir 的根目录,并且始终按原样提供或复制而无需进行转换。
publicDir: 'public',
// 存储缓存文件的目录。此目录下会存储预打包的依赖项或 vite 生成的某些缓存文件,使用缓存可以提高性能。
// ps: 如需重新生成缓存文件,你可以使用 --force 命令行选项或手动删除目录。
cacheDir: 'node_modules/.vite',
// 定义全局常量替换方式。其中每项在开发环境下会被定义在全局,而在构建时被静态替换。
define: {
// app的信息
__APP_INFO__: JSON.stringify(APP_INFO),
},
resolve: {
// 当使用文件系统路径的别名时,请始终使用绝对路径。相对路径的别名值会原封不动地被使用,因此无法被正常解析。
alias: [
{
find: '@/',
replacement: resolve(process.cwd(), '.', 'src') + '/',
},
{
find: '#/',
replacement: resolve(process.cwd(), '.', 'types') + '/',
},
]
},
// 需要用到的插件数组。
plugins: createVitePlugins(viteEnv, command === 'build'),
server: {
// 如果将此设置为 0.0.0.0 或者 true 将监听所有地址,包括局域网和公网地址。
host: true,
// 指定开发服务器端口。注意:如果端口已经被使用,Vite 会自动尝试下一个可用的端口
port: 3000,
// 启用 TLS + HTTP/2。 当 server.proxy 选项 也被使用时,将会仅使用 TLS。
https: false,
// 在开发服务器启动时自动在浏览器中打开应用程序。当此值为字符串时,会被用作 URL 的路径名。
open: true,
// 为开发服务器配置自定义代理规则。
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
},
},
build: {
target: 'es2015',
outDir: 'dist',
assetsDir: 'assets',
// 小于此阈值的导入或引用资源将内联为 base64 编码,以避免额外的 http 请求。
assetsInlineLimit: 4096,
// 启用/禁用 CSS 代码拆分。当启用时,在异步 chunk 中导入的 CSS 将内联到异步 chunk 本身,并在其被加载时插入。
cssCodeSplit: true,
// 不开启map,map作用:在项目打包后,发生错误时,可能查看到哪一行代码报的错,负责代码都是压缩的,无法准确知道哪里的报错
sourcemap: false,
// 启用/禁用 brotli 压缩大小报告。压缩大型输出文件可能会很慢,因此禁用该功能可能会提高大型项目的构建性能。
brotliSize: false,
// chunk 大小警告的限制(以 kbs 为单位)。
chunkSizeWarningLimit: 500
},
esbuild: {
// 是否在构建中删除数组中列出的项目
pure: VITE_DROP_CONSOLE ? ['console.log', 'debugger'] : [],
},
// 以 envPrefix 开头的环境变量会通过 import.meta.env 暴露在你的客户端源码中。
envPrefix: 'VITE_',
}
})
.env
.env.production
.env.development
目前创建的环境变量的文件,下图是当前用到的环境变量,就一个
build/utils.ts —用于格式化从.env中获取的内容
/**
* @description: 给环境变量的值转换格式,因为默认都是字符串的
* @param {ViteEnv} envConf
* @return {*}
*/
export function wrapperEnv(envConf: any) {
const ret: any = {};
for (const envName of Object.keys(envConf)) {
let realName = envConf[envName].replace(/\\n/g, '\n');
realName = realName === 'true' ? true : realName === 'false' ? false : realName;
ret[envName] = realName;
if (typeof realName === 'string') {
process.env[envName] = realName;
} else if (typeof realName === 'object') {
process.env[envName] = JSON.stringify(realName);
}
}
return ret;
}
build/vite/index.ts —向vite项目中注册的插件
import { PluginOption } from 'vite';
import vue from '@vitejs/plugin-vue';
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const vitePlugins:(PluginOption | PluginOption[])[] = [
vue(),
]
return vitePlugins
}
types/global.d.ts --ts声明文件
declare interface ViteEnv {
VITE_DROP_CONSOLE: boolean;
}
tsconfig.json --ts配置
tsconfig.node.json该文件我已删除,目前用不到
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"allowSyntheticDefaultImports": true,
"module": "esnext",
"moduleResolution": "node",
"checkJs": true,
"strict": true,
"jsx": "preserve",
"baseUrl": ".",
"sourceMap": true,
"resolveJsonModule": true,
"removeComments": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"paths": {
"@/*": ["src/*"],
"#/*": ["types/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "types/**/*.d.ts", "src/**/*.vue", "vite.config.ts"],
"exclude": ["node_modules", "dist", "**/*.js"]
}
3. eslint+preitter自动代码风格化
需要安装的依赖
eslint —代码规则检查
prettier —代码风格化插件
eslint-config-airbnb-base —vite vue 可用的airbnb代码规范的eslint插件
eslint-config-prettier —关闭eslint中所有不必要或可能与Prettier冲突的规则。
eslint-import-resolver-alias —使得eslint获得对路径别名的支持
eslint-plugin-import —该插件旨在支持 ES2015+ (ES6+) 导入/导出语法的 linting,并防止文件路径和导入名称拼写错误的问题。
eslint-plugin-prettier —使得eslint可以遵循prettier的规则
eslint-plugin-vue —使得eslint获得对vue文件的代码规则检查
vite-plugin-eslint —使得vite可以将eslint的检查结果显示浏览器上
@typescript-eslint/eslint-plugin --增加es对ts的支持
@typescript-eslint/parser --ts解释器
npm i -D eslint prettier eslint-config-airbnb-base eslint-config-prettier eslint-plugin-html eslint-import-resolver-alias eslint-plugin-import eslint-plugin-prettier eslint-plugin-vue vite-plugin-eslint
.eslintrc.js —eslint配置文件,(此文件添加后,编辑器应该已经获得了eslint的代码检查)
module.exports = {
root: true,
env: {
browser: true,
es6: true,
node: true
},
parser: 'vue-eslint-parser', // 该解释器是由eslint-plugin-vue带有的
extends: [
'plugin:vue/vue3-recommended', // 使得支持vue的eslint检查
'plugin:@typescript-eslint/recommended', // 使得支持ts的eslint检查
'airbnb-base', // 按照aribnb规范
'plugin:prettier/recommended' // eslint-config-prettier使得eslint格式有关的检查都扔给prettier去处理
],
plugins: ['vue', '@typescript-eslint', 'prettier'],
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2020,
sourceType: 'module',
jsxPragma: 'React',
ecmaFeatures: {
jsx: true
}
},
settings: {
'import/resolver': {
alias: {
map: [['@', './src']],
// 可能是自动添加后缀吧,得跟下面规则中的忽略文件后缀一起使用\
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
}
}
},
rules: {
'prettier/prettier': 'error',
'import/no-extraneous-dependencies': ['error', { devDependencies: true }], // 允许导入的第三方库存在在devDependencies中
'import/extensions': [
'error',
'ignorePackages', // 忽略文件后缀
{
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never'
}
],
// 允许修改传入的对象上的属性
'no-param-reassign': [
'error',
{
props: false
// ignorePropertyModificationsFor: [
// 'config', // for axios
// 'state' // for vuex state
// ]
}
]
}
}
.prettierrc.js —preittier的风格化配置
module.exports = {
printWidth: 140, // 一行的字符数,如果超过会进行换行,默认为80,官方建议设100-120其中一个数
tabWidth: 2, // 一个tab代表几个空格数,默认就是2
useTabs: false, // 启用tab取代空格符缩进,默认为false
semi: false, // 行尾是否使用分号,默认为true
singleQuote: true, // 字符串是否使用单引号,默认为false,即使用双引号,建议设true,即单引号
quoteProps: 'as-needed', // 给对象里的属性名是否要加上引号,默认为as-needed,即根据需要决定,如果不加引号会报错则加,否则不加
trailingComma: 'none', // 是否使用尾逗号,有三个可选值"<none|es5|all>"
jsxSingleQuote: false, // 在jsx里是否使用单引号,你看着办
bracketSpacing: true, // 对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
endOfLine: 'auto',
}
build\vite\plugin\eslint.ts — 将eslint可视化插件的配置
import eslintPlugin from 'vite-plugin-eslint';
export default function configEslintPlugin() {
return eslintPlugin({
include: ['src/**/*.js', 'src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'],
exclude: ['./node_modules/**'],
cache: false,
fix: true
})
}
build\vite\plugin\index.ts – 在这里引入刚创建的eslint插件
.vscode/settings.json —在该项目的vscode编辑器的配置文件中需要设置关于eslint的配置项,(添加后应该已经可以保存自动格式化)
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.fixAll.eslint": true
},
"eslint.alwaysShowStatus": true,
"eslint.validate": [
"vue",
"javascript",
"javascriptreact",
"html",
"typescript"
],
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"eslint.options": {
"overrideConfig": {
"env": {
"browser": true,
"es6": true
},
"parserOptions": {
"ecmaVersion": 2019,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"no-debugger": "off"
}
}
},