vue-cli4.5&&webpack4升级vite4全面总结
🙂前言
vite是什么?
js 早期只能 script 的属性 src 链接,无法像现在工程化依赖打包插件实现 import 模块化,所以在奔向 js 原生完成工程化构建的伟大航路中,先后有 requirejs
, webpack
等构建工具的出现,es6 后 js 增加了 type="module"
, vite 就是基于此属性扩展开发,相对于前面的构建工具来讲, vite 确实带来更加的效率,同时在精简易上手的基础上,也能完美满足更多的扩展性,属实算是当前的构建工具一哥。
扩展阅读可阅读 vite 官网,或者阅读 es6 的 type="module"
官方文档
为什么使用vite?
- 快!快!快!各种快就完事~
- 相对webpack和其他构建工具来讲,小波个人的体验各种配置和扩展插件更易上手,更好配置(当然需要再学习一个插件库
rollupjs
) - 方便后续升级 ts 和项目的更深入优化
😦vite升级思路
- 直接 vite 脚手架建个初始项目,再把原项目 src 文件夹等相关文件拷贝进去
- 基于现有项目直接升级(本文的升级步骤基于此思路)
🧐工作项目环境
- vue-cli 4.5
- webpack 4.4
- vue 3.2
- ant design vue 2.x
🤔步骤思路总结
- 删除 vue-cli, babel, webpack 相关依赖库和文件
- 升级vue3, @vue/compiler-sfc, eslintrc, prettier
- 安装 vite, 移动 index.html, 配置 vite.config.js
- 针对项目代码逐一修复出现的bug
- 打包优化(to do…)
😚vue-cli4.5 && webpack4 升级 vite4 步骤详解
package.json
删除 vue-cli, babel, webpack 相应配置1
2
3
4
5
6
7
8
9
10
11
12
13// 删除
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"webpack": "^4.46.0"
"serve": "node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js serve",
"build": "node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js build",
"babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.13.3",删除
babel.config.js
,vue.config.js
,jsconfig.json
1
2
3
4
5
6
7
8
9
10
11// jsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"baseUrl": "./",
"paths": {
"@/*": ["src/*"],
"~/*": ["src/assets/*"]
}
}
}删除
.eslintrc.js
的 babel 配置项,把 es6 改成 es20211
2
3
4
5
6
7
8parserOptions: {
// parser: 'babel-eslint'
},
env: {
node: true,
// es6: true
es2021: true
},升级 vue3 到最新版本( vite 需要最新版本), 升级 eslint, prettier( jsx 无法格式化需要升级这两个依赖)
1 |
|
提示
升级步骤是基于 pnpm 命令安装,提前全局安装一下
1npm install pnpm -g
- 创建
vite.config.js
并配置
1 |
|
移动
index.html
到根目录并修改相应配置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<!--remove-->
<title><%= htmlWebpackPlugin.options.title %></title>
<!--add-->
<title>site Title</title>
//...
<!--remove-->
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<!--add-->
<strong>We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<!--remove-->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!--add-->
<link rel="icon" href="/favicon.ico">
<script type="module" src="/src/main.js"></script>package.json
修改脚本命令1
2
3
4"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src"更新环境变量
1
2
3
4
5
6
7
8
9.env # loaded in all cases
.env.local # loaded in all cases, ignored by git
.env.[mode] # only loaded in specified mode
.env.[mode].local # only loaded in specified mode, ignored by git
// 文件名可以不变,但是,您不能再访问流程变量上的环境变量。 相反,它们可以在 import.meta.env 上找到。
// old
base: process.env.BASE_URL,
// new
base: import.meta.env.BASE_URL,用于使声明客户端暴露的环境变量更明显的
VUE_APP_
前缀已更改为VITE_
,因此如果您有任何此类环境变量,则必须相应地更新它们。vite.config.js
配置 sfc 导入添加 .vue 扩展名1
2
3
4
5...
resolve: {
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
//...
},清理
webpack
魔法注释1
/* webpackChunkName: "about" */
提示
vite 会自动根据文件夹进行按需分包加载,打包后的文件名格式
x+hash.js
, 所以业务文件夹的x.vue
尽量不要用index.vue
jsx 报错
1
2
3
4
5
6
7
8
9
10// 1. 安装
pnpm add @vitejs/plugin-vue-jsx -D
// 2. 配置 vite.config.js
import vueJsx from '@vitejs/plugin-vue-jsx'
...
resolve: {},
esbuild: { loader: { '.js': '.jsx' } }
// 3. .vue 文件要把 lang="jsx" 补上, .js 文件要改成 .jsxError: The following dependencies are imported but could not be resolved: qs
1
2// 缺少依赖库 安装 qs
pnpm add qsInternal server error: Unable to parse HTML; parse5 error code end-tag-without-matching-open-element
1
2
3
4
5
6// 因为ant的导入样式 ~ 问题,在配置我增加了 { find: /^~/, replacement: ''} 导致无法找到 .less 文件,
// 直接把 ~ 去掉
// old
@import '~ant-design-vue/dist/antd.less';
// new
@import 'ant-design-vue/dist/antd.less';Cannot read properties of undefined (reading ‘_android’)
1
2
3
4
5
6
7pnpm add qrcodejs2-fix
pnpm remove qrcodejs2
//原来导入的地方把 名字 改成 下面代码
import QRCode from 'qrcodejs2-fix'
// 如果出现一直报错原来的 qrcodejs2,删除node_modules包类似问题参考文章
图片或者导入依赖库原来采用了 webpack 的 require , 报错
require is not defined
1
2
3
4
5
6
7
8
9
10
11// vite 返回静态资源图片 name = x.png/x.jpg
const getImageUrl = name => {
return new URL(`../../assets/image/${name}`, import.meta.url).href
}
// 如果是 require 的依赖库 改成以下,注意要用 await
// old
let elementResizeDetectorMaker = require('element-resize-detector')
// new
let elementResizeDetectorMaker = await import('element-resize-detector')
let erd = elementResizeDetectorMaker.default()注意:
new URL(dep, import.meta.url)
dep
无法使用 别名 @ 来描述路径new URL(dep, import.meta.url)
如果抽离为公共方法,dep
中路径不能是完整一个变量传入,变量只能是路径结尾的图片类型
类似问题参考文章
ReferenceError: Cannot access ‘store’ before initialization vuex,This could be due to syntax errors or importing non-existent modules
1
2
3
4// 出现类似这样报错,绝大部分可能性就是代码中出现了循环导入
// eg: a import b, b import c, c import a
// 只能自己跟着报错找到可能出现循环导入的文件然后检查代码提示
小波推荐检查文件是否循环导入安装 vscode 插件 find unused exports
使用说明:
vscode左侧栏会有个相同图标,只要打开文件,切到面板就会自动分析文件的导入导出情况
CIRCULAR IMPORTS 即是循环导入提示区域
类似问题参考文章
Vite HMR error: Cannot access ‘…’ before initialization ?
vue3+vite热更新遇到的问题HMR error: Cannot access ‘…’ before initialization
You are running the esm-bundler build of vue-i18n. It is recommended to configure your bundler to explicitly replace feature flag globals with boolean literals to get proper tree-shaking in the final bundle
1
2
3// 多语言报错
// vite.config.js
alias: { ..., 'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js' },ant design vue 没导出的组件去掉,未使用的函数要删除
1
eg: moment invalid
provide 的定义函数放到调用执行前面
1
理解js上下文执行顺序
Added non-passive event listener to a scroll-blocking ‘wheel’ event. Consider marking event handler as ‘passive’ to make the page more responsive.
1
// 缺少对应的库,提示什么就安装什么
module.exports 报错
1
2module.exports = {}
要改成 esmodule 模式 => export {}感兴趣的童鞋可以深入阅读 commonjs 规范(module.exports),es6 规范(export [default]),amd 规范(require),这三者的区别
多语言报错 Not available in legacy mode
1
2
3
4
5
6
7const i18n = createI18n({
// ...
// 设为true或者不设置
legacy: true,
allowComposition: true,
// ...
})日期插件出现部分中文,部分英文
1
2
3import 'moment/dist/locale/zh-cn'
// 不仅需要调用,上面也必须导入
moment.locale(locale)[unplugin-vue-components] component “xx“ has naming conflicts with other components, ignored.
1
2
3
4
5
6
7
8
9
10// 配置 vite.config.js
import Components from 'unplugin-vue-components/vite'
...
plugins: [
Components({
resolvers: [IconsResolver()],
// 此属性解决报错
directoryAsNamespace: true
}),
]class关于Cannot access XXX before initialization的报错
还是循环导入的锅,开发时热更新报上面的错误提示,小波最后只能强制采用刷新机制来处理,可以自己+个判断只对有问题的页面强制刷新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 配置 vite.config.js
plugins: [
...
// 强制刷新
{
name: 'singleHMR',
handleHotUpdate({ modules }) {
modules.map((m) => {
m.importedModules = new Set()
m.importers = new Set()
})
return modules
}
}
]
以上步骤是小波升级公司项目遇到的相关问题,希望为同样要把前端项目升级成 vite 构建的童鞋提供点点参考。
以下是一份小波升级后完整的 vite.config.js
配置,包含了分包等优化
1 |
|
😫一些奇奇怪怪的问题
1 |
|
安装依赖库报错 ERESOLVE could not resolve,强制安装
1
pnpm add [...] --legacy-peer-deps
😊来自小波的bilibili视频教程
🙂相关参考资料链接
『旅行者』,帮小波关注一波公众号吧。
小波需要100位关注者才能申请红包封面设计资格,万分感谢!
关注后可微信小波,前66的童鞋可以申请专属红包封面设计。
微信
支付宝