【实战】 Webpack to Vite, 为开发提速!

发表于 3年以前  | 总阅读数:387 次

Webpack to Vite 背景

最近,就 前端开发过程中的痛点及可优化项 做了一次收集。 其中,构建耗时、项目编译速度慢 的字眼出现了好几次。

随着业务的快速发展,我们很多项目的体积也快速膨胀。随之而来的, 就是打包变慢等问题。

提升研发效率,是技术人永恒的追求。

我们项目也有启动慢的问题,同事也提到过几次。刚好我之前也做过类似的探索和优化, 于是就借这个机会,改造一下项目, 解决启动耗时的问题

于昨天下午(2021.4.7 23:00), 成功嵌入 Vite, 项目启动时间由约 190s => 20s, 热更新时间缩短为 2s

中间踩了一些坑, 好在最后爬出来了, 相关技术要点都会在下文中呈现。

FBI Warning:以下文字,只是我结合自己的实际项目, 总结出来的一些浅薄的经验, 如有错误,欢迎指正 :)

今天的主要内容:

  • 为什么 Vite 启动这么快
  • 我的项目如何植入 Vite
  • 改造过程中遇到的问题以及解决方式
  • 关于 Vite 开发、打包上线的一些思考
  • 相关代码和结论

正文

为什么 Vite 启动这么快

底层实现上, Vite 是基于 esbuild 预构建依赖的。

esbuild 使用 go 编写,并且比以 js 编写的打包器预构建依赖, 快 10 - 100 倍。

因为 js 跟 go 相比实在是太慢了,js 的一般操作都是毫秒计,go 则是纳秒。

另外, 两者的启动方式也有所差异。

webpack 启动方式

image.png

Vite 启动方式

image.png

Webpack 会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。

而 Vite 是直接启动开发服务器,请求哪个模块再对该模块进行实时编译

由于现代浏览器本身就支持 ES Module,会自动向依赖的 Module 发出请求。

Vite 充分利用了这一点,将开发环境下的模块文件,就作为浏览器要执行的文件,而不是像 W ebpack 那样进行打包合并

由于 Vite 在启动的时候不需要打包,也就意味着不需要分析模块的依赖不需要编译。因此启动速度非常快。当浏览器请求某个模块时,再根据需要对模块内容进行编译。

这种按需动态编译的方式,极大的缩减了编译时间,项目越复杂、模块越多,vite 的优势越明显。

在 HMR(热更新)方面,当改动了一个模块后,仅需让浏览器重新请求该模块即可,不像webpack那样需要把该模块的相关依赖模块全部编译一次,效率更高。

从实际的开发体验来看, 在 Vite 模式下, 开发环境可以瞬间启动, 但是等到页面出来, 要等一段时间。

我的项目如何植入 Vite

新项目

创建一个 Vite 新项目就比较简单:

yarn create @vitejs/app

image.png image.png

生成好之后, 直接启动就可以了:

image.png

已有项目

已有项目的迁移, 稍微繁琐一些。

首先, 加入 Vite 的相关配置。这里我使用了一个 cli 工具:wp2vite.

安装好之后, 直接执行:

image.png

这一步, 会自动生成 Vite 的配置文件,并引入相关的依赖。

把依赖安装一下, 启动就可以了。

如果没有意外的话, 你会收获一堆报错

恭喜你,进入开心愉快的踩坑环节。

我在改造过程中遇到的问题

1. alias 错误

image.png

项目代码里配置了一些别名,vite 无法识别,所以需要在vite 里面也配置 alias:

 resolve: {
    alias: {
      '@': resolve(__dirname, 'src'),
    },
  },

2. 无法识别 less 全局变量

image.png

解决办法:

把自定义的全局变量从外部注入即可, 直接在 vite.config.js 的 css 选项中加入:

  css: {
    preprocessorOptions: {
      less: {
        modifyVars: {
          hack: `true;@import '${resolve('./src/vars.less')}';`,
          ...themeVariables,
        },
        javascriptEnabled: true,
      },
    },
  },

3. Uncaught Error: Target container is not a DOM element.

image.png

根元素未找到。

原因是:默认生成的 index.html 中:

<div id="root"></div>

id 是 root, 而逻辑中的是#app, 这里直接改成 id=app 即可。

4. typings 文件找不到

image.png

typings 文件未找到

这个错误, 乍一看, 一头雾水。

进去看一下源代码和编译后的代码:

源代码:

image.png

编译后:

image.png

image.png

typings 文件这不是好好的在这吗, 怎么就找不到?

想了一下:Vite 不知道 typeings 文件是不需要被编译的,需要告诉编译器不编译这个文件。

最后在 TS 官方文档里找到了答案:

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html

Type-Only Imports and Export

This feature is something most users may never have to think about; however, if you’ve hit issues under --isolatedModules, TypeScript’s transpileModule API, or Babel, this feature might be relevant.

TypeScript 3.8 adds a new syntax for type-only imports and exports.

import type { SomeThing } from "./some-module.js";
export type { SomeThing };

需要单独引入types, 于是把代码改为:

image.png

同时要注意, 如果一个文件有有多个导出, 也要分开引入:

image.png

唯一痛苦的是: 全局都需要改一遍, 体力活。

至此,typeings 问题完美解决。

5. 无法识别 svg

我们在使用 svg 作为图标组件的时候, 一般是:

import Icon from '@ant-design/icons';
import ErrorSvg from '@/assets/ico_error.svg';

const ErrorIcon = (props: any) => <Icon component={ErrorSvg} />;

// ...
<ErrorIcon />

浏览器报错:

image.png

error occurred in the </src/assets/ico_error.svg> component

很明显的看到, 这里是把文件路径作为组件了。

现在要做的是:把这个文件路径, 换成可以识别的组件。

搜索一番, 找到了个插件:vite-plugin-react-svg

加入配置:

const reactSvgPlugin = require('vite-plugin-react-svg');

plugins: [
  reactSvgPlugin(),
],
import MyIcon from './svgs/my-icon.svg?component';

function App() {
  return (
    <div>
      <MyIcon />
    </div>
  );
}

需要注意的是:引入的 svg 文件需要加 ?component 作为后缀。

看了一下源码, 这个后缀是用来作为标识符的,

image.png

如果后缀匹配上是component, 就解析文件, 并缓存, 最后返回结果:

image.png

知道原理之后, 就需要把全部的 .svg => .svg?component

vscode 一键替换就可以, 不过注意别把 node_module 里面的也替换了。

6. global 未定义

image.png

global 是 Node里面的变量, 会在客户端报错 ?

一层层看下去, 原来是引入的第三方包使用了global。

看 vite 文档里提到了 Client Types:

image.png

追加到 tsconfig 里面:

 "compilerOptions": {
    "types": ["node", "jest", "vite/client"],
 }

然后, 并没有什么乱用。。。

image.png

没办法, 只得祭出 window 大法。

在入口index.tsx 里面加上:

(window as any).global = window;

刷新, 好了。

image.png

7. [未解决] 替代HtmlWebpackPlugin

还需要注入一些外部变量, 修改入口html, favicon, title 之类。

找到一个插件:vite-plugin-singlefile

不过并没有什么用。

有了解的同学请留言赐教。

至此, 整个 app 已经能在本地跑起来了, build 也没问题。

7. 线上打包构建时, 内存溢出

本地能跑起来, 打包也没问题, 后面当然是放到线上跑一跑啦。

立刻安排!

memory.png

内存不足, 我就给你加点:

image.png

success.png

搞定!

关于 Vite 开发、打包上线的一些思考

从实际使用来看, vite 在一些功能上还是无法完全替代 webpack。

毕竟是后起之秀, 相关的生态还需要持续完善。

个人认为,目前一种比较稳妥的方式是:

  • 保留 webpack dev & build 的能力, vite 仅作为开发的辅助

等相关工具再完善一些, 再考虑完全迁移过来。

相关代码和结论

一个完整的 Vite demo

仓库地址:https://github.com/beMySun/react-hooks-i18n-template/tree/test-wp2vite

image.png

业务项目的 vite.config.js 完整配置

import { defineConfig } from 'vite';
import reactRefresh from '@vitejs/plugin-react-refresh';
import legacyPlugin from '@vitejs/plugin-legacy';
import { resolve } from 'path';

const fs = require('fs');
const lessToJS = require('less-vars-to-js');
const themeVariables = lessToJS(fs.readFileSync(resolve(__dirname, './src/antd-custom.less'), 'utf8'));
const reactSvgPlugin = require('vite-plugin-react-svg');

// https://cn.vitejs.dev/config/
export default defineConfig({
  base: './',
  root: './',
  resolve: {
    alias: {
      'react-native': 'react-native-web',
      '@': resolve(__dirname, 'src'),
    },
  },
  define: {
    'process.env.REACT_APP_IS_LOCAL': '\'true\'',
    'window.__CID__': JSON.stringify(process.env.cid || 'id'),
  },
  server: {
    port: 8080,
    proxy: {
      '/api': {
        target: 'https://stoku.test.shopee.co.id/',
        changeOrigin: true,
        cookieDomainRewrite: {
          'stoku.test.shopee.co.id': 'localhost',
        },
      },
    },
  },
  build: {
    target: 'es2015',
    minify: 'terser',
    manifest: false,
    sourcemap: false,
    outDir: 'build',
    rollupOptions: {},
  },
  esbuild: {},
  optimizeDeps: {},
  plugins: [
    // viteSingleFile({
    //   title: 'dynamic title', // doesn't work
    // }),
    reactSvgPlugin(),
    reactRefresh(),
    legacyPlugin({
      targets: [
        'Android > 39',
        'Chrome >= 60',
        'Safari >= 10.1',
        'iOS >= 10.3',
        'Firefox >= 54',
        'Edge >= 15',
      ],
    }),
    // vitePluginImp({
    //   libList: [
    //     {
    //       libName: 'antd',
    //       style: (name) => `antd/es/${name}/style`,
    //     },
    //   ],
    // }),
  ],
  css: {
    preprocessorOptions: {
      less: {
        modifyVars: {
          hack: `true;@import '${resolve('./src/vars.less')}';`,
          ...themeVariables,
        },
        javascriptEnabled: true,
      },
    },
  },
});

最后

使用 Vite 能大幅缩短项目构建时间,提升开发效率。

不过也要结合项目的实际情况,合理取舍。

对于我的这个项目而言,把 Vite 作为辅助开发的一种方式,还是挺有用的。

期待 Vite 能继续完善,为研发提效。

好了, 内容大概就这么多, 希望对大家有所帮助。

才疏学浅,如有错误, 欢迎指正。

谢谢。

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/4-HKMqRC-aY_OLIcpRyfag

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:6月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:6月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:6月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:6月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:6月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:6月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:6月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:6月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:6月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:6月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:6月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:6月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:6月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:6月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:6月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:6月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:6月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:6月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:6月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:6月以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  236810次阅读
vscode超好用的代码书签插件Bookmarks 1年以前  |  6656次阅读
 目录