创建基础项目
pnpm create vite
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文件存放在里面
注意:要将 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
代码校验及格式化统一
注意 eslint8 和 eslint9 配置文件大更新,本文使用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
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 插件
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 作用于构建后的文件,通过 gzip 或 brotli 等压缩算法生成额外的压缩文件,供服务器在传输阶段使用。这是传输层面的压缩,用来减少网络传输中的文件大小。
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`),
}),
],
})