vite+vue3项目配置

970 阅读8分钟

创建基础项目

pnpm create vite

image.png

package.json 配置 "type": "module",即模块化使用ESM 若使用"type": "commonjs",则以下配置文件需使用 CJS语法导出

jsconfig.json

根目录创建 jsconfig.json 文件,告诉 vscode 这是一个 javascript 项目,启用项目特定的功能,如路径解析跳转

{
  "compilerOptions": {
    "baseUrl": ".",
  },
    "include": [
    "src/**/*.js",
    "src/**/*.vue",
  ]
}

低版本兼容

pnpm add @vitejs/plugin-legacy -D
// vite.config.js
import legacy from '@vitejs/plugin-legacy'

export default defineConfig({
  plugins: [
    //  兼容性处理
    legacy({
       targets: ['> 1%', 'last 2 versions', 'not dead', 'not ie 11'], // 设置目标浏览器,browserslist 配置语法
    }),
  ],
})

开发环境 https 配置

pnpm add vite-plugin-mkcert -D
// vite.config.js
import mkCert from 'vite-plugin-mkcert'

export default defineConfig({
  plugins: [
    // https 生成证书
    mkCert(),
  ],
  server: {
    https: true,
  },
})

打包产物体积报告

pnpm add rollup-plugin-visualizer -D
// vite.config.js
import { visualizer } from 'rollup-plugin-visualizer'

export default defineConfig({
  plugins: [
     // 打包完成后自动打开浏览器,显示产物体积报告
    visualizer({ open: true }),
  ],
})

图片压缩

pnpm add vite-plugin-imagemin -D
// vite.config.js
import viteImagemin from 'vite-plugin-imagemin'

export default defineConfig({
  plugins: [
    // 图片压缩
    viteImagemin({
      // 无损压缩配置,无损压缩下图片质量不会变差
      optipng: {
        optimizationLevel: 7,
      },
      // svg 优化
      svgo: {
        plugins: [
          { name: 'removeViewBox' },
          { name: 'removeEmptyAttrs', active: false },
        ],
      },
    }),
  ],
})

svg 图标雪碧图

pnpm add vite-plugin-svg-icons -D
// vite.config.js
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'

export default defineConfig({
  plugins: [
    // svg 图标雪碧图
    createSvgIconsPlugin({
      iconDirs: [path.join(__dirname, 'src/assets/svg-icons')],
      symbolId: 'icon-[name]',
    }),
  ],
})

在项目src/assets目录下创建svg-icons文件夹,将svg文件存放在里面

image.png

注意:要将 svg 文件中的fill="xxx"代码删除,否则无法自定义颜色

入口文件main.js引入雪碧图

// main.js
import 'virtual:svg-icons-register'

创建 svg 图标组件

<!-- 
  名称:svg-icon
 -->
<script setup>
const props = defineProps({
  // svg 文件的名称
  name: {
    type: String,
    default: '',
  },
})

const symbolId = computed(() => `#icon-${props.name}`)
</script>

<template>
  <svg aria-hidden="true" v-bind="$attrs">
    <use :href="symbolId" />
  </svg>
</template>

<style lang="scss" scoped></style>

ESLint + Prettier

代码校验及格式化统一

注意 eslint8eslint9 配置文件大更新,本文使用eslint8

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

根目录下创建 .eslintrc.cjs文件,(eslint8不支持ESM,所以使用.cjs强制使用common模块化)

// .eslintrc.cjs
module.exports = {
  root: true,
  env: {
    node: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-recommended',
    '@vue/prettier',
  ],
  parserOptions: {
    ecmaVersion: 2022,
    parser: '@babel/eslint-parser',
    requireConfigFile: false,
    sourceType: 'module',
  },
  rules: {
    // 禁止声明未使用的变量。
    'no-unused-vars': [
      'error',
      {
        vars: 'all', // 检查所有变量
        args: 'none', // 不检查函数参数
      },
    ],
    'prefer-const': 'error', // 如果变量不会被重新赋值,则使用 const。
    eqeqeq: 'error', // 要求使用全等运算符(=== 和 !==)。
  },
}


根目录下创建 .prettierrc文件

补充 ESLint9 + Prettier

image.png

pnpm add globals eslint prettier eslint-plugin-prettier eslint-config-prettier eslint-plugin-vue @vue/eslint-config-prettier @babel/eslint-parser -D

根目录下创建 eslint.config.js文件

// eslint.config.js
import globals from 'globals'
import pluginJs from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'


/** @type {import('eslint').Linter.Config[]} */
export default [
  {
    ignores: ['node_modules', 'dist', 'public'],
    files: ['**/*.{js,mjs,cjs,vue}'],
  },
  {
    languageOptions: {
      globals: { ...globals.browser, ...globals.node },
    },
  },
  pluginJs.configs.recommended,
  ...pluginVue.configs['flat/recommended'],
  {
    rules: {
      // 禁止声明未使用的变量。
      'no-unused-vars': [
        'error',
        {
          vars: 'all', // 检查所有变量
          args: 'none', // 不检查函数参数
        },
      ],
      'prefer-const': 'error', // 如果变量不会被重新赋值,则使用 const。
      eqeqeq: 'error', // 要求使用全等运算符(=== 和 !==)。
      // 在这里追加 vue 规则
      'vue/multi-word-component-names': 'off',
    },
  },

  /**
   * prettier 配置
   * 会合并根目录下的prettier.config.js 文件
   * @see https://prettier.io/docs/en/options
   */
  eslintPluginPrettierRecommended,
]

根目录下创建 prettier.config.js文件

// prettier.config.js
/**
 * @type {import('prettier').Config}
 * @see https://www.prettier.cn/docs/options.html
 */
export default {
  semi: false,
  singleQuote: true,
  endOfLine: 'auto',
  printWidth: 100,
}

auto import

自动导入 import 语句,如import { ref } from 'vue',减少样板代码和提高开发效率

pnpm add unplugin-auto-import -D

配置 vite.config.js

// vite.config.js
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [
    // 自动引入三方库
    AutoImport({
      include: [
        /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
        /\.vue$/,
        /\.vue\?vue/, // .vue
      ],
      imports: ['vue', 'vue-router', 'pinia'],
      eslintrc: {
        enabled: false, // 若没此json文件,先开启,生成后在关闭
        filepath: './.eslintrc-auto-import.json', // 设置eslintrc-auto-import.json生成路径 Default `./.eslintrc-auto-import.json`
        globalsPropValue: true, // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
      },
      resolvers: [],
      dts: 'typings/auto-imports.d.ts', // 设置auto-import.d.ts生成路径 Default ./auto-imports.d.ts
    }),
  ],
})

eslintrc.enabled 设置成 true ,启动项目后会在根目录生成 .eslintrc-auto-import.json文件,生成后可以改成false

eslint9以下

配置 .eslintrc.cjs

modules.exports = {
  // ...其他配置
  globals: {
    defineProps: 'readonly',
    defineEmits: 'readonly',
    defineExpose: 'readonly',
    withDefaults: 'readonly',
  },
  extends: [
    // ...其他配置
    './.eslintrc-auto-import.json',
  ],
}

eslint9 配置 eslint.config.js

import { readFile } from 'node:fs/promises'

const autoImportFile = new URL('./.eslintrc-auto-import.json', import.meta.url)
const autoImportGlobals = JSON.parse(await readFile(autoImportFile, 'utf8'))

export default [
 // ...其他配置
 {
    languageOptions: {
      globals: {
        ...autoImportGlobals.globals,
      },
    },
  },
]

配置jsconfig.json

{
  "include": [
    // ...其他配置
    "./typings/auto-imports.d.ts"
  ]
}

路径别名 alias

配置 vite.config.js文件

// vite.config.js
export default defineConfig({
 resolve: {
    alias: {
      '@': '/src',
    },
  },
})

配置 jsconfig.json文件

// jsconfig.json
{
  "compilerOptions":{
    // ...其他配置
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

打包移除 console 和 debugger

// vite.config.js
export default defineConfig({
  esbuild: {
    drop: ['console', 'debugger'],
  },
})

sass

pnpm add sass sass-loader -D

添加 全局样式

/src/styles 下创建 index.scss 文件,根据自己习惯修改,以下提供一个模板

// index.scss

html {
  box-sizing: border-box;
}

body {
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-family: PingFangSC-Regular, PingFang SC, Helvetica Neue, Helvetica, Hiragino Sans GB, Microsoft
      YaHei, Arial, sans-serif;
}

html,
body {
  height: 100%;
}

label {
  font-weight: 700;
}

#app {
  min-height: 100%;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

* {
  margin: 0;
  padding: 0;
}

a:focus,
a:active {
  outline: none;
}

a,
a:focus,
a:hover {
  cursor: pointer;
  color: inherit;
  text-decoration: none;
}

div:focus {
  outline: none;
}

.clearfix {
  &:after {
    visibility: hidden;
    display: block;
    font-size: 0;
    content: ' ';
    clear: both;
    height: 0;
  }
}

ul li {
  list-style-type: none;
}

// main-container global css
.app-container {
  padding: 16px;
}

main.js 引入

import { createApp } from 'vue'
import App from './App.vue'

import './styles/index.scss'

const app = createApp(App)

app.mount('#app')

stylelint

pnpm add stylelint stylelint-config-html stylelint-config-recess-order stylelint-config-recommended-vue stylelint-config-standard stylelint-config-standard-scss stylelint-prettier postcss-html postcss-scss -D

根目录下创建 .stylelintrc.js文件

export default {
  extends: [
    // standard 规则集合
    'stylelint-config-standard',
    // standard 规则集合的 scss 版本
    'stylelint-config-standard-scss',
    // standard 规则集合的 vue 版本
    'stylelint-config-recommended-vue/scss',
    'stylelint-config-html/vue',
    // 样式书写顺序
    'stylelint-config-recess-order',
  ],
  // 指定不同文件对应的解析器
  overrides: [
    {
      files: ['**/*.{vue,html}'],
      customSyntax: 'postcss-html',
    },
    {
      files: ['**/*.{css,scss}'],
      customSyntax: 'postcss-scss',
    },
  ],
  rules: {
    'scss/no-global-function-names': null, 
  },
}

根目录下创建 .stylelintignore文件

dist
node_modules
public
.husky
.vscode
.idea
*.sh
*.md

css浏览器前缀补全

pnpm add autoprefixer -D

根目录下创建 postcss.config.js文件

export default {
  plugins: {
    autoprefixer: {
      overrideBrowserslist: ['last 2 versions'],
    },
  },
}

打包压缩目标兼容语言

// vite.config.js
export default defineConfig({
  build: {
    target: ['es2015'],
  },
})

打包拆包

// vite.config.js
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          // 将 vue 相关库打包成单独的 chunk 中
          'vue-vendor': ['vue', 'vue-router'],
          // 将组件库的代码打包
          library: ['vant'],
        },
      },
    },
  },
})

打包文件生成路径

// vite.config.js
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        // 业务代码和第三方包代码
        chunkFileNames: (chunkInfo) => {
          return 'assets/js/[name]-[hash].js'
        },
        // 静态资源
        assetFileNames: (assetInfo) => {
          const extType = assetInfo.name.split('.').pop()
          if (extType === 'css') {
            return 'assets/css/[name]-[hash].[ext]'
          } else if (
            extType === 'svg' ||
            extType === 'png' ||
            extType === 'jpg' ||
            extType === 'jpeg' ||
            extType === 'gif'
          ) {
            return 'assets/img/[name]-[hash].[ext]'
          }
          return 'assets/[name]-[hash].[ext]'
        },
        // 入口文件
        entryFileNames: 'assets/js/[name]-[hash].js',
      },
    },
  },
})

原子化css - unocss

pnpm add unocss -D

配置 vite.config.js

// vite.config.js
import UnoCSS from 'unocss/vite'

export default defineConfig({
  plugins: [
    // 原子化css
    UnoCSS(),
  ],
})

配置 main.js

// main.js
import 'virtual:uno.css'

根目录创建uno.config.ts

import {
  defineConfig,
  presetAttributify,
  presetUno,
  transformerVariantGroup,
} from 'unocss'

export default defineConfig({
  // 使用的预设
  presets: [
    // Attributify 预设:允许通过属性设置样式,如 <div bg="red-500"></div>
    presetAttributify(),
    // UnoCSS 预设:基本的原子化 CSS 类
    presetUno(),
  ],
  // 变换器
  transformers: [
    // Variant Group 变换器:允许将多个变体组合在一起使用,如 bg-red-500 hover:bg-red-700
    transformerVariantGroup(),
  ],
  // 自定义规则:可以在这里定义你的自定义 CSS 规则
  rules: [
    // 例如:['custom-rule', { 'property': 'value' }]
  ],
  // 快捷方式:定义一些常用的样式组合,简化使用
  shortcuts: [
    {
      'flex-center': 'flex items-center justify-center',
    },
  ],
})

代码提示:vscode 安装 UnoCSS 插件

image.png image.png

unplugin-vue-components

  • 按需自动引入组件:根据 Vue 文件中使用的组件,自动检测并引入所需的组件,而不需要手动编写 import 语句。

  • 支持本地和第三方组件库:不仅支持本地定义的组件,也支持流行的 Vue UI 组件库(如 Element Plus、Vant 等)的自动按需引入。

pnpm add unplugin-vue-components -D

配置 vite.config.js

// vite.config.js
import Components from "unplugin-vue-components/vite";
import { VantResolver } from "unplugin-vue-components/resolvers";
// **Element Plus**:`ElementPlusResolver`
// **Vant**:`VantResolver`
// **Ant Design Vue**:`AntDesignVueResolver`
// **Naive UI**:`NaiveUiResolver`

export default defineConfig({
  plugins: [
    Components({
      resolvers: [VantResolver()]
    }),
  ],
})

unplugin-icons

  • 按需加载图标:你可以根据项目中的需求,直接按需加载各种图标库的图标,而无需手动导入每个图标。

  • 支持多种图标库:集成了 Iconify,提供了 100 多个图标库(如 Material Design Icons、FontAwesome、Heroicons、Feather Icons 等)。

  • 自动组件化:图标可以被自动转换为组件(如 Vue、React 组件),无需手动处理 SVG 文件。

  • 自定义图标库:除了官方提供的图标库外,还可以轻松地将本地或自定义的 SVG 图标库整合进来。

  • 优化打包体积:通过按需加载,确保只引入用到的图标,避免引入整个图标库,优化打包体积。

pnpm add unplugin-icons -D

配置 vite.config.js

// vite.config.js
import Icons from "unplugin-icons/vite";

export default defineConfig({
  plugins: [
     Icons({
      autoInstall: true, // 如果使用的图标库未安装,它会自动安装
      customCollections: { // 添加自定义 SVG 图标库,文件名为图标名称 
        myicons: path.resolve(__dirname, 'src/icons'),
      },
    })
  ],
})

图标库使用方式

<template>
  <div>
    <icon-mdi-home /> <!-- 使用 Material Design Icons 中的 home 图标 -->
    <icon-fa-solid-user /> <!-- 使用 FontAwesome 的 solid 风格 user 图标 -->
  </div>
</template>

自定义图标库使用方式

<template>
  <div>
    <icon-myicons-customicon /> <!-- 使用自定义图标库中的 customicon 图标 --> 
  </div>
</template>

构建后的文件压缩 vite-plugin-compression

vite-plugin-compression 作用于构建后的文件,通过 gzipbrotli 等压缩算法生成额外的压缩文件,供服务器在传输阶段使用。这是传输层面的压缩,用来减少网络传输中的文件大小。

pnpm add vite-plugin-compression -D

配置 vite.config.js

// vite.config.js
import Icons from "unplugin-icons/vite";

export default defineConfig({
  plugins: [
    viteCompression({ 
      algorithm: 'gzip', // 选择 gzip 压缩算法 
      ext: '.gz', // 压缩后的文件后缀名 
      threshold: 10240, // 只对大于 10KB 的文件进行压缩 
      deleteOriginFile: false, // 是否删除未压缩的源文件 
    }),
  ],
})

setup语法糖组件名称 vite-plugin-vue-setup-extend-plus

注意:vue3.3之后,可以使用defineOptions来定义组件名,该插件可弃用

import { defineOptions } from 'vue' 
defineOptions({ 
    name: 'Foo',
    // 其他配置选项 
})
pnpm add vite-plugin-vue-setup-extend-plus -D

配置 vite.config.js

// vite.config.js
import vueSetupExtend from "vite-plugin-vue-setup-extend-plus";

export default defineConfig({
  plugins: [
    vueSetupExtend(),
  ],
})

使用方式

<script setup name="组件名称">
// ...
</script>

构建后的文件的打包

pnpm add vite-plugin-archive -D

配置 vite.config.js

// vite.config.js
import { readFileSync } from 'fs'
import { viteArchive } from 'vite-plugin-archive'

const { name, version } = JSON.parse(readFileSync('./package.json', 'utf-8'))

export default defineConfig({
  plugins: [
    viteArchive({
      outputFile: path.resolve('dist', `${name}_v${version}.zip`),
    }),
  ],
})