目录

  1. 前言
  2. 迁徙前后比照
  3. 迁徙流程
  4. 迁徙业务代码到vite我的项目
  5. 我的项目开发阶段报错解决
  6. 我的项目打包阶段解决
  7. 总结

一. 前言

公司有个特地大保护工夫长的后盾管理系统,应用的是vue2webpack3,尽管配置了很多编译优化,但启动和开发热更新速度仍然很慢,极大的影响了开发效率,于是筹备迁徙vite2来优化,当初已迁徙降级,来复盘记录下过程,至于vite速度快于webpack的起因,曾经有很多文章讲的很明确,这里只记录下迁徙过程和遇到的问题。

二. 迁徙前后比照

比照迁徙前webpack3迁徙后vite2
启动开发模式40秒3秒之内
热更新6秒+1秒之内
打包构建(vite不做低版本浏览器兼容)2分30秒40秒
打包构建(vite做低版本浏览器兼容)2分30秒1分05秒

三. 迁徙流程

  1. 先创立新的vite我的项目
  2. 新版vite我的项目默认是反对vue3的,须要把vue改成vue2版本后配置vite-plugin-vue2插件来反对vue2
  3. 把我的项目代码改成vue2写法,确保新vite我的项目能够失常运行vue2
  4. 把原webpack我的项目生产环境依赖复制到vite我的项目,剔除掉webpack相干的插件依赖
  5. 复制原我的项目src文件代码和其余业务相干代码到新vite我的项目。
  6. vite我的项目配置开发环境启动命令,依据报错信息来进行调整。
  7. 在测试开发和打包环境都没问题后,替换原先的我的项目。

四. 迁徙业务代码到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"}
  1. 打包增加node node_modules/esbuild/install.js,是用来解决esbuild装置时报错的bug相干issue
  2. 之所以环境变量没有应用NODE_ENV,是因为很多第三方包都应用NODE_ENV来判断开发环境和打包环境,为了不影响,采纳新加一个环境变量的形式

第三步, 配置vite.config.js,使vite在我的项目外面注入环境变量

只是应用cross-env设置环境变量的话,我的项目外面是拜访不到的,须要配置一下vite的define配置,能力拜访到,相似于webpackDefinePlugin插件性能

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, 所以未找到,此时有两种解决方案

  1. 手动增加 .vue后缀,然而我的项目这么宏大,很多中央都没有带后缀,全副改必定不容易。
  2. 配置vite.config.jsextensions字段,来增加主动查找文件扩展名后缀。

采纳第二种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文件中应用 @importelement-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.jsplguins插件外面增加

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.jscss.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