文档章节

记一次webpack4+react+antd项目优化打包文件体积的过程

o
 osc_y8yehimr
发布于 2019/03/20 18:34
字数 1172
阅读 110
收藏 0

「深度学习福利」大神带你进阶工程师,立即查看>>>

背景

  最近自己整了一个基于webpack4和react开发的博客demo项目,一路整下来磕磕碰碰但也实现了功能,就准备发到阿里云上面去看看,借用了同事的阿里云小水管服务器,配置完成之后首页加载花了十几秒,打开控制台network查看资源,打包的js体积有将近6M,及其影响访问体验,于是就开始了优化的路。

 

原因和解决方法

  在webpack的配置文件中,对公共js做了抽取,分别会打包出react-verdor.js和antd-verdor.js,优化前的antd-verdor足足有4m大小,估计是把antd组件全部加载下来了,顺着这个思路查找解决方案。

optimization.splitChunks: {
      chunks: 'all',
      cacheGroups: {
        "react-vendor": {
          test: (module) => (/react/.test(module.context) || /redux/.test(module.context)
            || /classnames/.test(module.context) || /prop-types/.test(module.context)),
          priority: 3,
          reuseExistingChunk: false
        },
        "antd-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/antd/.test(module.context)),
          priority: 2,
          reuseExistingChunk: false
        },

      }
    }

 

antd官方推荐按需加载,我开始也是根据官方推荐做的,在.babelrc做如下配置

{
  "plugins": [
    ["import", {
      "libraryName": "antd",
      "libraryDirectory": "es",
      "style": "css"
    }]
  ]
}

不过事实是打包文件有4M,那肯定是配置错了,继续查找别的配置方法,终于找到一个管用的,在webpack配置文件中做如下配置(本质上还是自己太菜,不理解.babelrc)

{
        test: /\.(js|jsx)/,
        use: {
          loader:'babel-loader',
          options: {
            presets: ["env", "react", 'stage-0'],
            plugins: [
              ['import', [{ libraryName: 'antd', style: true }]]
            ]
          }
        },
        include: resolve('src')
      },

配置完成后进行打包,体积明显变小了,antd-vendor.js的大小变成200多K。antd按需引入的问题解决后,看别的文件还是挺大的,于是决定把REACT中的组件也做成按需加载的方式,拆分更多的js出来,这里使用了react-loadable实现,拆分完成之后继续打包,发现部分子js的体积明显过大,继续查找原因。

在浏览器中跳转到对应的页面查看加载的js,查看js文件中的注释,发现有两个第三方插件被我全部import进来了了,其实我永不到那么多,分别是

crypto和highlightjs,crypto是一个加密算法库,提供md5和sha 256等经典加密算法,我这个项目中只在登录时用到了一次加密密码,而那个页面对应的js有500多k,问题显而易见,通过下面这个修改把问题解决了
//修改前

import crypto from ('crypto')

module.exports = {
    MD5_SUFFIX: 'sskjtxdywdddzyjknn',
    md5: function (pwd) {
        let md5 = crypto.createHash('md5');
        return md5.update(pwd).digest('hex')
      
    },
}

//修改后

const md5 = require("crypto-js/md5")

module.exports = {
    MD5_SUFFIX: 'sskjtxdywdddzyjknn',
    md5: function (pwd) {

        return md5.update(pwd).digest('hex')
    },
}

 

解决引入highlightjs后文件的过大的的思路和上面类似,我选择了直接加载hightlightjs保留核心功能后的压缩代码,size只有30k,而之前的默认import后的size有将近1M

 

还能优化吗

前面发现的问题不外乎是由第三方库造成的,解决了前面的问题后,此时的js体积已经从之前的6M降到1.8M了。那么还能继续通过webpack配置来优化打包后的文件大小吗?抱着这个疑问继续查找解决方案,最后决定试一试这个文章说明的方法 

https://zhuanlan.zhihu.com/p/36280323

一顿操作下来打包出来的文件只减小了30K,最后再放上配置文件js的完整代码,希望能有大佬提出建议,非常

//webpack.base.config.js

module.exports = {

  /*entry: {
    app: './src/index.jsx',
  },*/
  output: {
    publicPath: process.env.NODE_ENV === config.prod.ENV
      ? config.prod.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.jsx', '.json'],
    alias: {
      '@components': path.resolve(__dirname, '../src/components'),
      '@': resolve('src'),

    }
  },

  module: {
    rules: [
      {
        test: /\.(js|jsx)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ["env", "react", 'stage-0'],
            plugins: [
              ['import', [{ libraryName: 'antd', style: true }]]
            ]
          }
        },
        include: resolve('src')
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: assetsPath('img/[name].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: assetsPath('media/[name].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: assetsPath('font/[name].[ext]')
        }
      },
      {
        test: /\.css$/,

        use: [{
          loader: 'style-loader'
        }, {
          loader: "css-loader",
          options: {
            name: "[path][name].[ext]",

          }
        }]
      },
      {
        test: /\.less$/,
        exclude: /node_modules/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader',
        ]
      },
      {
        test: /\.less$/,
        include: /node_modules/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            'loader': 'less-loader',
            options: {
              javascriptEnabled: true
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css'

    }),
    new LodashModuleReplacementPlugin
  ]
}

//webpack.prod.config.js

const webpackConfig = merge(baseWebpackConfig, {
  entry: {
    app: './src/index.jsx',
  },

  mode: 'production',
  devtool: false,
  output: {
    path: config.prod.assetsRoot,
    filename: assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: assetsPath('js/[name].[chunkhash].js'),
  },
  plugins: [

    new HtmlWebpackPlugin({
      filename: 'index.html',
      title: pkg.description,
      template: path.resolve(__dirname, '../index.html'),
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
      },
    }),
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../src/static'),
        to: config.prod.assetsSubDirectory,
      }
    ])
  ],
  optimization: {
    minimizer: [
      new UglifyJsPlugin(),
      new OptimizeCSSAssetsPlugin(),
      new TerserPlugin({
        terserOptions: {
          parse: {

            ecma: 8,
          },
          compress: {
            ecma: 5,
            warnings: false,

            comparisons: false,

            inline: 2,
          },
          mangle: {
            safari10: true,
          },
          output: {
            ecma: 5,
            comments: false,

            ascii_only: true,
          },
        },
        // Use multi-process parallel running to improve the build speed
        // Default number of concurrent runs: os.cpus().length - 1
        parallel: true,
        // Enable file caching
        cache: true,
        sourceMap: false,
      }),
    ],
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        "react-vendor": {
          test: (module) => (/react/.test(module.context) || /redux/.test(module.context)
            || /classnames/.test(module.context) || /prop-types/.test(module.context)),
          priority: 3,
          reuseExistingChunk: false
        },
        "antd-vendor": {
          // || /[\\/]node_modules[\\/]/.test(module.context)
          test: (module) => (/antd/.test(module.context)),
          priority: 2,
          reuseExistingChunk: false
        },

      }
    }

  }
})

 

感谢!

 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
记一次失败的Perl + Nginx + FastCGI 配置过程

这两天心血来潮,不知道为什么和 Perl + Nginx + FastCGI 配置 耗上了。但是失败了,记录如下: 1)安装Nginx 1.4.3 ,我的是WINDOWS 7 系统,修改配置文件如下: location ~ .(pl|cgi|perl)?...

通吃岛-低手哥
2013/10/27
1.7K
7
Flappy Bird(安卓版)逆向分析(一)

更改每过一关的增长分数 反编译的步骤就不介绍了,我们直接来看反编译得到的文件夹 方法1:在smali目录下,我们看到org/andengine/,可以知晓游戏是由andengine引擎开发的。打开/res/raw/at...

enimey
2014/03/04
6.1K
18
浅入浅出Android(003):使用TextView类构造文本控件

基础: TextView是无法供编辑的。 当我们新建一个项目MyTextView时候,默认的布局(/res/layout/activity_main.xml)中已经有了一个TextView: <TextView 运行效果如下: 修改其文本内容...

樂天
2014/03/22
685
1
5分钟 maven3 快速入门指南

前提条件 你首先需要了解如何在电脑上安装软件。如果你不知道如何做到这一点,请询问你办公室,学校里的人,或花钱找人来解释这个给你。 不建议给Maven的服务邮箱来发邮件寻求支持。 安装Mav...

fanl1982
2014/01/23
1.2W
7
代码生成器--Codgen

Codgen是一个基于数据库元数据模型,使用freemarker模板引擎来构建输出的代码生成器。freemarker的数据模型结构通常来说都是一个Map树状结构模型,codgen也不例外,它的数据模型这棵树的根节...

黄天政
2013/01/29
1.4W
2

没有更多内容

加载失败,请刷新页面

加载更多

程序员职场:拥有一个学位将会在你的职业生涯中更加顺利!

1、作为程序员为什么要拥有学位? 很多情况下,作为程序员,学位是进入大公司的敲门砖。 现在很多大的科技公司,学位是硬性要求。 一般都是本科以上的学历,甚至有的必须是硕士以上学历。 如...

IT技术分享社区
03/03
12
0
varchar和nvarchar有什么区别? - What is the difference between varchar and nvarchar?

问题: Is it just that nvarchar supports multibyte characters? 只是nvarchar支持多字节字符吗? If that is the case, is there really any point, other than storage concerns, to us......

技术盛宴
42分钟前
12
0
用flutter给图片加个好看的遮罩层【flutter20个实例之六】

一、老套路,先看样式 左起图一是我业务中的样式,左起图二、三是下方源码展示样式(复制可直接运行,无额外组件引入) 二、讲解 1.结构拆分 我们先看下页面布局结构,首先肯定是有个GridVie...

一代码农码一代
43分钟前
17
0
世界上最美的瀑布在这里,太美了!

亲近大自然,高山流水遇知音,倾听心灵的声音。。。 声明:文章及图片、视频来自网络,如有版权方面的疑问请和我们联系,我们将在24小时内删除。 本文分享自微信公众号 - Python提升课堂(DJXY0...

花儿开放
2014/08/17
0
0
商城小程序制作流程

随着商城小程序的火爆,很多商家都迫不及待的想制作商城小程序,下面就和大家分享一下商城小程序制作流程? 第1步: 注册并认证小程序账号 注册并认证小程序账号,打开百度搜索,“微信公众平...

木鱼小铺小程序1
53分钟前
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部