• 记解决 `antd is not defined` 解决ant design 打包体积过大的问题


    用 react antd开发了一个页面,最后webpack打包的大小竟然达到了 1.9Mgzip压缩之后也有500kb。

    这超出了能承受的范围,我一个小网站哪有这么大的带宽。

    1. 找原因

    开始的时候并不知道是antd的锅,后来发现了一些工具可以提供UI来分析打包的js的组成部分。比如这个: https://www.npmjs.com/package/webpack-bundle-analyzer

    借助这个工具,我看到了打包的js绝大部分都是antd带来的。我首先确认了我配置了antd官方提供按需加载的,所以应该不是按需加载出了问题。然后经过仔细分析发现主要是下面4个原因:

    icons

    antd的icons占用了很大的部分。原因是正常情况下icons是不会按需加载的,只能全部引用。很多人也遇到这个问题,antd官方给出了一个workaround,稍微有点麻烦,因为你需要自己去找你引用了那些icon:https://github.com/ant-design/ant-design/issues/12011#issuecomment-420038579

    base css

    我的页面基本上只用了一个table,但是antd的css体积也达到了了几百kb。原因是antd的css虽然可以按需加载,但是一些基础的base css是一定会被打包的。这一点没有找到解决方案。

    moment.js

    我自己没有用到moment.js,但是antd用到了moment.js,moment.js也是占用了不小的体积。这个是有一个plugin可以减少moment.js的体积的。原理是让webpack只加载你用到了语言包。插件是:new webpack.ContextReplacementPlugin(/moment[/\]locale$/, /zh-cn/)

    lodash

    同样我没有用到lodash,但是antd用到了。lodash也有一个plugin去减少webpack打包的体积:lodash-webpack-plugin

    2. 使用antd的公共cdn去解决。

    上面分析了antd之所以很大的原因。有些是解决不了的,比如css太大的问题。那么自然就想到了能不能不把antd打包进去,而是在网页中通过cdn引入antd呢?cdn又不走我的网站带宽。答案是可以的,这就是webpack的externals配置。于是我决定使用antd的cdn去解决打包体积太大的问题。

    3. 解决 antd is not defined 问题。

    开始的时候这样做的,在webpack的externals里面只配置了antd

      externals: {
        'antd': 'antd'
      },

    然后在页面引入antd的cdn

    <link rel="stylesheet" href="https://cdn.bootcss.com/antd/3.23.3/antd.min.css">
    <script src="https://cdn.bootcss.com/antd/3.23.3/antd.min.js" type="text/javascript"></script>

    这样做之后,整个打包的体积直接降到了几百kb,不过遗憾的是打开页面出现了 antd is not defined。这个开始也是束手无策,网上并没有搜到好的解决办法。后来找到了原因,不能直接引入antd的cdn,在这之前要把antd依赖的其他资源也加进来。那么antd依赖的哪些呢?首先react和react-dom是必须的。加进来之后,还是有问题。于是再仔细读antd的文档,发现下面的内容:

    支持环境#
    
        现代浏览器和 IE9 及以上(需要 polyfills)。
        强烈不推荐使用已构建文件,这样无法按需加载,而且难以获得底层依赖模块的 bug 快速修复支持。
    
        注意:3.0 之后引入 antd.js 前你需要自行引入 moment。

    吐槽下这个推荐。虽然它强烈不推荐使用已构建文件,但是没办法啊,antd的按需加载做的确实有问题。

    因为我用的3.x 版本,所以还要引入polyfills和moment。加上之后,终于可以了。同时因为webpack去掉了polyfills,react,react-dom,最终的打包体积只剩下了100kb了(gzip压缩前)。

    最终的代码:

      externals: {
        'react': 'React',
        'react-dom': 'ReactDOM',
        'antd': 'antd'
      },
      <link rel="stylesheet" href="https://cdn.bootcss.com/antd/3.23.3/antd.min.css">
      <script src="https://cdn.bootcss.com/babel-polyfill/7.6.0/polyfill.min.js"></script>
      <script src="https://cdn.bootcss.com/react/16.9.0/umd/react.production.min.js"></script>
      <script src="https://cdn.bootcss.com/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
      <script src="https://cdn.bootcss.com/moment.js/2.24.0/moment.min.js"></script>
      <script src="https://cdn.bootcss.com/moment.js/2.24.0/locale/zh-cn.js"></script>
      <script src="https://cdn.bootcss.com/antd/3.23.3/antd.min.js" type="text/javascript"></script>

    最后温馨提示,用cdn最好加上fallback,当cdn不幸挂了的话,换另一家cdn。

    <script>window.antd||document.write('<script src="https://cdnjs.cloudflare.com/ajax/libs/antd/3.23.6/antd.min.js"></script>')</script>
  • 相关阅读:
    CAST和CONVERT
    #pragma 预处理指令详解
    Android系统移植主要事项
    Java动态绑定机制的内幕
    Java接口和抽象类用法总结
    Android工程的编译过程
    点击按钮,并且实现增加一个按钮的效果 (附效果图)
    iOS-设置导航栏"返回"按钮 (附效果图)
    常用代码整理(重要)
    NSTimer 的暂停与恢复运行。
  • 原文地址:https://www.cnblogs.com/yy17yy/p/11626916.html
Copyright © 2020-2023  润新知