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

背景

  最近自己整了一个基于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
        },

      }
    }

  }
})

感谢!

原文地址:https://www.cnblogs.com/haimianxiubaobao/p/10566799.html

时间: 2024-10-07 11:42:56

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

【React Native开发】React Native进行签名打包成Apk

转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/50525976 本文出自:[江清清的博客] (一)前言 [好消息]个人网站已经上线运行,后面博客以及技术干货等精彩文章会同步更新,请大家关注收藏:http://www.lcode.org 前几节课程我们对于React Native的一些基础配置,开发工具以及调试,Android项目移植做了相关讲解,今天一起来学习一下另外一个比较重要的知识点,就是React Nativ

Springboot + mybatis + React+redux+React-router+antd+Typescript(二): React+Typescrip项目的搭建

前言: 后台搭建完以后开始搭建前端,使用create-react-app搭建项目非常方便. 前端主要是如何向后台请求数据,以及如何使用redux管理state,路由的配置. 前端github地址: https://github.com/www2388258980/rty-web 后台github地址: https://github.com/www2388258980/rty-service 项目访问地址:          http://106.13.61.216:5000/          

webpack+react+antd 单页面应用实例

webpack+react+antd 单页面应用实例 React框架已经火了好长一段时间了,再不学就out了! 对React还没有了解的同学可以看看我之前的一篇文章,可以快速简单的认识一下React.React入门最好的实例-TodoList 自己从开始接触react一窍不通,到慢慢的似懂非懂,通过各种途径学习也有一阵了.学习过程中还会接触到很多新的东西,比如ES6.webpack,过程艰辛谁人懂,见坑填坑慢慢来.今天把学习过程过滤了一下,只说项目实际需要用的东西,总结了一套能看到的东西,分享给

Rails + React +antd + Redux环境搭建

前提条件:node和ruby on rails必须已经安装好(相关安装流程不再此处介绍) 1.nvm.node 2.npm or yarn装一个就好 3.rvm.ruby on rails 4.foreman 一.新建一个rails项目后加入react gem包 1.Gemfile文件添加gem 'react_on_rails', '~>6' # use latest gem version > 62.bundle install安装gem包3.rails generate react_on_

【腾讯Bugly干货分享】React Native项目实战总结

本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 "8小时内拼工作,8小时外拼成长"这是大家共同的理想.除了每天忙于工作外,我们都希望能更多地区吸收领域内的新知识与新技能,从而走向人生巅峰. Dev Club 是一个交流移动开发技术,结交朋友,扩展人脉的社群,成员都是经过审核的移动开发工程师.每周都会举行嘉宾分享,话题讨论等活动. 上一期我们邀请了腾讯SNG工程师&qu

React 实践项目 (五)

React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! React 实践项目 (一)React 实践项目 (二)React 实践项目 (三)React 实践项目 (四)React 实践项目 (五) 这次我们把应用部署到服务器上. 项目到现在麻雀虽小五脏俱全,为了提高我们写代码的积极性,自然是选择部署到服务器上在小伙伴面前秀一波了.部署 React 应用也是非常方便简单的. 打包应

深入浅出的webpack4构建工具--webpack4+react构建环境(二十)

下面我们来配置下webpack4+react的开发环境,之前都是针对webpack4+vue的.下面我们也是在之前项目结构的基础之上进行配置下. 首先看下如下是我为 webpack4+react 基本的项目结构如下: ### 目录结构如下: demo1 # 工程名 | |--- dist # 打包后生成的目录文件 | |--- node_modules # 所有的依赖包 | |--- app | | |---src | | | |-- index.jsx # 项目的入口文件jsx | | | |

【webpack系列】从零搭建 webpack4+react 脚手架(二)

html文件如何也同步到dist目录?bundle.js文件修改了,万一被浏览器缓存了怎么办?如何为导出的文件加md5?如何把js引用自动添加到html?非业务代码和业务代码如何分开打包?如何搭建开发环境?如何实现开发环境的热更新? 在上一节我们已经搭建了一个最基本的webpack环境, 这一节我们带着上节的一些疑问,继续优化我们的react工程. 1.整合html-webpack-plugin public的index.html应该自动编译到dist目录,并且所有的js引用是自动添加的.你可以

react + antd mobile + postcss

在搭建完之后 => 搭建教程 https://www.cnblogs.com/safeold/p/10581295.html 2019年3月28日 , 今天搜react + antd mobile 高清方案, 结果搜出来的全是修改 webpack.config.dev.js文件的 然鹅新版的cra(create-react-app) 生成的项目 只有一个 webpack.config.js 了,根本没有什么dev , prod 所以我就整合了一哈,搞了一个新版的 搭建完项目之后 npm run