create-react-app 减少构建大小:main.[hash].chunk.js 是 3MB+,主要是图像

AVA*_*AVT 8 reactjs webpack create-react-app

我用 yarn build.

它生成一个 3.27MB 的build\static\js\main.8dc5bf7f.chunk.js文件:

3.27 MB   build\static\js\main.8dc5bf7f.chunk.js
82.79 KB  build\static\js\2.61d04f1f.chunk.js
2 KB      build\static\css\main.275d97bd.chunk.css
1.93 KB   build\static\css\2.8380becc.chunk.css
768 B     build\static\js\runtime~main.848c2454.js

The bundle size is significantly larger than recommended.
Consider reducing it with code splitting
You can also analyze the project dependencies
Run Code Online (Sandbox Code Playgroud)

我曾经source-map-explorer分析过这个文件,它显示:

在此处输入图片说明

因此该文件包含我整个应用程序的所有图像。

但有趣的是,构建仍然有一个static/media目录,其中包含 .png 格式的所有图像。显然该应用程序仍然加载这些 png 文件以显示图像。

那么js文件中的那些东西是什么?我想知道它们是否甚至被使用过?

请:

  • 向我解释为什么我的整个应用程序中的所有图像都包含在我的逻辑 javascript 文件中。
  • 有没有办法删除它们?我需要增加页面负载。初始加载时 4MB 令人难以置信。

Grg*_*gur 10

随着应用程序变得越来越大,这是大多数工程师面临的一个棘手问题。

在您的情况下,您要导入许多由于 CRA 的 webpack 设置而进行 base64 编码的小 PNG。您可以使用react-rewired 之类的库覆盖该行为。虽然它涉及更多的过程,但我建议不要维护外部图像存储库。在开发环境中更容易测试和使用。尤其是离线时。

我还看到您的大部分视图都捆绑在 main.js 中。

减少包大小的秘诀在于利用代码拆分和延迟加载。

这是我为此整理的视频的链接:https : //www.youtube.com/watch?v=j8NJc60H294

简而言之,我建议以下模式:

代码拆分路由(如果有)

这通常是通过使用来实现的 React.lazy()

import React, { Suspense, lazy } from 'react';
// import MyRoute from 'routes/MyRoute' - we are replacing this import

const MyRoute = lazy(() => import('routes/MyRoute'));

const Loading = () => <div>Loading route...</div>;

const View = () => (
  <Suspense fallback={Loading}>
    <MyRoute />
  </Suspense>
);
Run Code Online (Sandbox Code Playgroud)

代码拆分低优先级元素

每个页面都有关键路径内容。这是您的访问者想要首先体验的内容。这是视图的主要目的。它通常位于折叠区域的上方(页面加载时他们看到的视图部分,没有任何滚动)。

但是,该部分也可以根据优先级进行剖析。英雄是一个很好的关键路径示例,因此我们应该优先考虑它。汉堡菜单是一个很好的取消优先级的元素,因为它需要交互才能被查看。

任何低于折叠的东西也可以被取消优先级。Youtube 评论就是一个很好的例子。只有当我们充分向下滚动时,它们才会被加载。

您可以按照与上述相同的原则来确定关键路径内容的优先级:

import React, { Suspense, lazy } from 'react';
import Hero from 'component/Hero'

const Burger = lazy(() => import('components/Burger'));

// The fallback should be used to show content placeholders.
// It doesn't have to be a loading indicator.
const Loading = () => <img src="path/to/burger/icon" alt="Menu"/>;

const View = () => (
  <main>
    <Hero />
    <Suspense fallback={Loading}>
       <Burger />
    </Suspense>
  </main>
);

Run Code Online (Sandbox Code Playgroud)

为库创建抽象组件

遵循上述原则,我建议为每个库创建简单的抽象组件。假设您需要动画并使用 Framer Motion。您可以在一处导入并在任何地方使用。

许多库附带命名导出并且lazy()不支持。我写了一个非常简单的库react-lazy-named来帮助解决这个问题。

// AnimatedDiv.js

import React, { lazy } from 'react';

// This is similar to
//   import { motion } from 'framer-motion';
//   const Div = motion.div;
// Also, we hint webpack to use resource preloading (think service worker goodness)
const Div = lazy(() => import('framer-motion' /* webpackPreload: true */), 'motion.div'));

// Use regular div as a fallback.
// It will be replaced with framer-motion animated Div when lazy-loaded
const AnimatedDiv = (props) => (
  <Suspense fallback={<div>{props.children}</div>}>
    <Div {...props} />
  </Suspense>
);
Run Code Online (Sandbox Code Playgroud)

如果您有任何问题或需要帮助,您可以在此处回复或在上述视频的评论中在 3 秒内加载 React 应用程序


Sul*_* H. 8

基本上,您import在应用程序中处理的任何与 webpack 捆绑的内容都将被视为依赖项。

so:import img from path/to/img将使其成为依赖项,因此,包含在您的包中,这就是您想要逃避的。

有两种可能的方案可以解决此问题:

  1. 停止导入图像,使它们可用/托管在 CDN 中,例如 AWS S3。
  2. 应用 Move Statics Out 方法,即将静态文件的所有目录从包中移出,使它们在静态依赖文件夹中可用并开始使用相对链接,我建议使用copy-webpack-plugin

对我来说,我会选择 1。