web-dev-qa-db-fra.com

Comment minimiser la taille du bundle webpack?

J'écris une application Web en utilisant react et webpack comme bundle de modules. Mon code jsx est très léger jusqu'à présent, la taille du dossier entier est de 25 ko.

Ma bundle.js créé à partir de webpack vaut 2,2 Mo cependant. Après avoir exécuté l'optimisation avec le -p drapeau, le paquet est réduit à 700 Ko, ce qui reste extrêmement volumineux.

J'ai examiné le react.min.js fichier de 130 Ko.

Est-il possible que le WebPack génère de si gros fichiers ou est-ce que je fais quelque chose de mal?

webpack.config.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

package.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"
  }
}
55
itaied

Selon vos commentaires, vous utilisez material-ui et react-bootstrap. Ces dépendances sont regroupées par webpack avec vos react et react-dom paquets. Chaque fois que vous require ou import un paquet, il est fourni avec votre fichier bundle.

Et voici ce que je suppose. Vous importez probablement le react-bootstrap et material-ui _ composants utilisant la méthode bibliothèque:

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

C’est pratique et pratique, mais cela ne regroupe pas seulement Button et FlatButton (et leurs dépendances), mais l’ensemble entier bibliothèques.

Une façon de le réduire est d'essayer de ne pas utiliser que import ou require, disons le composant. En utilisant le même exemple:

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

Cela regroupera uniquement Button, FlatButton et leurs dépendances respectives. Mais pas toute la bibliothèque. Je voudrais donc essayer de me débarrasser de toutes vos librairies et utiliser le moyen composant.

Si vous n'utilisez pas beaucoup de composants, la taille de votre fichier fourni devrait être considérablement réduite.

Comme autre explication:

Lorsque vous utilisez les composants library, vous importez tous ces composants réagissent au bootstrap et tous ces composants matériels-ui , quels que soient ceux que vous utilisent réellement.

95
dreyescat

01/2017 EDIT - J'ai depuis appris un peu plus sur les différents plugins Webpack et je voulais le mettre à jour. Il s’avère que glifyJS possède une myriade d’options de configuration qui ne semblent pas très courantes, mais qui peuvent avoir un effet considérable sur la taille de votre paquet. Voici ma config actuelle avec quelques annotations (les documents sur site sont excellents):

 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,
      }
    })

Une fois, j’ai rencontré un problème obscur avec uglify-ication des caractères Unicode échappés. Soyez donc conscient que si vous utilisez ces transformations, il est possible que de tels cas Edge soient possibles.

Vous pouvez en savoir plus sur les options spécifiques webpack prises en charge dans documents sur le webpack avec des liens de suivi pour une lecture plus approfondie.


(Note: Je pense que votre package.json est mélangé ... au moins quelques-unes de ces dépendances de dev sont des dépendances dans chaque package.json que j'ai vu (par exemple, le react-starter-kit )

Si vous vous préparez à la production, vous devez suivre quelques étapes supplémentaires pour réduire la taille de votre fichier. Voici un extrait de mon webpack.config.js:

 plugins: [


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

1) minifie/répugne votre code

2) remplace le code en double pour réduire la taille du fichier

3) indique à Webpack d’omettre certaines choses qu’il utilise pour les versions d’environnement de noeud

Enfin, si vous utilisez une carte source (ce que vous devriez probablement faire), vous voudrez ajouter la ligne appropriée. Sentry a écrit n article de Nice sur ce sujet .

Dans ma construction, j'utilise devtool: 'source-map' pour la production

29
Brandon

PDATED 05/18: mettre à jour le paramètre UglifyJsPlugin pour une meilleure minification

J'utilise la configuration ci-dessous pour la minification en code de production.

 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
    })
  ],
16
Khalid Azam

Avez-vous examiné la manière dont vos scripts sont envoyés sur le réseau filaire ... J'avais quelques composants très simples qui réagissaient jusqu'à environ 300 kb chacun, et cela après l'optimisation du webpack. Après avoir été gzippés, ils sont descendus à 38kb. Toujours considérable - mais c'est ce que nous obtenons aujourd'hui avec les fonctionnalités de demain. Si vous utilisez node/express pour desservir des ressources statiques, y compris votre code javascript, consultez la compression ( https://github.com/expressjs/compression ). Je vous suggérerais également de consulter le guide des meilleures pratiques en matière de production de nœuds pour la production https://expressjs.com/fr/advanced/best-practice-performance.html Si vous ne fournissez pas de fichiers via nœud, alors Apache (ou un autre serveur Web) aura des options pour compresser les fichiers texte.

1
kimmiju

Je trouve utile de mentionner l’utilitaire source-map-Explorer qui aide à savoir ce qui se trouve exactement dans votre fichier bundle.js. Cela peut vous aider à identifier s'il y a des choses inutiles dans le paquet js. vous pouvez installer le source-map-Explorer à partir de npm et l'utiliser comme

source-map-Explorer yourBundle.js

De plus, comme mentionné par @kimmiju, vérifiez si votre serveur utilise une compression.

Network Tab in Chrome

Vous pouvez également essayer de charger de manière asynchrone des routes (chargement différé dans le WebPack), de manière à ce que l'ensemble de votre fichier bundlejs ne soit pas envoyé en une seule fois. en morceaux lorsque l'utilisateur navigue vers ces itinéraires.

0
Rahil Ahmad