vite + webpack 工程化实践

您所在的位置:网站首页 vue查看webpack版本 vite + webpack 工程化实践

vite + webpack 工程化实践

#vite + webpack 工程化实践| 来源: 网络整理| 查看: 265

背景

我们有个用umi搭建的项目一直在迭代增加功能,项目引入的第三方库也越来越多,本地开发webpack启动dev-server越来越慢,就拿我自己用的Macbook pro 14寸来说,搭载了M1 Pro芯片都要一分钟左右,热更新要3秒左右,其他前端小伙伴用的机子启动要3分钟,热更新等10多秒,这是非常影响开发体验和效率的,目前构建工具除了webpack之外还有esbuild以及swc,而目前基于esbuild的vite是非常不错的选择,所以有了迁移vite的动力

vite VS webpack

相信都2022年了大家应该都或多或少了解过vite,简介我就不再赘述了,简单列一下vite与webpack的优缺点:

viteWebpack启动开发服务器利用浏览器的原生ESM加载源码模块,启动时处理一次依赖预构建即可,二次启动秒开,访问时浏览器原生解析依赖递归依赖分析、转换代码、编译、打包输出主流浏览器可直接执行的js文件,浏览器访问直接渲染构建打包器基于ESBuild使用Go编写,构建速度比nodejs快10-100倍webpack由javascript编写运行在nodejs环境,运行效率较差热更新精准更新已修改的ESM模块修改文件后需要重新构建文件,且随着应用体积增大而花费更长时间生态vite生态只能说勉强够用,某些功能可能需要妥协或者自己实现Loader和Plugin生态丰富,方案齐全生产环境Esbuild本身存在一些限制,所以生产环境采用的rollup依托丰富的生态,稳定可靠

vite就像苹果刚出M1芯片的那种新世代的感觉,第一感觉是快,上手后是真香,但生态是个小遗憾,未来可期。

总结一下优缺点:

在启动开发服务器、热更新方面vite掌握了绝对优势,而在生态与生产环境构建的场景下rollup对比webpack优势不明显,rollup比较适合于类库的项目打包,所以对于生产环境构建和生态考虑我依然会选择webpack

所以从对比来看vite和webpack 各自的优点都非常绝妙的满足了对方的缺点,这难道就是命中注定的另一半么,那么为何不取长补短,将双方的优势合为一体呢

vite + webpack

我们只需要在开发环境用vite,生产环境用webpack就可以形成互补,即能提高开发效率,还能保证生产稳定,值得注意的是这两套构建工具要在同一套代码里正常执行。

vite对于文件结构有特殊要求(模块化的样式文件名必须要有.module),与webpack的配置形式也大相径庭,所以还需要一个适配器(Adapter),只使用一种配置形式实现两套构建工具正常执行。

这个适配器,就是来自阿里飞冰团队的ice.js`,ice.js从2.0开始同时支持Webpack@5 以及 Vite@2 两种模式,只用一套特定的配置形式,只要通过环境变量就可以实现开发环境用vite,生产环境用webpack了。

实现vite + webpack

我们可以快速初始化一个ice.js项目:

$ npm init ice # or $ yarn create ice 复制代码

根据交互提示选择想要的模板,创建完就可以进入项目里安装依赖启动:

$ cd # 安装依赖 $ npm install # 启动项目 $ npm start 复制代码

执行上述命令后,会自动打开浏览器窗口访问 http://localhost:3333,这时应该看到默认的页面。

然后在package.json里配置启动命令区分开发环境使用vite模式,生产环境使用webpack模式即可:

"scripts": { "start": "icejs start --mode vite", "build": "icejs build --mode webpack", .... }, 复制代码 个性化定制

由于ice.js内置了很多约定式的第三方能力(路由、状态管理、请求库、权限,封装过的entry等),而我从旧项目迁移必定会有不兼容写法的情况,所以想放弃内置功能,不要约定式的文件结构,自己写entry,自己接入路由、请求库、状态管理等功能,ice.js也是支持这么做的,需要在ice的配置中关闭这些功能:

store: false, // 关闭自带的状态管理 auth: false, // 关闭自带的权限控制 request: false, // 关闭自带的request disableRuntime: false, // 关闭所有运行时能力 复制代码

然后根据自己需要配置src/app.tsx的entry代码就可以了,我这里有一个已经引入了react-router-dom、dva的项目可以参考:lipten/ice-vitepack-project: icejs2.0 + antd + dva.js 定制entry和工程配置的初始项目 (github.com)

常见问题 第三方库不兼容ESModule:

vite只能加载ESModule规范的模块,对于其他模块规范文件需要特殊处理,vite的依赖预构建默认会找package.json里的依赖包自动处理兼容的写法,所以第三方库我们可以放到src路径下,通过yarn add ./src/xxx 添加本地库

添加后就会在package.json自动有下面这行依赖

"xxx": "./src/libs/xxx", 复制代码 require语句换成Import xxx from 'xxx'

一些静态资源可能用了require语句,需要换成ESM的写法

动态路径加载文件地址

当vite需要实现require(@/assets/images/${imgPath})这种动态路径加载时,换成以下写法:

// 仅支持相对路径 new URL(`../../../src/${path}`, importa.url).href 复制代码

可以做一下兼容webpack的处理

export const importAssetsPath = (path: string) => { return window.IS_VITE ? new URL(`../../../src/assets/${path}`, importa.url).href : require(`../assets/${path}`); }; 复制代码 动态加载模块import().then()

vite不支持动态加载模块import('xxxx').then()

Image

vite自带的rollup支持这种用法,所以可以增加 /* @vite-ignore */ 可以支持import('xxxx').then()

Image

引入@ant-design/compatible报错

Image

因为@ant-design/compatible依赖了draft-js里面用了global这个变量在浏览器会报错,只要在入口js赋值一下global即可

window.global = window 复制代码 require()使用动态路径时必须要有src/xxx作为静态路径

webpack可能在分析require路径时需要确定src下以及路径作为静态字符串目录

下面的代码是无法正常解析的:

const path = 'assets/images/xxx.png' require(`@/${path}`) require(`../${path}`) require(`~/src/${path}`) 复制代码

应该改为下面的路径写法:

const path = 'images/xxx.png' require(`@/assets/${path}`) require(`../assets/${path}`) require(`~/src/assets/${path}`) 复制代码


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3