关于vue.js:前端工程化vue2webpack3项目迁移vite2踩坑总结

30次阅读

共计 10682 个字符,预计需要花费 27 分钟才能阅读完成。

目录

  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

正文完
 0