背景
项目代码越来越多,使用Vue-cli每次启动项目或者热更新的时间都比较长,尤大开发的Vite早有耳闻并也有一点了解,所以准备将Vue-cli转到Vite,使用的工具是webpack-to-vite。
1、屏蔽Vue.conf.js里面的配置
注释掉chainWebpack,configureWebpack等配置,否则转换会报错。
2、require的写法转换
由于vite是不支持CommonJs的写法的(比如这边的require),原先可以这样写是Vue-cli帮我们做了转换。转为vite之后,虽然不做改动的话,开发环境不会报错,但是打包环境(npm run build之后npm run preview)会报错:require is not defined,这是因为开发环境使用了@originjs/vite-plugin-commonjs插件,但是这个插件未对打包结果做处理。
原先的写法:
function getSvgIcon(path, name) {
return require(`../../public/icons/${path}/${name}.svg`)
}
改为:
function getSvgIcon(path, name) {
return new URL(`/icons/${path}/${name}.svg`, import.meta.url).href
}
但是,这样改动,Vue-cli启动会报错。
3、代理
vite提供的功能更类似webpack,vue-cli是包装webpack提供了检测是否本地文件的功能。
vite提供了类似bypass函数。
这边套用官网的server配置:
// vite.config.js
server: {
proxy: {
'/apidev': {
target: 'http://10.136.96.79:19997',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/apidev/, '')
}
}
}
// http.js
const isProduction = process.env.NODE_ENV !== 'development'
axios.defaults.baseURL = isProduction ? settings.backendUrl : `/apidev/${settings.backendUrl}`
上面的proxy中之所以用/apidev之后又删掉,是因为尝试了直接使用'/','/*'等写法均不生效(猜测可能是’/‘区分不了是静态文件还是请求),这种写法是参考的官网。
4、国际化
原先国际化load语言的时候有require相关的写法:
// i18n.js
function loadLocaleMessages() {
const locales = require.context('../locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
const messages = {}
locales.keys().forEach(key => {
const matched = key.match(/([A-Za-z0-9-_]+)\./i)
if (matched && matched.length > 1) {
const locale = matched[1]
messages[locale] = locales(key)
}
})
return messages
}
// App.vue
loadLocaleMessages: function() {
const locales = require.context('../../locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
const messages = {}
locales.keys().forEach(key => {
const matched = key.match(/([A-Za-z0-9-_]+)\./i)
if (matched && matched.length > 1) {
const locale = matched[1]
messages[locale] = locales(key)
}
})
return messages
}
}
改为:
// i18n.js
import zh from '@/locales/zh.json'
import en from '@/locales/en.json'
function loadLocaleMessages() {
return {
en,
zh
}
}
// App.vue
import zh from '@/locales/zh.json'
import en from '@/locales/en.json'
loadLocaleMessages: function() {
return {
en,
zh
}
}
【建议】import.meta.glob / new URL 回头试试
5、开发环境CSS乱了
原先的index.html中:
<body class="xx">
XXXX
</body>
在body中有class="xx",但是现在vite生成的index.html默认没有带上这个class导致我们自己写的很多样式没有生效。只需要在vite生成的index.html手动加上class="xx"即可。
注意:vite.config.js配置build的多入口
6、打包
可以正常打包,但是有warning信息:
rendering chunks (80)...warnings when minifying css:
> <stdin>:20:24: warning: Unexpected ">"
20 │ .main-content .dialog > > > .node-fill .v-text-field[data-v-23fae236] {
╵ ^
> <stdin>:25:18: warning: Unexpected ">"
25 │ .dialog .upload > > > .v-file-input .v-text-field__details[data-v-e0...
╵ ^
> <stdin>:31:18: warning: Unexpected ">"
31 │ .dialog .upload > > > .v-text-field > .v-input__control > .v-input__...
╵ ^
> <stdin>:34:18: warning: Unexpected ">"
34 │ .dialog .upload > > > .update-file[data-v-e0246af8] {
学习下vue中style scope深度访问新方式(::v-deep)。
这个需要改一下深度作用选择器的写法:
>>> 改为 ::v-deep
7、build的时候warning: "@charset" must be the first rule in the file
参见issue,忽视这个warning
8、首屏加载优化
开发环境虽然npm run serve很快,但是页面首屏加载时间很长【请求400+】。看了下是Vuetify和staticInfo相关请求过多。
建议:优化
优化1. 参见官网,修改一下vuetify的引入方式
// 修改前
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
export default new Vuetify({
icons: {
iconfont: 'md'
}
})
// 修改后,并且删除步骤10引入的vite-plugin-components以及vite.config.js中相关的配置
import Vue from 'vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
Vue.use(Vuetify)
export default new Vuetify({
icons: {
iconfont: 'md'
}
})
页面首次加载的请求减少100+,页面加载时间(首次)优化到5.84s,缩短了10s+
优化2. 开启http2试试,因为http 1.x 同时只能6-8个请求, http2没这个限制。否则存在优先级高的请求、并发TCP连接数超过6个(本实例是这个原因)、缓存读写异常这三个原因会导致请求stalled时间长。
效果比对
代码量:src目录约9w行
| Vue-Cli | Vite | |
|---|---|---|
| 启动时间 | 39s | 805ms |
| 页面加载时间(首次) | 1.68s | 17.24s(5.8s) |
| 组件热更新时间 | 130ms【+编译时间】 | 82ms |
webpack 热更新时间:构建时间 + 请求时间,vite 则只有请求时间