vite+vue3工程化实践

1,345 阅读5分钟

一、vite简介

vite是一个开发构建工具,开发过程中它利用 原生 ESM 方式提供源码,让浏览器接管了打包程序的部分工作,生产中利用rollup作为打包工具

Vite 使用 esbuild 预构建依赖。Esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍

目前vite已经更新到了2.0正式版

在本文中将使用vite2搭配vue3构建一个前端工程化的大体流程,实现: css/js代码规范、git提交规范、组件库按需引入配置、svg雪碧图全局引入等功能

二、创建项目

yarn create vite my-app

选择vue模版

三、配置eslint

1、安装相关插件

npm install eslint eslint-config-alloy @babel/eslint-parser eslint-plugin-vue vue-eslint-parser @typescript-eslint/eslint-plugin @typescript-eslint/parser -D

eslint-plugin-vue vue官方eslint插件
vue-eslint-parser vue文件Eslint解析器
eslint-config-alloy 团队常用规范
@babel/eslint-parser babel解析器 允许ESLint在Babel 转换的源代码上运行
@typescript-eslint/eslint-plugin TS代码验证插件
@typescript-eslint/parser ts解析器

2、编写eslint配置文件

// 项目根目录 .eslinttrc.js
module.exports = {
  root: true,
  env: {
    browser: true,
    node: true,
    es2021: true,
  },
  // VUE模版解析器
  parser: 'vue-eslint-parser',
  parserOptions: {
    ecmaVersion: 2020,
    // TypeScript ESLint 解析器
    parser: '@typescript-eslint/parser',
    sourceType: 'module',
  },
  extends: ['alloy', 'alloy/vue', 'alloy/typescript'],
  globals: {
    defineProps: 'readonly',
    defineEmits: 'readonly',
    defineExpose: 'readonly',
    withDefaults: 'readonly',
    defineComponent: 'readonly',
    ref: 'readonly',
    computed: 'readonly',
    ...
  },
  rules: {
    // 配合vue/no-multiple-template-root自动引入
    'vue/no-multiple-template-root': 'off',
    ...
  },
};

四、配置prettier

1、安装prettier

npm install prettier -D

2、配置prettier

// 项目根目录 .prettierrc.js
module.exports = {
  printWidth: 120,
  tabWidth: 2,
  useTabs: false,
  semi: true,
  ...
};

五、配置stylelint

1、安装相关插件

npm install sass stylelint stylelint-config-html postcss-html stylelint-config-prettier stylelint-config-standard-scss stylelint-order -D

sass vite内置对scss less文件的支持,但必须安装相对应的预处理器依赖
stylelint-config-html postcss-html 捆绑使用,解析vue文件,对vue里面的css代码进行解析
stylelint-config-recommended-vue 推荐的vue配置
stylelint-config-standard-scss stylelint的标准SCSS配置
stylelint-order css样式书写顺序规则插件(个人认为css书写顺序还是有必要)
stylelint-config-prettier 解决stylelint和pretiier的冲突

2、配置stylelintrc

// 项目根目录 .stylelintrc.js
module.exports = {
  extends: ['stylelint-config-standard-scss'],
  root: true,
  plugins: ['stylelint-order'],
  rules: {
    // csss样式书写顺序
    'order/order': ['custom-properties', 'declarations'],
    'order/properties-order': [
      'position',
      'top',
      'right',
      'bottom',
      'left',
      'overflow',
      'margin',
      'padding',
      'width',
      'height',
      ...
    ],
  },
  ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts', '**/*.svg'],
  overrides: [
    {
      extends: ['stylelint-config-recommended-vue/scss', 'stylelint-config-html/vue'],
      files: ['*.vue', '**/*.vue'],
      rules: {
        'selector-pseudo-element-no-unknown': [
          true,
          {
            ignorePseudoElements: ['v-deep'],
          },
        ],
        'selector-pseudo-element-no-unknown': [
          true,
          {
            ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'],
          },
        ],
      },
    },
  ],
};

六、配置git提交规范

一般项目中的git规范验证需要husky+commitLint,本文使用yorkie来实现git自定义规范验证

注:yorkie是尤雨溪魔改的husky插件,轻量级,不需要过多的配置,不过需要自己写具体验证的方法

1、安装插件

npm install yorkie chalk@.1.2 -D
  注:
  1. 下载之前最好是已生成.git文件,如果下载插件没有git记录,
  需要在生成git文件之后手动的去执行yorkie的install方法
  node node_modules/yorkie/bin/install.js
  2. 最好不要用pnpm来下载,第一次下载此插件没有问题,
  但如果是本地有过下载记录,pnpm会指向下载插件的地址,并不会真正的下载,
  也就不会去获取项目本身的git环境
  3. yorkie插件就是在本地记录了git的生命周期钩子函数并暴露出来,前提是项目本身有git文件
  4. chalk命令行工具下载 4.1.2版本,最高版本和yorkie有冲突

2、自定义git提交commit验证

// 新建git-commit.js文件  根目录scripts/git-commit.js

#!/usr/bin/env node

const fs = require('fs');

const chalk = require('chalk');

const gitParams = process.env.HUSKY_GIT_PARAMS || '.git/COMMIT_EDITMSG';
const prefixes = [
  'feat',
  'fix',
  'docs',
  'merge',
  'style',
  'refactor',
  'perf',
  'test',
  'build',
  'ci',
  'chore',
  'revert',
];

const commitRE = new RegExp(`^(${prefixes.join('|')}): .{1,50}`);
const similarRE = /(^[a-zA-Z]+):/;
chalk.level = 1;
let message = fs.readFileSync(gitParams, 'utf-8').trim();
const commitPrefixOption = {
  feat: '    新增功能',
  fix: '     修复了一些 bug',
  docs: '    更新了一下文档',
  merge: '   合并某个分支的代码(解决冲突)',
  style: '   不影响程序逻辑的代码修改(修改空白字符,格式缩进,补全缺失的分号等,没有改变代码逻辑)',
  refactor: '重构已有模块代码',
  perf: '    性能, 体验优化',
  test: '    新增测试用例或是更新现有测试',
  build: '   主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交',
  ci: '      主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交',
  chore: '   不属于以上类型的其他类,比如构建流程, 依赖管理',
  revert: '  回滚某个更早之前的提交',
};
...........

3、添加命令

 // package.json
"gitHooks": {
    "commit-msg": "node scripts/git.commit.js"
  },

接下来看看效果,随便改一个文件提交一下

效果如下

试一下正确的提交

成功提交

七、配置lint-staged

接下来把我们上面配置的所有插件全部集成到一起,这就需要用到了lint-staged 插件

1、安装插件

npm install lint-staged -D

2、添加命令

// package.json 

  "scripts": {
    "lint:fix": "npm run lint:js && npm run lint:style",
    "lint:js": "eslint --fix --cache --ext .vue,.js,.jsx,.ts,.tsx ./src",
    "lint:style": "stylelint --fix "**/*.{vue,less,postcss,css,scss}" ./src",
    "lint-staged:js": "eslint --ext .vue,.js,.jsx,.ts,.tsx ./src",
    "lint-staged:css": "stylelint --aei --cache "**/*.{vue,less,postcss,css,scss}" ./src",
    "lint-staged": "lint-staged"
  },
  "lint-staged": {
    "**/*.{vue,scss,css}": "npm run lint-staged:css",
    "**/*.{vue,js,jsx,ts,tsx}": "npm run lint-staged:js",
    "**/*.{vue,js,jsx,tsx,ts,scss,md,json}": [
      "prettier --write"
    ]
  },
  "gitHooks": {
    "pre-commit": "lint-staged",
    "commit-msg": "node scripts/git.commit.js"
  },

现在我们已经完成了所有的配置命令,在git提交的时候,我们的配置会对项目里的代码进行 eslint/prettier/stylelint的代码验证,然后会紧接着对git commit提交的信息进行验证

实验一下

找个文件故意写错js代码和css代码

根据我们的eslint规范和css配置的样式顺序规范,这两段代码都是错的

执行git 提交

结果如下

从上面的测试中我们可看出 不可使用var声明变量,和css代码 position要放在width之前的问题

\

现在我们有两种方式可以改正,一是手动修改,二是执行我们配置好的npm run lint:fix修复代码命令来修复代码

接下来我们执行npm run lint:fix

结果如下

然后我们的代码文件已经被自动修复成为符合我们代码规范的代码了

接下来我们再次提交

目前我们的提交流程到此结束

八、提高开发效率的vscode配置

1、vscode开发相关的插件

ESLint Prettier Stylelint Volar(vue3使用)

使用这些插件可以更好的在项目开发过程中提高我们的效率

上面的一些插件搭配vscode配置文件才可以让收益最大化

2、配置.vscode配置文件

在项目根目录新建.vscode文件夹,新建settings.json

配置文件看个人喜好,比如在保存文件的时候自动修复代码格式

{
  "files.eol": "\n",
  "volar.tsPlugin": false,
  "volar.tsPluginStatus": false,
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll": true,
    "addMissingImports": true
  },
  "[vue]": {
    "editor.codeActionsOnSave": {
      "source.fixAll": true
    }
  },
  "eslint.validate": ["javascript", "javascriptreact", "vue", "typescript", "typescriptreact"],
  "stylelint.validate": ["vue", "html", "css", "scss"],
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[html]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[less]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[scss]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[markdown]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

新建extensions.json

{
  "recommendations": [
    "johnsoncodehk.volar",
    "dbaeumer.vscode-eslint",
    "stylelint.vscode-stylelint",
    "esbenp.prettier-vscode"
  ]
}

九、vite/vue3实用性较强的插件

1、unplugin-auto-import

此插件可以为 Vite、Webpack 和 Rollup 按需自动导入 API

看一下效果

//使用插件之前我们是这样编写vue3代码的
<script setup>
import { ref, computed } from 'vue'
const count = ref(0)
const doubled = computed(() => count.value * 2)
</script>  

//使用插件之后
<script setup>
const count = ref(0)
const doubled = computed(() => count.value * 2)
</script> 

安装插件

npm install unplugin-auto-import -D

配置vite

注:安装的时候会自动的生成auto-imports.d.ts在根目录,也可以指定路径,

如果不使用ts开发也可以改为false

unplugin-auto-import还支持axios/vueuse等库的自动引入api

//vite.config.ts
import vue from '@vitejs/plugin-vue';
import AutoImport from 'unplugin-auto-import/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    vue(),
    // 按需自动导入 API
    AutoImport({
      dts: 'types/auto-imports.d.ts',
      //dts: false,
      include: [/.[tj]sx?$/, /.vue$/, /.vue?vue/],
      imports: ['vue', 'vue-router'],
    }),
  ],
});

在当前的项目配置中,在页面没有引入的情况下使用api会引起我们的eslint报错,有两种解决方案

1、安装vue-gloabl-api配置我们的eslint

// .eslintrc.js
module.exports = {
  extends: [
    'vue-global-api'
  ]
};

2、手动的在eslint配置的 global中添加我们使用的api

// .eslintrc.js  
globals: {
    defineProps: 'readonly',
    defineEmits: 'readonly',
    defineExpose: 'readonly',
    withDefaults: 'readonly',
    defineComponent: 'readonly',
    ref: 'readonly',
    computed: 'readonly',
    ...
  },

2、unplugin-vue-components

此插件为Vue 的按需组件自动导入

看一下效果

//使用前
<template>
  <div>
    <HelloWorld msg="Hello Vue 3.0 + Vite" />
  </div>
</template>
<script>
import HelloWorld from './src/components/HelloWorld.vue'
export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

//使用后
<template>
  <div>
    <HelloWorld msg="Hello Vue 3.0 + Vite" />
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

搭配组件库使用,例如Element-plus/Vant/Ant Design Vue/View,插件中都有支持按需引入

安装插件

npm install unplugin-vue-components -D

配置vite

注:安装的时候会自动的生成components.d.ts在根目录,也可以指定路径,

如果不使用ts开发也可以改为false

在tsconfig.json添加components.d.ts到includes

按需引入element-plus的时候也可以搭配unplugin-auto-import使用,不使用也没有影响

我们本地开发的组件也支持自动引入

//vite.config.ts
import vue from '@vitejs/plugin-vue';
import AutoImport from 'unplugin-auto-import/vite';
import { defineConfig } from 'vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
export default defineConfig({
  plugins: [
    vue(),
    // 按需自动导入 API
    AutoImport({
      dts: 'types/auto-imports.d.ts',
      //dts: false,
      include: [/.[tj]sx?$/, /.vue$/, /.vue?vue/],
      imports: ['vue', 'vue-router'],
    }),
     // 按需组件自动导入
    Components({
      dts: 'types/components.d.ts',
       //dts: false,
      resolvers: [ElementPlusResolver()],
      include: [/.vue$/, /.vue?vue/],
    }),
  ],
});

3、vite-plugin-svg-icons

此插件用于生成svg雪碧图

预加载在项目运行时就生成所有图标, 流行操作一次dom

高性能内置缓存,仅当文件被修改时才会重新生成

安装插件

npm install vite-plugin-svg-icons -D

配置vite

//vite.config.ts
import vue from '@vitejs/plugin-vue';
import path from 'path';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import viteSvgIcons from 'vite-plugin-svg-icons';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
import { defineConfig } from 'vite';

export default defineConfig({
  base: './',
  plugins: [
    vue(),
    // 按需组件自动导入
    Components({
      dts: 'types/components.d.ts',
      resolvers: [ElementPlusResolver()],
      include: [/.vue$/, /.vue?vue/],
    }),
    // 按需自动导入 API
    AutoImport({
      dts: 'types/auto-imports.d.ts',
      include: [/.[tj]sx?$/, /.vue$/, /.vue?vue/],
      imports: ['vue', 'vue-router'],
      // resolvers: [ElementPlusResolver()],
    }),
    // 在项目运行时生成svg雪碧图
    viteSvgIcons({
      iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
      symbolId: 'icon-[dir]-[name]',
    }),
  ],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
});

在main.ts/js引入插件注册

//main.ts
import 'virtual:svg-icons-register';

封装一个icon组件

//src/components/SvgIcon.vue
<template>
  <svg aria-hidden="true" :style="getStyle">
    <use :xlink:href="symbolId" :fill="color" />
  </svg>
</template>

<script lang="ts" setup>
import type { CSSProperties } from 'vue';
interface Props {
  name: string;
  prefix?: string;
  color?: string;
  size?: string | number;
}
const props = withDefaults(defineProps<Props>(), {
  prefix: 'icon',
  color: '#333',
  size: 16,
});
const symbolId = computed(() => `#${props.prefix}-${props.name}`);
const getStyle = computed((): CSSProperties => {
  const { size } = props;
  let s = `${size}`;
  s = `${s.replace('px', '')}px`;
  return {
    width: s,
    height: s,
  };
});
</script>

看一下效果,在我们插件配置的制定文件夹里面放入svg文件

由于我们使用了unplugin-vue-components插件,不需要引入就可以使用该标签

在我们引入使用之后会自动的在components.d.ts加入组件引用的类型声明

看一下效果

<template>
  <div class="wrap">
    <el-button>demo</el-button>
    <el-input />
    <svg-icon name="upload" size="19"></svg-icon>
  </div>
</template>

<style lang="scss">
.wrap {
  margin: 50px auto;
  width: 500px;
}
</style>

组件引入之后,components.d.ts文件自动更新

页面效果

看一下浏览器资源概览

我们的按需引入组件和svg插件的配置成功了

十、总结

总体来说配置vite比webpack简单很多,有一种丝滑般的体验,现在vite生态已经很不错了,社区内有很多比较不错的插件,开发过程中,运行速度不是一般的快,能明显感觉到比webpack快了不少,对于技术栈以vue为主的开发团队来说是不错的选择,vite第一优先级支持vue,包括vue2的支持也是无缝衔接,推荐在接下来的中小项目中尝试使用vite开发。