javascript - Porque é que o meu bundle do Webpack é tão grande?


Estou a escrever algum JavaScript que usa Moment.js e Handlebars. Supõe-se que o Moment.js tenha 30 KB comprimido com gzip e que o Handlebars tenha menos de 10 KB comprimido com gzip. Mas quando uso o Webpack para empacotar o meu código, obtenho um ficheiro resultante de 271 KB!

Instalei o webpack-bundle-size-analyzer para investigar e encontrei ficheiros muito maiores do que o esperado:

webpack --json | webpack-bundle-size-analyzer
moment: 454.54 KB (74.1%)
handlebars: 94.39 KB (15.4%)
twitter-text: 62.3 KB (10.2%)
<self>: 1.94 KB (0.317%)

Tenho a sensação de que estou a fazer algo que está a causar o carregamento de muitas coisas desnecessárias, uma vez que esperava um tamanho final de ficheiro <100 KB.

main.js

var template = require('./template.handlebars')
var Handlebars = require('handlebars/runtime')
var twitter = require('twitter-text')
var moment = require('moment')

webpack.config.js

var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: './src/main.js',

  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'bundle.min.js'
  },

  resolveLoader: {
    root: path.join(__dirname, 'node_modules')
  },

  module: {
    loaders: [
      {
        test: /\.handlebars$/,
        loader: 'handlebars-loader'
      }
    ]
  },

  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
}

Resposta #1

Atualização em 10 de agosto

Pode referir-se a este problema no github/moment. Basicamente, pode eliminar todas as outras localidades de que não precisa.

Extrato dos comentários:

plugins: [
    new webpack.ContextReplacementPlugin(/moment["/]locale$/, /^\.\/(en|zh-tw)$/)
]

Acho que o webpack já fez o seu melhor. Quando olhas para os ficheiros em node_modules/moment/min/

Você verá isto:

220K  moment-with-locales.min.js
 57K  moment.min.js

Portanto, se incluir o momento com locais, 2XXKB faz sentido. Para reduzir ainda mais o tamanho, pode tentar

  1. incluir o momento sem locais explicitamente

    var moment = require('moment/min/moment.min')
    // if you dun need the locale support
    
  2. Ou então pode tentar comprimir a sua saída manualmente com gz usando este plugin compression-webpack-plugin.

Resposta #2

Adicione IgnorePlugin no ficheiro webpack.config.js e import locale/xx o que precisar.

Ler mais: https://webpack.js.org/plugins/ignore-plugin/

const webpack = require('webpack')
new webpack.IgnorePlugin({
  resourceRegExp: /^\.\/locale$/,
  contextRegExp: /moment$/,
});