首页 > 解决方案 > 将应用程序的一部分分解到它自己的 NPM 包中会导致更大的整体应用程序大小

问题描述

我们在所有项目中都使用create-react-appTypescript,并且出现了一个稍大的常用 React 组件模块。试图将这些因素分解到它自己的 NPM 包中(为了更容易维护和更好地重用),这里PackageA称为TestApp代码存在于同一应用程序的代码库中)。TestApp是一个非常简陋的应用程序,它基本上只是展示了 中组件的一些(但不是全部)部分PackageA,以前是项目本身内部的组件,现在删除了这部分,而是从私人发布PackageA的 .

PackageA在从组件中分解出来之前的初始 JS 块的大小TestApp(假设“main”是来自项目本身的代码,而另一个块被认为包含依赖项):

分解后PackageA的尺寸TestApp

可以看出,整体大小随着13 kB gzip 和56 kB unzip 的增加而增加。这对应于gzipped增加了~ 6%和 unzipped 增加了~ 8%。这并不算多,但我仍然希望它们有点相似。

更多的信息

这种规模增加的可能来源是什么?我们可以从哪里开始寻找?也许这种增加可能在于代码在包中的转译create-react-app方式,并且对于包含在项目本身中的代码比对导入的代码更有效地做到这一点。我知道这是一个棘手的问题,可能有很多答案,而且很难回答。

这是tsconfig.json用于分解的PackageA

{
  "compilerOptions": {
    "target": "es6",
    "lib": ["es6", "dom"],
    "jsx": "react-jsx",
    "module": "es6",
    "rootDir": "./src",
    "moduleResolution": "node",
    "declaration": true,
    "sourceMap": true,
    "outDir": "./build/esm",
    "inlineSources": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  },
  "include": ["./src"],
  "exclude": ["**/*.test.tsx", "**/*.test.ts", "**/*.stories.tsx"]
}

标签: typescriptnpmpackagecreate-react-appes6-modules

解决方案


我知道这个问题可能在很大程度上取决于你所处的情况,但我仍然认为我会分享我的过程。

测量尺寸

通常在您构建时,您的框架会输出构建工件的大小。在 的情况下create-react-app,这些大小似乎是 gzip 压缩版本的大小。

您还可以检查您的浏览器开发工具并注意下载的包的大小,这些包通常不是压缩后的大小,而是实际大小。

在分解某些东西或进行某种比较时,请注意更改前后的不同尺寸。给定关于这些大小应该如何改变的某种直觉,评估是否是这种情况。

分析捆绑包

您可以使用 NextJS @next/bundle-analyzer,在大多数其他情况下,您可以使用source-map-explorer. 后者使用源映射将捆绑的代码映射到源;如果源本身有源映射,则使用这些源,否则您将看到对node_modules. 使用source-map-explorer,可能值得同时研究视觉表示和 json 表示,因为在很多来源的情况下,视觉表示可能会抑制 json 表示不会参与的某个组件或库的参与。

您可以在source-map-explorer应用程序的不同版本之间进行一些有价值的比较。

分析源代码到生产代码的特殊情况

例如,在source-map-explorer确定某些源代码在某些上下文中扩展得更多之后,您可能希望进一步研究该问题。使用源映射(在开发模式下或在生产模式下,如果您有它们可用),您可能想要跟踪输出包中源代码的某个部分的印记。许多浏览器支持将捆绑代码映射到源代码(给定源映射),但并非所有浏览器都允许您做相反的事情。然而,Firefox 具有此功能,它允许您在给定捆绑代码的情况下查看源代码,反之亦然。当您尝试跟踪某些源代码在输出中实际产生的结果时,这非常有用。

我的用例呢?

好吧,以下是在我的情况下导致大小增加的原因列表:

  • 我从包中的索引导入,索引导入包的所有导出。这应该不是 esm 模块的问题,但是如果没有sideEffects: false标志,package.json就会有一些歧义。即使 MY 包中未使用的源没有添加到输出包中,但不能排除一些间接依赖项没有副作用,因此将这些添加到包中,即使导入它们的组件甚至没有使用。添加sideEffects: falsepackage.json我的包中解决了这个问题并减小了包的大小。

  • 在我的主项目中保留使用 捆绑的组件时,create-react-app由于@babel/plugin-transform-runtime插件的存在,Babel 在所有转译文件中添加的一些便利方法都被删除了。这个插件删除了这些便利方法,因为在运行这些文件时保证存在一些 Babel 运行时(它们可以从中导入)。当将相同的配置用于已分解的组件时,尺寸缩小得更多。

  • 最后,在撰写本文时,tsc编译器似乎输出了比 Babel 更详细的代码(请参阅TypeScript:tsc 将 jsx 转换为比 babel 更详细的代码)。在转译我第一次使用的包tsc和开始使用 Babel 后,尺寸缩小了更多。

总而言之,通过上述更改,输出最终仅比重构前大 1.7 kB(解压缩),这是一个既可以理解又可以接受的结果。


推荐阅读