Как минимизировать размер пакета webpack?


Я пишу веб-приложение с помощью react и webpack как мой модуль bundler. Мой jsx код действительно легкий до сих пор, размер всей папки составляет 25 КБ.

мой bundle.js создан из webpack - в 2,2 Мб хоть. После запуска оптимизации с помощью -p флаг, он уменьшает пакет до 700kb, который по-прежнему очень большой.

Я заглянул в react.min.js файл и его размер составляет 130 КБ.

возможно ли, что webpack производит такой большой файлы или я делаю что-то не так?

webpack.конфиг.js

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

module.exports = {
  entry: './public/components/main.jsx',
  output: {
    path: __dirname + "/public",
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /.jsx?$/,
      loader: 'babel-loader',
      exclude: /node_modules/,
      query: {
        presets: ['es2015', 'react']
      }
    }, {
      test: /\.css$/,
      loader: "style!css"
    }]
  }
};

EDIT

пакета.json:

{
  "name": "XChange",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "main": "./bin/www",
  "devDependencies": {
    "body-parser": "~1.13.2",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "express": "~4.13.1",
    "jade": "~1.11.0",
    "morgan": "~1.6.1",
    "serve-favicon": "~2.3.0",
    "react-dom": "~0.14.3",
    "react": "~0.14.3",
    "webpack": "~1.12.9",
    "babel-loader": "~6.2.0",
    "babel-core": "~6.2.1",
    "babel-preset-react": "~6.1.18",
    "babel-preset-es2015": "~6.1.18",
    "react-bootstrap": "~0.28.1",
    "material-ui": "~0.14.0-rc1",
    "history": "~1.13.1",
    "react-router": "~1.0.2",
    "style-loader": "~0.13.0",
    "css-loader": "~0.18.0"
  },
  "dependencies": {
    "express-validator": "~2.18.0",
    "mongoose": "~4.2.9",
    "kerberos": "~0.0.17",
    "bcrypt": "~0.8.5"
  }
}
5   51   2015-12-12 15:15:15

5 ответов:

по Вашим комментариям вы используете material-ui и react-bootstrap. Эти зависимости в комплекте с webpack вместе с вашим react и react-dom пакеты. В любое время вы require или import пакет он входит в комплект как часть вашего файла пакета.

и вот оно мое предположение. Вы, вероятно, импортируете react-bootstrap и material-ui компоненты с помощью библиотека путь:

import { Button } from 'react-bootstrap';
import { FlatButton } from 'material-ui';

это приятно и удобно, но это не только пучки Button и FlatButton (и их зависимости), но весь библиотеки.

один из способов исправить это, чтобы попытаться только import или require что нужно, скажем,компонент путь. Используя тот же пример:

import Button from 'react-bootstrap/lib/Button';
import FlatButton from 'material-ui/lib/flat-button';

это будет только пакет Button,FlatButton и их соответствующие зависимости. Но не всю библиотеку. Так что я постараюсь избавиться от всех ваших библиотека импорт и использовать компонент путь вместо.

если вы не используете много компонентов, то это должно значительно уменьшить размер вашего файла в комплекте.

а далее объяснения:

когда вы используете библиотека как вы импортируете все эти react-bootstrap и все эти материалы-ui компоненты, независимо от того, какие из них вы используете.

01/2017 EDIT - С тех пор я узнал немного больше о различных плагинах Webpack и хотел обновить это. Оказывается, что UglifyJS имеет небольшое количество опций конфигурации, которые, похоже, не очень распространены, но могут оказать значительное влияние на размер вашего пакета. Это моя текущая конфигурация с некоторыми аннотациями (документы на сайте отличные):

 new webpack.optimize.UglifyJsPlugin({
      comments: false, // remove comments
      compress: {
        unused: true,
        dead_code: true, // big one--strip code that will never execute
        warnings: false, // good for prod apps so users can't peek behind curtain
        drop_debugger: true,
        conditionals: true,
        evaluate: true,
        drop_console: true, // strips console statements
        sequences: true,
        booleans: true,
      }
    })

однажды я столкнулся с неясной проблемой с uglify - ication экранированных символов Юникода, так что помните, что если вы используете эти преобразования, то такие крайние случаи возможны.

вы можете прочитать больше о конкретных вариантах webpack поддерживает в webpack docs С некоторыми последующими ссылками для дальнейшего чтения.


(примечание: Я думаю, что ваш пакет.JSON-это смесь... по крайней мере, некоторые из этих dev-зависимостей являются зависимостями в каждом пакете.json я видел (например,react-starter-kit)

если вы подготовка к производству, есть еще несколько шагов, которые вы должны предпринять, чтобы получить размер файла вниз. Вот фрагмент моего веб-пакета.конфиг.js:

 plugins: [


        new webpack.optimize.UglifyJsPlugin(),
        new webpack.optimize.DedupePlugin(),
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': JSON.stringify('production')
            }
        })
    ],

1) уменьшает / уродует ваш код

2) заменяет дубликат кода для минимизации размера файла

3) говорит webpack опустить некоторые вещи, которые он использует для сборки среды узла

наконец, если вы используете исходную карту (что, вероятно, следует), вы захотите добавить соответствующую строку. Часовой написал хороший пост в блоге об этом.

в моей сборке, я использую devtool: 'source-map' для производства

обновлено 05/18 : обновление UglifyJsPlugin настройки для лучшего минимизации

Я использую ниже конфигурацию для минимизации в производственном коде.

 plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        // This has effect on the react lib size
        'NODE_ENV': JSON.stringify('production'),
      }
    }),
    new ExtractTextPlugin("bundle.css", {allChunks: false}),
    new webpack.optimize.AggressiveMergingPlugin(),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      mangle: true,
      compress: {
        warnings: false, // Suppress uglification warnings
        pure_getters: true,
        unsafe: true,
        unsafe_comps: true,
        screw_ie8: true,
        conditionals: true,
        unused: true,
        comparisons: true,
        sequences: true,
        dead_code: true,
        evaluate: true,
        if_return: true,
        join_vars: true
      },
      output: {
        comments: false,
      },
      exclude: [/\.min\.js$/gi] // skip pre-minified libs
    }),
    new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), 
    new CompressionPlugin({
      asset: "[path].gz[query]",
      algorithm: "gzip",
      test: /\.js$|\.css$|\.html$/,
      threshold: 10240,
      minRatio: 0
    })
  ],

вы смотрели на то, как вы скрипты отправляются по проводу... У меня было несколько очень простых компонентов react, которые были около 300 КБ каждый, и это было после оптимизации webpack. После того, как они были gzipped они спустились до 38kb. Все еще значительный - но это то, что мы получаем за использование функций tomorrows сегодня. Если вы используете node / express для обслуживания статических ресурсов, включая ваш javascript-посмотрите на сжатие (https://github.com/expressjs/compression). Я бы тоже предложите посмотреть руководство по передовой практике узла для производства https://expressjs.com/en/advanced/best-practice-performance.html Если вы не обслуживаете файлы через узел, то apache (или другой веб-сервер) будет иметь параметры для сжатия текстовых файлов.

Я считаю полезным упомянуть утилиту source-map-explorer, которая помогает узнать, что именно находится в вашем пакете.js файл. Это может помочь вам определить, есть ли какие-либо ненужные вещи в bundle js. вы можете установить source-map-explorer из npm и использовать его как

source-map-explorer yourBundle.js

кроме того , как упоминалось @kimmiju, проверьте, использует ли ваш сервер некоторое сжатие.

Network Tab in Chrome

вы также можете попробовать асинхронно загрузить маршруты (ленивая загрузка в webpack), так что весь ваш файл bundlejs не отправляется за один раз, вместо этого он отправляется кусками, когда пользователь переходит к этим маршрутам.