【问题标题】:How to further optimize webpack bundle size如何进一步优化 webpack 包大小
【发布时间】:2018-03-12 12:50:33
【问题描述】:

所以我能够将包大小从 13mb 减少到 6.81mb

我做了一些优化,比如正确的生产配置、优化 lodash 等库以及用 date-fns 替换 momentjs。

现在已经到了大多数包不超过 1mb 并且大多数是 npm 安装的依赖项的地步。

使用 webpack-bundle-analyzer 这是我的包现在的样子

那么你们认为我可以做更多的事情来减少捆绑包的大小吗? 也许删除 jquery 并使用 vanilla js?但是它只有 1mb... 我可以做些什么来显着优化大小吗?

如果您愿意,请提供更多详细信息

这就是我的构建方式NODE_ENV=production webpack

const webpack = require('webpack')
const path = require('path')
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const OptimizeCSSAssets = require('optimize-css-assets-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')

const config = {
  entry: ['babel-polyfill', './src/index.js'],
  output: {
    path: path.resolve(__dirname, './public'),
    filename: './output.js'
  },
  resolve: {
    extensions: ['.js', '.jsx', '.json', '.scss', '.css', '.jpeg', '.jpg', '.gif', '.png'], // Automatically resolve certain extensions
    alias: { // Create Aliases
      images: path.resolve(__dirname, 'src/assets/images')
    }
  },
  module: {
    rules: [
      {
        test: /\.js$/, // files ending with js
        exclude: /node-modules/,
        loader: 'babel-loader'
      },
      {
        test: /\.scss$/,
        use: ['css-hot-loader', 'style-loader', 'css-loader', 'sass-loader', 'postcss-loader']
      },
      {
        test: /\.jsx$/, // files ending with js
        exclude: /node-modules/,
        loader: 'babel-loader'
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loaders: [
          'file-loader?context=src/assets/images/&name=images/[path][name].[ext]',
          {
            loader: 'image-webpack-loader',
            query: {
              mozjpeg: {
                progressive: true
              },
              gifsicle: {
                interlaced: false
              },
              optipng: {
                optimizationLevel: 4
              },
              pngquant: {
                quality: '75-90',
                speed: 3
              }
            }
          }
        ],
        exclude: /node_modules/,
        include: __dirname
      }
    ]
  },
  plugins: [
    new ExtractTextWebpackPlugin('styles.css'),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery'
    }),
    // make sure this one with urls is always the last one
    new webpack.DefinePlugin({
      DDP_URL: getDDPUrl(),
      REST_URL: getRESTUrl()
    }),
    new LodashModuleReplacementPlugin({collections: true})
  ],
  devServer: {
    contentBase: path.resolve(__dirname, './public'), // a directory or URL to serve HTML from
    historyApiFallback: true, // fallback to /index.html for single page applications
    inline: true, // inline mode, (set false to disable including client scripts (like live reload))
    open: true // open default browser while launching
  },
  devtool: 'eval-source-map' // enable devtool for bettet debugging experience
}

module.exports = config

if (process.env.NODE_ENV === 'production') {
  module.exports.plugins.push(
    // https://reactjs.org/docs/optimizing-performance.html#webpack
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    }),
    new webpack.optimize.UglifyJsPlugin(),
    new OptimizeCSSAssets(),
    new BundleAnalyzerPlugin()
  )
}

function getDDPUrl () {
  const local = 'ws://localhost:3000/websocket'
  const prod = 'produrl/websocket'
  let url = local
  if (process.env.NODE_ENV === 'production') url = prod
  // https://webpack.js.org/plugins/define-plugin/
  // Note that because the plugin does a direct text replacement,
  // the value given to it must include actual quotes inside of the string itself.
  // Typically, this is done either with either alternate quotes,
  // such as '"production"', or by using JSON.stringify('production').
  return JSON.stringify(url)
}

function getRESTUrl () {
  const local = 'http://localhost:3000'
  const prod = 'produrl'
  let url = local
  if (process.env.NODE_ENV === 'production') url = prod
  // https://webpack.js.org/plugins/define-plugin/
  // Note that because the plugin does a direct text replacement,
  // the value given to it must include actual quotes inside of the string itself.
  // Typically, this is done either with either alternate quotes,
  // such as '"production"', or by using JSON.stringify('production').
  return JSON.stringify(url)
}

【问题讨论】:

  • 你在运行webpack -p 对吗?您是否使用 uglifyjs 插件来删除 cmets?
  • @The.Bear 是的,我添加了我的配置和我使用的命令以获取更多详细信息。
  • 我现在尝试添加{comments: false}。至于生产,是的,我确信它正在进入生产阶段。
  • @The.Bear 所以我添加了它正在进入生产的console.log。传递{output: {comments: false}} 没有任何改变。如果我将它作为true 传递,那么包大小只会增加 0.01mb
  • @The.Bear 不可思议!禁用源映射将包大小从 6mb 减少到仅 900kb!回答问题,以便我接受。

标签: javascript webpack


【解决方案1】:

您的问题是,即使您运行 webpack 生产命令,您也包含了 devtool: 'eval-source-map'。这将包括最终捆绑包中的源映射。因此,要删除它,您可以执行以下操作:

var config = {
  //... you config here
  // Remove devtool and devServer server options from here
}

if(process.env.NODE_ENV === 'production') { //Prod
   config.plugins.push(
       new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('production')}),
       new OptimizeCSSAssets(),
       /* The comments: false will remove the license comments of your libs
       and you will obtain a real single line file as output */
       new webpack.optimize.UglifyJsPlugin({output: {comments: false}}),
   );
} else { //Dev
    config.devServer = {
        contentBase: path.resolve(__dirname, './public'), 
        historyApiFallback: true, 
        inline: true,
        open: true
    };
    config.devtool = 'eval-source-map'; 
}

module.exports = config

【讨论】:

    猜你喜欢
    • 2016-03-18
    • 2022-12-25
    • 2018-05-29
    • 2015-09-27
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多