557 字
3 分钟
解决 Tabler 升级导致分块过多的 Bug

前两天对项目的依赖做了一次升级,已经两年没有更过了,这次涉及的依赖是 mantine 和 tabler,但升级之后出现了一个神秘问题,本文用于记录现象、排查过程与解决方案。

严格来说,这是 tabler 和 vite 的问题。

问题现象#

  • 开发环境初始化加载 6000+ chunks
  • 本地服务冷启动耗时增加约30秒
  • 生产构建不受影响

alt text alt text

排查过程#

先观察异常请求的特征#

通过 Network 面板发现大量 <5kb 的 chunk 请求,点开响应可以看到包含 @tabler 关键字。 alt text

从依赖上溯源#

@tabler/[email protected] 的源码中发现他是通过动态导入的方式加载所有图标的:

var dynamicImports = {
  "a-b-2": () => import('./icons/IconAB2.mjs'),
  // ...
}

export { dynamicImports as default };

import() 属于动态导入,对于每一个导入的内容,vite 都会创建出一个独立的 chunk,到这里还不能说完全有问题,关键在于他使用 dynamicImports 的地方:

import * as dynamicImports from './dynamic-imports.mjs';

export { dynamicImports };

在 tabler 这个依赖的入口文件 tabler-icons-react.mjs 中,他将 dynamicImports 给直接导入导出了,就意味着你如果导入了 @tabler/icons,在开发环境下,vite 分析依赖的时就会把相关的的模块全都加载进来。

根据 issue 的记录,这个写法是为了支持动态加载图标而加入的,就是 <Icon name={iconName} /> 这种场景,但 pr 提供者似乎完全没有考虑到使用 vite 构建工具的情况。

解决方案#

我这里想到、收集到的总共三种:

版本回退#

回退到 3.17 版本,这样可能会丢失一些新版本加入的图标

代码修补#

通过 patch-package 修改入口文件,把那两行注释掉,失去动态导入的特性。

别名#

// vite.config.js
export default {
  resolve: {
    alias: {
      '@tabler/icons-react': 'node_modules/@tabler/icons-react/dist/esm/icons/index.mjs'
    }
  }
}

跳过依赖的指定入口,直接使用 esm 构建好的静态模块,但这种也要注意一个问题,有些静态文件的名称和导出时的名字不一样,比如 IconBoxSeam 是找不到对应图标的,因为图标文件名是 Package

解决 Tabler 升级导致分块过多的 Bug
https://blog.erio.work/posts/解决tabler升级导致分块过多的bug/
作者
Dupfioire
发布于
2025-05-21
许可协议
CC BY-NC-SA 4.0