pnpm 优势
cross-device link not permitted
:::warning
如果包储存的位置与安装位置不在同一个盘,那么包已下载的包将会被复制,而不是被链接,如果你在C盘执行了 pnpm install
,则pnpm存储必须在C盘,如果pnpm存储在其他盘,所需要的包将会被复制到项目位置而不是链接形式,这样严重扼制了pnpm存储和性能优势。
:::npm install -g pnpm
config get registry
pnpm set registry https://registry.npm.taobao.org
# https://registry.npmjs.org/
pnpm config set store-dir E:/.pnpm-store# 修改默认仓库地址
pnpm store path # 获取包仓库地址(pnpm的仓库不能跨磁盘)
pnpm store prune # 从store中删除当前未被(硬连接)引用的包来释放store的空间
与 npm 的差异
npm命令 | pnpm等价命令 |
---|---|
npm install | pnpm install 安装全部依赖 |
npm install 包名 | pnpm add (-D) 包名 |
npm uninstall 包名 | pnpm remove 包名 |
npm run 脚本 | pnpm 脚本 |
使用vite 创建一个 vue3项目:
pnpm create vite vue3-template --template vue
cd vue3-template
pnpm install
pnpm run dev
参考 vite 官网
:::warning 依赖预构建,全代码抛弃 require :::
/*
依赖预构建 全代码抛弃require
1. vite将CommonJS或UMD发布的依赖项转换为 ESM 的语法规范 (esbuild实现), 放到node_modules/.vite/deps
2. 路径问题 , 强制 Vite 重新构建依赖,你可以用 --force 命令行选项启动开发服务器
3. 网络多包传输时, Vite 将有许多内部模块的ESM依赖关系转换为单个或几个模块, 只需要一个HTTP请求
4. @type import('vite').UserConfig 类型注释
*/
/*
环境变量/dotenv 定义常量define
1. mode 通过 --mode 指定
2. 在js中 使用 import.meta.env.VITE_xxx 使用环境变量
3. define: { NUM: JSON.stringify(1) }
*/
在项目根目录新建 config 文件夹,并新建 build.js 和 dev.js 文件 dev.js
/**
* @type import('vite').UserConfig
*/
export const devConfig = {
pl
};
build.js
/**
* @type import('vite').UserConfig
*/
export const buildConfig = {
};
上面我们在这两个文件头部都写了 @type import('vite').UserConfig , 这是vite提供的类型注释,方便代码提示: 新建 index.js 文件
import { devConfig } from './dev';
import { buildConfig } from './build';
export const envResolver = {
development: () => {
console.log('---development---');
return devConfig;
},
production: () => {
console.log('---production---');
return buildConfig;
}
};
参考链接 vite 情景配置
在 vite.config.js 使用刚刚配置的环境变量
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { envResolver } from './config/index.js';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) =>
Object.assign(envResolver[mode](), {
base: '/',
server: {},
build: {},
plugins: [vue()]
})
);
上面中的 mode 的值就是我们所处的环境,我们可以输出一下看看:
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { envResolver } from './config/index.js';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
console.log('mode', mode);
return Object.assign(envResolver[mode](), {
base: '/',
server: {},
build: {},
plugins: [vue()]
});
});
在刚刚创建的config文件夹新建 env 文件夹,并新建 .env.development 和 .env.production 文件
// .env.development 文件写入
VITE_PROJ_NAME = 'unTitled-dev'
// .env.production 文件写入
VITE_PROJ_NAME = 'unTitled-prod'
环境变量默认是在项目根目录的,为了让其生效,我们要在 vite.config.js 添加 envDir
配置
import { resolve } from 'path';
envDir: resolve(__dirname,'config/env'),
在 main.js 打印一下:
console.log('env_path', import.meta.env);
在 vite.config.js 配置路径别名
// 配置路径别名
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
在根目录创建jsconfig.json.用@符号代替src的位置
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"],
"components/*": ["src/components/*"],
"assets/*": ["src/assets/*"]
},
"allowSyntheticDefaultImports": true
},
// 注意,你配置的src的别名不能在下面的node_modules以及dist打包文件夹里面使用
"exclude": ["node_modules", "dist"]
}
:::warning 弃用** **::v-deep,使用 :deep() :::
:deep(.el-progress__text) {
}
/*
!default //降低scss变量优先级
!global // 表示就用此值
map.deep-merge https://www.sasscss.com/documentation/modules/map
*/
:::warning 有时候我们修改了vite源代码后,即使是重新运行项目,还是不会出现我们修改后的效果,因为vite默认存在缓存。 ::: 解决办法,在 package.json 添加运行命令: 执行:
# --force 刷新.vite缓存
pnpm run devNoCache
安装依赖: :::info 这里我们使用继承的方式来使用eslint的基本规范(用的比较舒服一点),然后遵循eslint-plugin-vue和 vite-plugin-eslint中的eslint规范。 :::
# 继承 校验import vue
pnpm add -D eslint eslint-config-airbnb-base eslint-plugin-import eslint-plugin-vue vite-plugin-eslint
初始化eslint:
先全局安装一下eslint npm i -g eslint
,然后执行:eslint --init
使用 vite-plugin-eslint 插件:
# vite-plugin-eslint可在控制台打印错误信息 注册插件
import eslint from 'vite-plugin-eslint';
eslint({ cache: false })
pnpm add -D autoprefixer postcss
在根目录新建 postcss.config.js
文件:
export default {
plugins: {
// 'postcss-import': {},
'postcss-pxtorem': {
rootValue: 37.5,
propList: ['*']
}
// 'tailwindcss/nesting': 'postcss-nesting'
// 'tailwindcss': {},
'autoprefixer': {}
}
}
测试一下效果, 在index.scss中写入下面css样式 :
::placeholder {
color: red;
}
main.js打印一下
import style from '@/styles/index.scss';
console.log('style', style);
pnpm add -D @tailwindcss/line-clamp postcss-nesting tailwindcss postcss-import
// 1. 安装插接件
pnpm add -D vite-plugin-svg-icons
// 2. 在vite.config.js 使用
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
createSvgIconsPlugin({
iconDirs: [resolve(process.cwd(), 'src/icons/svg')],
symbolId: 'icon-[dir]-[name]',
svgoOptions: false
})
// 3. 在main.js 注册全局组件
import 'virtual:svg-icons-register';
import svgIcon from '@/icons/svg-icon.vue';
app.component('svg-icon', svgIcon);
安装依赖
vite-plugin-vue-setup-extend
在 setup 中给组件定义别名 (setup语法加 name)unplugin-auto-import
自动导入插件unplugin-vue-components
导入vue组件插件安装使用:
// 1. 安装插件
pnpm add -D unplugin-auto-import unplugin-vue-components vite-plugin-vue-setup-extend
// 安装 element-plus 组件库
pnpm add element-plus
// 安装 vueuse 函数库
pnpm add @vueuse/core
# https://www.npmjs.com/package/unplugin-auto-import
// 2. 使用
import Components from 'unplugin-vue-components/vite'
Components({
// 指定自动导入的组件位置,默认是 src/components
dirs: ['src/components'],
resolvers: [
// 自动导入 Element Plus 组件
ElementPlusResolver()
],
// 配置文件生成位置,默认是根目录 /components.d.ts
dts: 'config/type/components.d.ts',
deep: true
}),
import AutoImport from 'unplugin-auto-import/vite';
AutoImport({
// 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
imports: ['vue', '@vueuse/core'],
resolvers: [
// 自动导入 Element Plus 相关函数,如:ElMessage, ElMessageBox...
ElementPlusResolver()
],
// 配置文件生成位置,默认是根目录 /auto-imports.d.ts
dts: 'config/type/auto-imports.d.ts'
}),
但会出现一个问题,不导入 vue,eslint报错,找不到相关 api,这时候我们需要配置eslint生成一个文件:
AutoImport({
// 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
imports: ['vue', '@vueuse/core'],
eslintrc: {
// 默认false, true启用。false生成一次就可以,避免每次工程启动都生成
enabled: true,
// 不导入ref, reactive vueUse时,vscode会报错, 让eslint生成 json文件
filepath: './.eslintrc-auto-import.json', // 生成json文件
globalsPropValue: true
},
resolvers: [ ElementPlusResolver() ],
// 配置文件生成位置,默认是根目录 /auto-imports.d.ts
dts: 'config/type/auto-imports.d.ts'
}),
在 .eslintrc.cjs 文件里配置继承 .eslintrc-auto-import.json 文件:
// .eslintrc.js
extends: [
'plugin:vue/vue3-essential',
'airbnb-base',
// 继承 .eslintrc-auto-import.json 规避找不到 ref vueuse函数
'.eslintrc-auto-import.json'
],
app.config.globalProperties.$version = app.version;
app.config.globalProperties.$stati = (url) => new URL(`../assets/${url}`, import.meta.url).href
验证效果:
<script setup name="test">
const { x, y } = useMouse();
const open = () => {
// eslint-disable-next-line
ElMessage({
message: 'info',
type: 'success'
});
};
const name = ref('Hello 2023!')
const user = reactive({
name: 'liaoyi',
age: 22
})
const change = () => {
user.name = '格罗姆'
}
onMounted(() => {
setTimeout(() => {
name.value = 'onMounted Hello 2023!'
}, 3000)
})
</script>
<template>
<svg-icon name="404" className="file-box" size="4" />
<hr>
<el-button @click="open" > 点击弹出提示框 </el-button>
<el-button type="primary" @click="change">改变姓名</el-button>
<hr>
<div>姓名:{{ user.name }}</div>
<div>年龄:{{ user.age }}</div>
<div> {{ name }}</div>
<hr>
<span>useMouse 获取鼠标: {{ x }} -- {{ y }}</span>
<hr>
<!-- 引用静态资源 -->
<img :src="$static('vue.svg')" alt="" />
</template>
<style scoped lang="scss">
.file-box {
color: blueviolet;
display: flex;
justify-content: center;
align-items: center;
}
</style>
pnpm add -D rollup-plugin-visualizer
注册插件:
import { visualizer } from 'rollup-plugin-visualizer';
visualizer({
open: mode === 'production',
gzipSize: true,
brotliSize: true,
filename: resolve(process.cwd(), 'dist/report.html'),
}),
运行 pnpm run build
安装插件:
// 安装插件
pnpm add -D vite-plugin-remove-console
// 注册插件
// 配置{external: ["src/assets/iconfont/iconfont.js"] } 对某文件 console 不剔除
removeConsole({
external: ['src/main.js']
}),
只有打包体积过大的时候,我们才需要做分包打包优化,如果包体积小的话,分包打包反而会影响性能。
我们试着在src/lib文件夹下新建 myUtils1.js 、myUtils2.js、myUtils3.js 文件夹
// myUtils1.js
export const clog1 = () =>{
onsole.log('output=> test1')
console.log('output=> test1')
}
// myUtils2.js
export const clog2 = () =>{
onsole.log('output=> test2')
console.log('output=> test2')
}
// myUtils3.js
export const clog3 = () =>{
onsole.log('output=> test3')
console.log('output=> test3')
}
此时我们可以在之前配置自动导入插件里添加目录导入这几个月文件:
AutoImport({
// ...
dirs: ['src/utils'], // 配置自动导入的目录(比如导入一些自己写的插件或者工具)
eslintrc: {
// 默认false, true启用。false生成一次就可以,避免每次工程启动都生成
enabled: true,
// 不导入ref, reactive vueUse时,vscode会报错, 让eslint生成 json文件
filepath: './.eslintrc-auto-import.json', // 生成json文件
globalsPropValue: true
},
// ...
}),
在vue文件中 :我们就可以直接使用这些方法:
<script setup >
clog1()
clog2()
clog3()
</script>
我们尝试一下把 element-plus 和 刚刚自动导入的myUtils* 文件分包打包 (打包生成单独的js文件:
// 分开打包
const splitDependencies = ['element-plus','myUtils'];
// 打包优化
build: {
// 设置最终构建的浏览器兼容目标
target: 'es2015',
// 构建后是否生成 source map 文件
sourcemap: false,
// chunk 大小警告的限制(以 kb为单位)
chunkSizeWarningLimit: 2048,
// 启用/禁用 gzip 压缩大小报告
reportCompressedSize: false,
rollupOptions: {
// 输出文件命名
output: {
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
manualChunks(id) {
// 这个id就是打包的文件路径
console.log('id >>>> ', id);
// 创建一个vendor包含所有依赖项的块node_modules
for (const dependency of splitDependencies) {
if (id.includes(dependency)) {
console.log('output=> id', id);
return dependency;
}
}
}
}
}
},
# 给setup语法加 name
pnpm add -D vite-plugin-vue-setup-extend
# 清除console
pnpm add -D vite-plugin-remove-console
# 打包显示进度条 https://blog.csdn.net/gongjin2012/article/details/125333102
pnpm add -D vite-plugin-progress
# 打包报告
pnpm add -D rollup-plugin-visualizer
# gzip压缩
pnpm add -D vite-plugin-compression
#兼容IE
pnpm add -D @vitejs/plugin-legacy
// import legacy from '@vitejs/plugin-legacy';
// legacy({
// targets: ['ie >= 11'],
// additionalLegacyPolyfills: ['regenerator-runtime/runtime']
// })
# hooks api
pnpm add @vueuse/core
# VueI18n
pnpm add vue-i18n #必须安装 前置依赖
pnpm add -D @intlify/vite-plugin-vue-i18n
// 默认仅支持 组合式api
VueI18n({ include: [resolve(__dirname, '../locales/**')],})
// use
import { createI18n } from 'vue-i18n';
import messages from '@intlify/vite-plugin-vue-i18n/messages';
const i18n = createI18n({
locale: 'en',
fallbackLocale: 'en',
messages,
});
// 使用 locale可改变其值与文件名相等
const { locale, t } = useI18n();
# mock 数据
pnpm add -D vite-plugin-mock
#swiper https://www.swiper.com.cn
pnpm add swiper # :watchOverflow="false"单页面生效
# 全屏混动
pnpm add vue-fullpage.js
# 美化基本html
pnpm add animate.css hover.css normalize.css
cnpm install --save axios@0.18.1 #请求发送
cnpm install --save vue-router@3.0.6 #路由
cnpm install --save-dev plop@2.3.0 #代码生成
cnpm install --save nprogress@0.2.0 #进度条
cnpm install --save path-to-regexp@2.4.0 # 匹配路由路径表达式工
cnpm install --save video.js
cnpm install --save js-cookie
cnpm install file-saver --save #文件保存
cnpm install --save jszip #压缩
cnpm install --save xlsx #excel
在vscode下载prettier插件 :
在根目录新增 .prettierrc
文件:
{
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"tabWidth": 2
}
设置默认格式化工具:
打来项目中任意vue文件或者js文件右键,点击 使用...格式化工具
在弹出的选择列表选择 配置默认格式化工具
,选择prettier
为了防止冲突,我们在.eslintrc.cjs 添加规则:
// “关闭”或0-关闭规则
// “警告”或1-将规则作为警告(不会影响退出代码)
// “错误”或2-将规则作为错误打开(退出代码为1 触发)
module.exports = {
//...
rules: {
//...
// 解决eslint与prettier冲突
indent: 0, // 强制使用一致的缩进
'space-before-function-paren': 0 // 方法名和括号之间需要有一格空格
}
}
1.全局安装commitizen和在项目中安装cz-customizable
npm install -g commitizen
pnpm add cz-customizable -D
2.在根目录下新建 .cz-config.cjs 文件并写入配置 之后就可以用 git cz 来代替 git commit
module.exports = {
// 可选类型
types: [
{ value: 'feat', name: 'feat: 新功能' },
{ value: 'fix', name: 'fix: 修复' },
{ value: 'docs', name: 'docs: 文档变更' },
{ value: 'style', name: 'style: 代码格式(不影响代码运行的变动)' },
{
value: 'refactor',
name: 'refactor: 重构(既不是增加feature,也不是修复bug)'
},
{ value: 'perf', name: 'perf: 性能优化' },
{ value: 'test', name: 'test: 增加测试' },
{ value: 'chore', name: 'chore: 构建过程或辅助工具的变动' },
{ value: 'revert', name: 'revert: 回退' },
{ value: 'build', name: 'build: 打包' }
],
// 消息步骤
messages: {
type: '请选择提交类型:',
customScope: '请输入修改范围(可选):',
subject: '请简要描述提交(必填):',
body: '请输入详细描述(可选):',
footer: '请输入要关闭的issue(可选):',
confirmCommit: '确认使用以上信息提交?(y/n/e/h)'
},
// 跳过问题
skipQuestions: ['body', 'footer'],
// subject文字长度默认是72
subjectLimit: 72
}
3.在package.json中进行新增
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
},
// 指定 .cz-config.cjs 文件路径
"cz-customizable": {
"config": ".cz-config.cjs"
}
}
运行一下git cz 试试:
# 安装 commitlint 校验插件
npm install --save-dev @commitlint/config-conventional@12.1.4 @commitlint/cli@12.1.4
pnpm add -D @commitlint/config-conventional @commitlint/cli
# 安装 husky 强制性使用规范
npm install husky@7.0.1 --save-dev
npm install husky -D
# 初始化 husky
npx husky install
此时我们可以看见根目录多了一个.husky文件:
导入commitlint配置文件:
在根目录新增 commitlint.config.cjs
文件并写入:
module.exports = {
// 继承的规则
extends: ['@commitlint/config-conventional'],
// 定义规则类型
rules: {
// type 类型定义,表示 git 提交的 type 必须在以下类型范围内
'type-enum': [
2,
'always',
[
'feat', // 新功能 feature
'fix', // 修复 bug
'docs', // 文档注释
'style', // 代码格式(不影响代码运行的变动)
'refactor', // 重构(既不增加新功能,也不是修复bug)
'perf', // 性能优化
'test', // 增加测试
'chore', // 构建过程或辅助工具的变动
'revert', // 回退
'build' // 打包
]
],
// subject 大小写不做校验
'subject-case': [0]
}
}
5.在package.json中新增指令
"prepare": "husky install"
6.执行命令
pnpm run prepare
7.执行命令
# 生成 husky commit时的配置文件
npx husky add .husky/commit-msg
8.把husky和commitlint进行关联, 在刚刚新增husky配置文件里写入
npx --no-install commitlint --edit
测试一下,强制提交规范成功:
既然安装了husky,为了更好的开发体验,husky也支持在推送代码时强制代码格式化
1.我们先来执行命令创建配置文件
npx husky add .husky/pre-commit
2.同样的生成的文件中写入下面命令
npx lint-staged
8.把package.json文件的lint-staged修改为
"lint-staged": {
"src/**/*.{js,vue}": [ //src目录下所有的js和vue文件
"eslint --fix", // 自动修复
"git add" // 自动提交时修复
]
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。