zoukankan      html  css  js  c++  java
  • 打包优化实践(如何Code Spliting)

    项目地址:ReactSPA

    使用 webpack 插件找出占用空间较大的包

    开发环境中可使用 analyze-webpack-plugin 观察各模块的占用情况。以该项目为例:浏览器中输入 http://localhost:3000/analyze.html 可以看到如下效果:

    按需加载

    • 对模块结合 babel 进行按需加载;
    • 测试 day.js 替代 moment.js. 实际上 moment.js 也使用按需加载 了(实验减少了 40KB+),所以最终结果相差不大;

    code-spliting

    使用 MiniCssExtractPlugin 插件分离 JavaScript 和 Css 文件:

      823.94 KB           build / static / js / main.496a38b7.js
      8.2 KB              build / static / css / main.css
    

    code-spliting 官方给出三种方案,分别如下:

    方案一:在 entry 处增加打包入口

    方案一的缺点如下:

    • 如果多个文件引人了相同的包(比如 lodash),引用的包会被分别打包两次;
    • 这种方案不够灵活,无法根据逻辑动态分割代码;

    所以方案一通常会结合方案二、方案三一起使用,方案一的配置大致如下:

    entry: [require.resolve('./polyfills'), paths.appIndexJs],
    
    // 也可以写成
    
    entry: {
      polyfill: require.resolve('./polyfills'),
      IndexJs: paths.appIndexJs,
    },
    

    方案二:使用插件 SplitChunkPlugin

      optimization: {
        runtimeChunk: false,
        splitChunks: {
          cacheGroups: {
            vendor: {
              chunks: 'all',
              test: /[\/]node_modules[\/]/,
              name: 'vendor',
              maxAsyncRequests: 5,
              priority: 10,
              enforce: true,
            },
          },
        },
      },
    

    打包效果如下:

      723.96 KB  build/static/js/vendor.a9289a29.chunk.js // node-modules 模块
      98.72 KB   build/static/js/main.7bcaca24.js
      8.2 KB     build/static/css/1.css
    

    此时将 node-modules 里的包打包成了一个大块头,这样对加载仍然是不友好的。解决方案为:将核心的框架单独打包出来,剩余模块异步加载,比如可以使用 bundle-loader)。

      optimization: {
        runtimeChunk: false,
        splitChunks: {
          cacheGroups: {
            vendor1: { // 主要模块
              chunks: 'all',
              test: /[\/]node_modules[\/](react|react-dom|antd)[\/]/,
              name: 'vendor1',
              maxAsyncRequests: 5,
              priority: 10,
              enforce: true,
            },
            vendor2: { // 次要模块
              chunks: 'all',
              test: /[\/]node_modules[\/]/,
              name: 'vendor2',
              maxAsyncRequests: 5,
              priority: 9,
              enforce: true,
              reuseExistingChunk: true,
            },
          },
        },
      }
    

    打包效果如下:

      588.06 KB  build/static/js/vendor2.d63694f4.chunk.js
      133.17 KB  build/static/js/vendor1.0d40234c.chunk.js
      98.72 KB   build/static/js/main.b7a98d03.js
      8.2 KB     build/static/css/2.css
    

    可以看到此时 node_modules 包已经被拆分成了核心模块和非核心模块。

    使用动态引入语法 import()

    首先使用官网安利的 react-loadable 这个包,它的思想是根据路由(代替模块)进行代码的动态分割,异步加载所需要的组件,从而极大地提高页面加载速率。

    在路由界面进行如下配置:

    const Loading = () => <div>Loading...</div>
    
    const Home = Loadable({
      loader: () => import('../pages/home'),
      loading: Loading,
    })
    
    // 类似这样使用路由
    <Router>
      <Route path="/home" component={Home} />
      <Route path="/follow" component={Follow} />
      <Route path="/tools" component={Tools} />
      <Route path="/music" component={Music} />
      <Route path="/todo" component={Todo} />
      <Route path="/album" component={Album} />
      <Route path="/editor" component={Editor} />
      <Route path="/todoList" component={TodoList} />
      <Route path="/searchEngine" component={Search} />
      <Route path="/waterfall" component={Waterfall} /
    </Router>
    

    我们来看代码分割后的结果:

    这里测试结果是去掉方案二的配置后进行的,实验对比后,使用方案三的方式稍优于方案二、三共同使用的方式。

      235.89 KB  build/static/js/IndexJs.57ee1596.js
      225.94 KB  build/static/js/15.c09a5919.chunk.js
      138.18 KB  build/static/js/17.30c26142.chunk.js
      82.71 KB   build/static/js/1.667779a6.chunk.js
      57.55 KB   build/static/js/16.f8fa2302.chunk.js
      16.46 KB   build/static/js/2.e7b77a5d.chunk.js
      14.79 KB   build/static/js/18.cad1f84d.chunk.js
      12.51 KB   build/static/js/0.73df11a7.chunk.js
      11.22 KB   build/static/js/13.19501c58.chunk.js
      8.34 KB    build/static/js/5.33fd1c35.chunk.js
      7 KB       build/static/js/8.9f1d0a47.chunk.js
      5.86 KB    build/static/js/12.24f0a7ec.chunk.js
      5.06 KB    build/static/css/18.css
      4.97 KB    build/static/js/polyfill.1c61a660.js
      3.58 KB    build/static/js/7.dd4976e3.chunk.js
      3.53 KB    build/static/js/14.16f6b811.chunk.js
      3.42 KB    build/static/css/17.css
      2.98 KB    build/static/js/10.464a61e4.chunk.js
      2.02 KB    build/static/js/11.3728d5a9.chunk.js
      1.45 KB    build/static/js/6.92fbac58.chunk.js
      1.13 KB    build/static/js/9.59160a3a.chunk.js
    

    有多少个路由,react-loadable 库就自动帮我们多拆分了多少个包文件。可以想象在越大的项目中,这种动态引人库的好处越明显。

    image

    而且可以很清晰的看到,当我们在 /home 下,只有 home 组件是被加载的,其他组件并没有被加载!

    那么 react-loadable 的神秘之力是如何实现的呢,它本质上是个运用了属性代理的高阶函数,通过在高阶函数里配合 import() 加进各种状态,从而达到异步加载模块的效果。

    参考文献

    code-splitting
    Code-Splitting(react)

  • 相关阅读:
    Neko's loop HDU-6444(网络赛1007)
    Parameters
    SETLOCAL
    RD / RMDIR Command
    devenv 命令用法
    Cannot determine the location of the VS Common Tools folder.
    'DEVENV' is not recognized as an internal or external command,
    How to change Visual Studio default environment setting
    error signing assembly unknown error
    What is the Xcopy Command?:
  • 原文地址:https://www.cnblogs.com/MuYunyun/p/9717094.html
Copyright © 2011-2022 走看看