作者:京东物流 邓道远

背景描述

随着项目的不断维护,代码越来越多,项目越来越大。调试代码的过程就变得极其痛苦,等待项目启动的时间也越来越长,尤其是需要处理紧急问题的时候,切换项目启动,等待的时间就会显得尤为的漫长。无法忍受这种开发效率的我,决定将老项目迁移至vite。

距离Vite工具发布到现在已经有了一些日子了,工具链与生态已经趋于稳定,最新版本已经更新到了3.0,既然念头已起,心动不如行动。

1、什么是Vite

vite 发音为/vit/ 法语中就是快的意思,“人”如其名,就是快

  • 一个开发服务器,它基于原生ES模块,提供了丰富的内建功能,如速度快到惊人的模块热更新(HRM)

  • 一套构建指令,它使用rollop来打包你的代码,并且是预配置的,可输出用于生产环境的高度优化过的静态资源。

2、为什么快

众所周知,当冷启动服务器时,基于打包器的启动必须优先抓取并构建你的整个应用,然后才能提供服务,这一抓取构建的过程随着文件越来越多,时间也会越来越长。

而Vite却通过将应用中的木块区分为依赖和源码两类,从而优化了大量的服务器启动时间。

  • 依赖大多为在开发时不会变动的纯 JavaScript。一些较大的依赖(例如有上百个模块的组件库)处理的代价也很高。依赖也通常会存在多种模块化格式(例如 ESM 或者 CommonJS)。

  • Vite 将会使用 esbuild预构建依赖。esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。

  • 源码通常包含一些并非直接是 JavaScript 的文件,需要转换(例如 JSX,CSS 或者 Vue/Svelte 组件),时常会被编辑。同时,并不是所有的源码都需要同时被加载(例如基于路由拆分的代码模块)。

  • Vite 以原生 ESM方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。

3、如何完成老项目迁移

当前项目是Vue2.0,vue-cli4.0,node v14.18.2

3.1 首先我们需要先明确项目结构

与原来的Vue老项目相比,模板文件 index.html 需要从public挪到项目根目录中,Vite将 index.html 视为源码和模块图的一部分。由于我们只有一个入口文件,所以在index.html中需要引入main.ts

<script type="module" src="/src/main.ts"></script>

而且运行过程中可能会遇到下面写法引发的报错

<link rel="icon" href="<%= BASE_URL %>favicon.ico" />

[vite] Internal server error: URI malforme

解决办法是可以写一个简单的插件替换一下

res = code.replace(/<%=\s+BASE_URL\s+%>/g, baseDir);

与Vue-cli相同,需要一个配置文件 vite.cofnig.js, 与原来的vue.config.js同级

3.2 安装依赖

既然我们使用Vite,那么我们需要安装一个vite依赖。但是我们的老项目是Vue2.0,vite优先支持Vue3.0,所以我们还需要一个转换工具 "vite-plugin-vue2"

npm i vite vite-plugin-vue2 -S

3.3 修改配置文件

修改package.json中的scripts,启动和打包方式使用vite

  • "serve": "vite",

  • "build": "vite build",

修改vite.config.js,与vue.config.js相似

import { defineConfig } from 'vite'
import { createVuePlugin } from 'vite-plugin-vue2' // https://vitejs.dev/config/ 这一行可以增加编辑器代码提示
export default defineConfig({
plugins: [
createVuePlugin({
jsx: true, // 兼容项目中的jsx组件
vueTemplateOptions: {}
}),
],
resolve: {
extensions: ['.vue', '.js', '.ts', '.jsx', '.tsx', '.json'],
alias: [
{
find: '@',
replacement: '/src'
}
]
},
server: {
open: true, // 控制台直接打开浏览器
host: 'xxxx.jd.com', // 本地host
allowedHosts: ['.jd.com', '.jdwl.com', '.jd.co.th', '.jd.id'],
port: 80,
cors: true,
proxy: {
'/api': {
target: 'https://xxx.jd.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '/api')
}
}
},
})

3.4 剔除原来的webpack相关依赖

可以手动剔除 也可以重新启动一个vite项目再将所需代码移动到vite项目中

3.5 启动应用

这个时候我们就可以启动应用了,不出意外的话,会有许多的报错信息,不过不要慌,我们一个一个的解决

4、遇见的问题汇总

4.1 环境变量

webpackl里的环境变量是默认存储在process.env里的,而vite是存储在import.meta.env里的

import.meta.env.MODE: {string} 应用运行的模式。

import.meta.env.BASE_URL: {string} 部署应用时的基本 URL。他由base 配置项决定。

import.meta.env.PROD: {boolean} 应用是否运行在生产环境。

import.meta.env.DEV: {boolean} 应用是否运行在开发环境 (永远与 import.meta.env.PROD相反)。

当然,既然是老项目,这种调用位置会有很多,我们可以使用比较简单的做法来兼容

export default defineConfig({
define: {
'process.env': {}
},
})

4.2 global 变量

因为VIte 是 ESM机制,有些包内部使用了 node 的 global对象,解决此问题可以通过自建pollfill, 然后在main.ts顶部引入

// polyfills
if (typeof (window as any).global === 'undefined') {
;(window as any).global = window
}

4.3 Scss全局变量报错

这一点是vite与vue-cli 配置方式不同引发,而且如果使用了环境变量也需要适配vite的写法兼容

export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: '$ossHostVariable: \'import.meta\u200b.env.VUE_APP_OSS_HOST\';'
}
}
}
})

4.4 path 报错

Vite 是 ESM机制 path是node的包,所以需要兼容浏览器的引入方式,需要安装依赖 “path-broswserfiy”

只需要将引入的包替换即可

import path from 'path'
// 替换成
import path from 'path-broswserfiy'

4.5 Require报错

问题的引发与上面一致 都是模块加载方式的不同导致的,可以通过"

vite-plugin-require-transform"插件来解决

import requireTransform from 'vite-plugin-require-transform'
export default defineConfig({
plugins: [
requireTransform({})
]
})

4.6 vue组件的动态导入

vue的组件导入方式有很多,vite可以支持 () => import('/.vue')的方式导入,不过与webpack的区别在于需要补全文件的后缀,动态导入需要 import.meta.glob的方式

const load = import.meta.glob('@/views/**/index.vue');

export const constantRoutes: any = [
{
path: '/404',
component: load['404']
},
]

4.7 编译时的分包策略

const SPLIT_CHUNK_CONFIG = [
{
match: /[\\/]src[\\/]_?common(.*)/,
output: 'chunk-common',
},
{
match: /[\\/]src[\\/]_?component(.*)/,
output: 'chunk-component',
},
]; const rollupOptions = {
output: {
chunkFileNames: 'assets/js/[name]-[hash].js',
entryFileNames: 'assets/js/[name]-[hash].js',
assetFileNames: 'assets/static/[name]-[hash].[ext]',
manualChunks(id) {
for (const item of SPLIT_CHUNK_CONFIG) {
const { match, output } = item; if (match.test(id)) {
return output;
}
} if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
},
},
}

5、启动时间

不多说了 上图

不过还会有一些问题,开发模式下比如页面首次加载时间比较缓慢,大约在5s左右,不过这也是可以理解的,毕竟编译过程都交给了浏览器,相比于老项目冷启动动辄2 3分钟的体验,已经是天大的提升了。

6、总结

最后再来回顾一下,整体的迁移过程。

首先,明确项目结构,index.html模板文件 提到根目录下,统计增加vite.config.js文件。

然后,编写配置文件 vite.config.js 注意与 vue.config.js上的语法区别,注意兼容写法。

最后,处理项目中两种打包工具的不兼容写法。大部分还是模块规范的区别,node环境的变量以及语法所引发,可以通过各种各样的插件来兼容解决。

以上即为本次迁移的全部过程,丰富、优化了前端工具链的构建流程,极大的提升了开发人员的幸福感,以及开发体验,项目冷启动时间更是提升了百分之99%。虽然前期遇到了许多的坑,但是成功后的感受就是一个字,"真香"。

拥抱下一代前端工具链-Vue老项目迁移Vite探索的更多相关文章

  1. vue老项目升级vue-cli3.0

    第一步我们卸载全局的vue2.0然后: 打开命令行 输入npm install -g @vue/cli-init   这个就是会安装全局的vue3.0版本.安装好之后我们也可以vue -V查看当前vu ...

  2. 老项目迁移到springboot之后,上线服务器出现404的解决方法

    原因是老项目迁移到springboot之后,已经不再使用web.xml的配置了,但是WEB-INF目录下还有web.xml,所以才导致的404,所以只需要在源码处删除整个WEB-INF重新build即 ...

  3. [技术博客] 软工-Ruby on Rails前端工具链的配置以及对Web应用结构设计的一点思考

    一.相关工具链简介 HAML HAML是专门面向Ruby on Rails模版语法设计的一门标记语言,其结合RoR的views部分模版语法的特点,对原来的*.html.erb(嵌入Ruby代码的HTM ...

  4. 【小家Spring】老项目迁移问题:@ImportResource导入的xml配置里的Bean能够使用@PropertySource导入的属性值吗?

    #### 每篇一句 > 大师都是偏执的,偏执才能产生力量,妥协是没有力量的.你对全世界妥协了你就是空气.所以若没有偏见,哪来的大师呢 #### 相关阅读 [[小家Spring]详解Propert ...

  5. NET Core2.1 WEB老项目迁移

    .NET Core2.1 版本新增功能不在赘述. NET Core2.1更新链接 如果开发需要安装Net Core2.1SDK,及Runtime. .NET Core2.1安装地址. 接下来是WEB ...

  6. antd+react项目迁移vite的解决方案

    antd+react+webpack往往是以react技术栈为主的前端项目的标准组合,三者都有成熟的生态和稳定的表现,但随着前端圈的技术不断革新,号称下一代构建平台vite2的发布,webpack似乎 ...

  7. 再见 Docker,是时候拥抱下一代容器工具了

    本文首发于:微信公众号「运维之美」,公众号 ID:Hi-Linux. 「运维之美」是一个有情怀.有态度,专注于 Linux 运维相关技术文章分享的公众号.公众号致力于为广大运维工作者分享各类技术文章和 ...

  8. Vue老项目支持Webpack打包

    1.老的vue项目支持webpack打包 最近在学习Vue.js.版本是2.6,webpack的版本也相对较老,是2.1.0版本.项目脚手架只配置了npm run dev和npm run build. ...

  9. 深入浅出的webpack构建工具--webpack4+vue+router项目架构(十四)

    阅读目录 一:vue-router是什么? 二:vue-router的实现原理 三:vue-router使用及代码配置 四:理解vue设置路由导航的两种方法. 五:理解动态路由和命名视图 六:理解嵌套 ...

  10. 老项目迁移到 springboot 过程

    打算把detectx迁移,毕竟springboot更适合它, 首先我是用的快速建立的项目,springboot版本为 1.5.19.RELEASE ,官网查了下,这个是GA稳定生产环境版本 然后如果要 ...

随机推荐

  1. ChatGPT 会开源吗?

    最近,我被一款叫做 ChatGPT 的人工智能(AI)聊天机器人,刷屏了.网上有人说它是搜索引擎杀手,还有人说它将取代程序员... 最后,我还是没扛住铺天盖地的赞美,跑去注册了个账号,抱着调侃&quo ...

  2. 网络爬虫之requests模块,自动办公领域之openpyx模块

    一.第三方模块的下载与使用 第三方模块:别人写的模块,一般情况下功能都特别强大    我们如果想使用第三方模块,第一次必须先下载,后面才可以反复使用(等同于内置模块) 下载第三方模块的方式 1. pi ...

  3. 04-CURD

    Insert @Test//测试插入 public void insertTest(){ User user = new User(); user.setName("wsk"); ...

  4. 3、mysql着重号解决关键字冲突

    1.着重号(`  `): 使用着重号(` `)将字段名或表名括起来解决冲突:保证表中的字段.表名等没有和保留字.数据库系统名或常用方法名冲突

  5. MongoDB - 副本集简介

    简介 在 MongoDB 中,副本集指的是一组 MongoDB 服务器实例掌管同一个数据集,实例可以在不同的机器上. 其中一个用于处理写操作的是主节点(Primary),还有多个用于保存主节点的数据副 ...

  6. C++ 之 cout 格式化输出

    写代码时每次用到格式化输出就各种搜来搜去,今天好好整理一下,方便以后查阅和使用. 参考链接: C++ 之 cout 使用攻略 C++ 格式化输出 首先,加上头文件 #include <ioman ...

  7. Flutter异常监控 - 伍 | 关于异常监控框架设计的思考

    前言 最近阅读 Catcher.BugSnag.Rollbar 三个 Flutter 异常监控开源框架,文章链接如下: Flutter 异常监控 - 壹 | 从 Zone 说起 Flutter 异常监 ...

  8. github下载后的文件,winrar打开中文是乱码

    是因为编码问题,通过7Z解压后正常

  9. Python3+Selenium3自动化测试-(准备)

    Python3+Selenium3自动化测试-(准备) 最近在学习selenium自动化测试相关的内容,所以将实际准备情况做一记录, # 系统:win10(64位) # 浏览器:Chrome(67.0 ...

  10. pytorch 配置详细过程

    torch github 项目多 方便,api好调用 cpu版本 装torch 安装最新版本的就可以. torchvision 要版本对应 算法: torchvision版本号= torch版本号第一 ...