共计 10682 个字符,预计需要花费 27 分钟才能阅读完成。
目录
- 前言
- 迁徙前后比照
- 迁徙流程
- 迁徙业务代码到 vite 我的项目
- 我的项目开发阶段报错解决
- 我的项目打包阶段解决
- 总结
一. 前言
公司有个特地大保护工夫长的后盾管理系统,应用的是 vue2 和webpack3,尽管配置了很多编译优化,但启动和开发热更新速度仍然很慢,极大的影响了开发效率,于是筹备迁徙 vite2 来优化,当初已迁徙降级,来复盘记录下过程,至于 vite 速度快于 webpack 的起因,曾经有很多文章讲的很明确,这里只记录下迁徙过程和遇到的问题。
二. 迁徙前后比照
比照 | 迁徙前 webpack3 | 迁徙后 vite2 |
---|---|---|
启动开发模式 | 40 秒 | 3 秒之内 |
热更新 | 6 秒 + | 1 秒之内 |
打包构建(vite 不做低版本浏览器兼容) | 2 分 30 秒 | 40 秒 |
打包构建(vite 做低版本浏览器兼容) | 2 分 30 秒 | 1 分 05 秒 |
三. 迁徙流程
- 先创立新的 vite 我的项目
- 新版 vite 我的项目默认是反对 vue3 的,须要把 vue 改成 vue2 版本后配置 vite-plugin-vue2 插件来反对vue2
- 把我的项目代码改成 vue2 写法,确保新 vite 我的项目能够失常运行vue2
- 把原 webpack 我的项目生产环境依赖复制到 vite 我的项目,剔除掉 webpack 相干的插件依赖
- 复制原我的项目 src 文件代码和其余业务相干代码到新 vite 我的项目。
- 新 vite 我的项目配置开发环境启动命令,依据报错信息来进行调整。
- 在测试开发和打包环境都没问题后,替换原先的我的项目。
四. 迁徙业务代码到 vite 我的项目
4.1 创立新的 vite 我的项目
关上 vite 官网, 依照官网提醒创立新的 vite 我的项目 (因为原先我的项目没有用ts,所以创立我的项目不选ts 版本,包管理工具也仍然抉择是npm)。
npm init vite@latest my-vue-app -- --template vue
创立实现后,应用 vs code 关上,关上命令行,执行 npm i 装置依赖
npm i
装置依赖实现后,应用 npm run dev 启动我的项目
npm run dev
启动实现后,关上我的项目地址 http://localhost:3000/
此时根本的 vite2+vue3 我的项目曾经启动胜利了,但此时 vite 反对的还是 vue3 版本的,咱们须要让 vite 反对 vue2 版本。
4.2 配置 vite 反对 vue2
此时关上vite.config.js, 外面的代码为
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()]
})
@vitejs/plugin-vue插件是对 vue3 语法做反对,如果要反对vue2,须要用vite-plugin-vue2
第一步 ,从vite 中删除 @vitejs/plugin-vue配置,从 package.json 文件中也删除。
npm uninstall @vitejs/plugin-vue -D
第二步 , 装置vite-plugin-vue2 依赖
npm install vite-plugin-vue2 -D
第三步 , 在vite.config.js 文件配置vite-plugin-vue2
import {defineConfig} from 'vite'
import {createVuePlugin} from "vite-plugin-vue2";
// https://vitejs.dev/config/
export default defineConfig({plugins: [createVuePlugin()]
})
第四步 ,批改vue 版本由 3 改为 2 版本
npm install vue@2 -S
第五步 , 批改main.js,创立根vue 实例写法改为 vue2 写法
import Vue from 'vue'
import App from './App.vue'
new Vue({render: h => h(App),
}).$mount('#app')
第六步 ,批改main.js 实现后,批改 App.vue 文件代码为 vue2 格局代码
<template>vue
<h1>{{title}}</h1>
</template>
<script>
export default {
name: 'App',
data() {
return {title: 'webpack3 迁徙 vite2'}
}
}
</script>
此时 package.json, vite.config.js, main.js, App.vue 代码别离为
执行 npm run dev,即可看到启动胜利, 代表此时vite 曾经反对 vue2 语法了,能够开始我的项目迁徙工作了。
4.3 复制原我的项目业务代码
第一步 ,复制原我的项目动态目录static 下文件到 vite 我的项目 public 文件夹下
第二步 ,复制原我的项目index.html 文件内容替换 vite 我的项目的 index.html 内容 (留神本地动态资源引入的门路) 替换后须要在 body 完结标签前增加
<script type=”module” src=”/src/main.js”></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title> 经营平台 </title>
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link href="https://unpkg.com/ionicons@4.2.2/dist/css/ionicons.min.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
<script type="module" src="/src/main.js"></script>
</body>
</html>
第三步 , 复制package.json 中生产环境依赖到新 vite 我的项目, 去除 webpack 相干配置依赖,此时最新的 vite 代码
{
"name": "my-vue-app",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^2.6.14",
"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
"dayjs": "^1.7.8",
"dingtalk-jsapi": "^2.7.3",
"element-ui": "^2.13.1",
"good-storage": "^1.0.1",
"js-base64": "^2.4.9",
"moment": "^2.23.0",
"nprogress": "^0.2.0",
"qs": "^6.5.2",
"sockjs-client": "^1.3.0",
"stompjs": "^2.3.3",
"swiper": "^4.3.5",
"v-viewer": "^1.2.1",
"vue-router": "^3.0.1",
"vue-virtual-scroller": "^1.0.10",
"vuex": "^3.0.1"
},
"devDependencies": {
"vite": "^2.9.2",
"vite-plugin-vue2": "^2.0.0"
}
}
第四步 ,复制原我的项目src 业务文件代码,间接替换 vite 我的项目 src 文件, 此时整体我的项目构造如下
4.4 配置 vite 的我的项目环境变量
因为原我的项目应用了 cross-env 来设置环境变量,为了能够失常启动我的项目,须要在 vite 外面也配置下环境变量
第一步, 装置cross-env
npm install cross-env -D
第二步 ,配置scripts 脚步命令, 应用 cross-env 来设置环境变量BASE_ENV(这一步要按本人我的项目状况来配置)
"scripts": {
"dev:dev": "cross-env BASE_ENV=development vite",
"dev:test": "cross-env BASE_ENV=test vite",
"dev:pre": "cross-env BASE_ENV=pre vite",
"dev:prod": "cross-env BASE_ENV=production vite",
"build:dev": "node node_modules/esbuild/install.js && cross-env BASE_ENV=development vite build",
"build:test": "node node_modules/esbuild/install.js && cross-env BASE_ENV=test vite build",
"build:pre": "node node_modules/esbuild/install.js && cross-env BASE_ENV=pre vite build",
"build:prod": "node node_modules/esbuild/install.js && cross-env BASE_ENV=production vite build",
"preview": "vite preview"
}
- 打包增加 node node_modules/esbuild/install.js,是用来解决 esbuild 装置 时报错的 bug 相干 issue
- 之所以环境变量没有应用 NODE_ENV, 是因为很多第三方包都应用NODE_ENV 来判断开发环境和打包环境,为了不影响,采纳新加一个环境变量的形式
第三步 , 配置vite.config.js,使vite 在我的项目外面注入环境变量
只是应用 cross-env 设置环境变量的话,我的项目外面是拜访不到的,须要配置一下 vite 的 define 配置,能力拜访到,相似于 webpack 的DefinePlugin插件性能
import {defineConfig} from 'vite'
import {createVuePlugin} from "vite-plugin-vue2";
// https://vitejs.dev/config/
export default defineConfig({plugins: [createVuePlugin()],
define: {
/** 我的项目环境变量 **/
'process.env.BASE_ENV': JSON.stringify(process.env.BASE_ENV)
},
})
此时后期筹备工作都曾经实现,能够开始启动我的项目了,必定会有很多报错,须要依据报错信息来进行调整
五. 我的项目开发阶段报错解决
先依据下面配置好的命令,启动开发模式
npm run dev:dev
5.1 第一个报错,The following dependencies are imported but could not be resolved:
由提示信息很容易能够看出,是因为原我的项目应用 webpack 配置了别名,但新 vite 我的项目未配置别名造成的,咱们须要在 vite 中增加别名配置
依据 vite 别名规定,vite.config.js增加配置,把 @/ 指向 src 目录
import {defineConfig} from 'vite'
import {createVuePlugin} from "vite-plugin-vue2";
// https://vitejs.dev/config/
export default defineConfig({plugins: [createVuePlugin()],
define: {
/** 我的项目环境变量 **/
'process.env.BASE_ENV': JSON.stringify(process.env.BASE_ENV)
},
resolve: {
/** 增加 alias 规定 **/
alias: [
{
find: '@/',
replacement: '/src/'
}
],
},
})
增加后再次重启我的项目,呈现第二个报错
5.2 第二个报错, Failed to resolve import “./App” from “src/main.js
报错是因为引入 App 组件的时候没有带文件后缀 .vue, 所以未找到,此时有两种解决方案
- 手动增加 .vue后缀,然而我的项目这么宏大,很多中央都没有带后缀,全副改必定不容易。
- 配置 vite.config.js 的extensions字段,来增加主动查找文件扩展名后缀。
采纳第二种 vite 配置 extensions 扩展名,在 vite.config.js 外面增加 resolve.extensions 配置
import {defineConfig} from 'vite'
import {createVuePlugin} from "vite-plugin-vue2";
// https://vitejs.dev/config/
export default defineConfig({plugins: [createVuePlugin()],
define: {
/** 我的项目环境变量 **/
'process.env.BASE_ENV': JSON.stringify(process.env.BASE_ENV)
},
resolve: {
/** 增加 alias 规定 **/
alias: [
{
find: '@/',
replacement: '/src/'
}
],
/** 临时先加.vue, .js, .json **/
extensions: [".vue", ".js", ".json"],
},
})
增加后再次重启我的项目, 呈现第三个报错
5.3 第三个报错, dependency “sass” not found. Did you install it
由报错信息可知,是因为我的项目外面应用了 sass,less, 然而没有对应的解析配置,须要增加一下vite 解析 sass,less 的配置
装置 vite 中解析 sass, less 插件
npm install less sass -D
在 vite 中只须要装置 sass,less 插件就能够了,vite 会主动应用该插件去解决 sass,less 文件
增加后再次重启我的项目, 呈现第四个报错
5.4 第四个报错, Can’t find stylesheet to import.
看报错信息是在配置 element-ui 自定义主题色的时候,在 element-variables.scss 文件中应用 @import了 element-ui 的主题文件,应用~ 前缀, 而 vite 解析不了,所以没有找到对应的文件。
须要把前缀~ 去掉,间接去援用 node_modules 下的主题款式文件即可,然而因为 element-ui 应用 calc 语法,在 sass2.0.0 版本会删除对该办法的反对,所以控制台会报正告:
Deprecation Warning: Using / for division outside of calc() is deprecated and will be removed in Dart Sass 2.0.0.
不影响失常我的项目运行,如果要解决的话,升高 sass 的版本就能够了,目前 sass 版本是1.51.1, 手动降版本
npm install sass@1.30.0 -D
增加后再次重启我的项目, 控制台就不会呈现正告了。
5.5 第五个报错, require is not defined
这次启动我的项目后,命令行没有报错了,而后关上浏览器,发现页面白屏,关上控制台看到控制台报错
token.js:18 Uncaught ReferenceError: require is not defined
at token.js
关上对应的 token.js 应用 reuire 引入了一张图片,而 vite 不反对require,咱们须要换一种引入形式来引入图片。
有三种计划:
1. 第一种是采纳 import/from 来引入,这种形式适宜图片和所有模块,也是最符合规范,利用 tree-shrink 的。2. 第二种是间接把图片提前压缩解决后放在 public 文件下,就能够通过根门路 /xxx.png 来拜访到了。3. 第三种应用 vite 提供的 import.meta.glob()办法,但该办法返回的是异步的,适宜配置懒加载动静路由。
这里我采纳的是第二种形式,把 boy.png 放在 public 目录下,require引入改成固定字符串 ‘/boy.png’ , 这样打包时就不必对图片做解决了,能够进步打包速度。
全局搜寻一下 require, 把应用require 引入图片的中央都改成绝对路径或者 import/from 引入。
批改后再次重启我的项目, 这次批改后命令后仍然没有报错,关上浏览器后页面呈现了第六个报错
5.6 第六个报错, Failed to resolve import‘../xxx.png’.
依据提示信息找到对应的文件,能清晰的看到报错起因,是因为页面外面应用 img 标签,src 应用的相对路径
<img src="../../../static/userContent.png"">
static目录曾经被 public 目录替换掉了,所以对于图片咱们还是间接压缩解决后放的 public 文件夹,我的项目内应用绝对路径来引入,解决完后变成了
<img src="/userContent.png"">
其余页面有相似状况的能够用同样的形式来解决。
批改后再次重启我的项目, 这次批改后命令后仍然没有报错,关上浏览器后页面能够失常显示登录页面了,然而登录后页面又呈现了第 7 个报错。
5.7 第七个报错, require 引入动静异步组件问题.
看报错信息,这次和路由有关系,找到对应文件 cache.js,发现页面应用require 来引入动静路由组件了。
解决方案,采纳 vite 提供的 import.meta.glob 办法,写法如下
const modules = import.meta.glob('./../../pages/**/*.vue');
function getBaseRouterWrap(item,PathMap,parentItem) {
return {
path: item.url,
name: item.routerName,
component: modules[`./../../${PathMap[item.routerName]}.vue`],
meta: {
parentName:parentItem ? parentItem.routerName : null,
title: item.name,
tag: true,
icon: item.ico || '',
needLogin: true,
count: item.count,
show: item.show
}
}
}
看一下const modules = import.meta.glob(‘./../../pages/**/**.vue’); 的返回后果
import.meta.glob办法会把门路下所有查问到的文件以门路为 key,异步返回内容为 value 放到一个对象外面,应用的时候依据对于的文件名称引入,内容是 () => import(‘xxx.vue’) 异步引入的,正好合乎 vue-router 组件懒加载规定。
批改后再次重启我的项目, 这次批改后命令后仍然没有报错,关上浏览器后页面能够失常登录跳转页面了,然而跳转后页面又呈现了第 8 个报错。
5.8 第八个报错,‘xxx.less’wasn’t found..
发现还是因为门路的问题,有两种解决形式:
1. 第一种将所有的~@/ 改成咱们曾经配置到别名 @/。2. 新配置一个别名让~@/ 也指向 src 目录。
这里采纳的第二种形式,比较简单,只改一个中央就好了。
批改后再次重启我的项目, 这次批改后命令后仍然没有报错,关上浏览器后页面能够失常跳转了,切换多个页面都没有发现问题,测试一下热更新速度,在某个页面进行测试的时候发现,每次热更新状态都会重置,查看文件加载状况,发现又从新引入了main.js。
5.9 第九个报错, 热更新后触发从新实例化 vue 流程
在查找起因后,发现在 main.js 外面定义了退出登录的办法,而在触发热更新的页面从 main.js 外面引入了该办法,所以每次触发热更新,从新申请该页面 .vue文件时,也会触发从新加载 main.js, 从而引起该问题的产生,解决办法,把main.js 裸露的办法独自抽离到其余 js 文件外面,抽离后再测试就没问题了。
至此,开发阶段呈现的报错就都曾经解决了。
六. 我的项目打包阶段解决
6.1 解决我的项目兼容低版本浏览器
vite 打包后默认指标浏览器是指向现带浏览器,就是反对 es module 的浏览器,可是在很多时候咱们须要兼容低版本的浏览器,vite 官网为咱们提供了开箱即用的插件 @vitejs/plugin-legacy
先装置插件
npm install @vitejs/plugin-legacy -D
在 vite.config.js 的plguins插件外面增加
import legacy from '@vitejs/plugin-legacy'
legacy({targets: ['ie >= 9'],
additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
})
targets要依据本人我的项目状况来配置,插件还有很多其余的配置,能够看插件文档
6.2 解决 css 加前缀问题
原我的项目配置了 pocss-loader 来打包时主动加 css 前缀来兼容低版本浏览器,所以迁徙到 vite 后也须要解决下,在 vite 中能够采纳 autoprefixer 来实现,装置:
npm install autoprefixer -D
在 vite.config.js 的css.postcss.plugins外面增加 autoprefixer 插件,因为该插件默认只反对common.js,所以要用 require 引入,前面配置要反对的指标浏览器。
css: {
postcss: {
plugins: [require('autoprefixer')({overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 9', '> 1%'],
grid: true,
}),
]
}
}
配置实现后,再次打包后,就能够看到 css 曾经加上了前缀。
七. 总结
下面的实现后,打包就也没问题了,就能够连贯我的项目 git 或者笼罩复制到原我的项目中,提交到测试环境开始构建了。
当初 vite 的生态也趋于变的成熟,曾经能够满足于大部分业务场景了,不过在迁徙前还是尽量要做下调研,看目前 vite 生态是否满足本我的项目中一些定制化或者非凡的场景,比方 微前端 ,electron 反对等。
本文记录了在本我的项目迁徙过程中遇到的问题,遇到的问题必定只是 webpack 迁徙 vite 很小的一部分问题,当前在迁徙其余我的项目时候遇到新的问题也会补充进来。
本次迁徙最终 vite 配置
import {defineConfig} from "vite";
import {createVuePlugin} from "vite-plugin-vue2";
import CompressionWebpackPlugin from 'vite-plugin-compression'
import legacy from '@vitejs/plugin-legacy'
export default defineConfig({
plugins: [
/** 反对 vue2 **/
createVuePlugin(),
/** gzip 压缩 **/
CompressionWebpackPlugin({
algorithm: 'gzip',
threshold: 10240 // 只有大小大于该值的资源会被解决。默认值是 10k
}),
/** 配置浏览器兼容 **/
legacy({targets: ['ie >= 9'],
additionalLegacyPolyfills: ['regenerator-runtime/runtime']
})
],
build: {
chunkSizeWarningLimit: 2000,
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
},
brotliSize: false,
},
/** 为我的项目注入环境变量 **/
define: {'process.env.BASE_ENV': JSON.stringify(process.env.BASE_ENV)
},
resolve: {
/** 引入文件未带后缀时,顺次查找数组外面配置的后缀文件 **/
extensions: [".vue", ".js", ".json"],
/** 配置 alias 别名 **/
alias: [
{
find: '@/',
replacement: '/src/'
}
],
},
/** css 主动加前缀 **/
css: {
postcss: {
plugins: [require('autoprefixer')({overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 9', '> 1%'],
grid: true,
}),
]
}
},
server: {host: "0.0.0.0",},
});
参考资料:
vite 官网:https://vitejs.cn