Webpack comment créer du code de production et comment l'utiliser

95

Je suis très nouveau dans Webpack, j'ai trouvé que dans la version de production, nous pouvons réduire la taille du code global. Actuellement, Webpack génère environ 8 Mo de fichiers et main.js environ 5 Mo. Comment réduire la taille du code en production? J'ai trouvé un exemple de fichier de configuration Webpack sur Internet et j'ai configuré pour mon application et je l'ai exécuté npm run buildet sa construction a commencé et il a généré des fichiers dans le ./dist/répertoire.

  1. Pourtant, ces fichiers sont lourds (comme la version de développement)
  2. Comment utiliser ces fichiers? Actuellement, j'utilise webpack-dev-server pour exécuter l'application.

fichier package.json

{
  "name": "MyAPP",
  "version": "0.1.0",
  "description": "",
  "main": "src/server/server.js",
  "repository": {
    "type": "git",
    "url": ""
  },
  "keywords": [
  ],
  "author": "Iam",
  "license": "MIT",
  "homepage": "http://example.com",
  "scripts": {
    "test": "",
    "start": "babel-node src/server/bin/server",
    "build": "rimraf dist && NODE_ENV=production webpack --config ./webpack.production.config.js --progress --profile --colors"
  },
  "dependencies": {
    "scripts" : "", ...
  },
  "devDependencies": {
    "scripts" : "", ...
  }
}

webpack.config.js

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var public_dir = "src/frontend";
var ModernizrWebpackPlugin = require('modernizr-webpack-plugin');

module.exports = {
  devtool: 'eval-source-map',
  entry: [
    'webpack-hot-middleware/client?reload=true',
    path.join(__dirname, public_dir , 'main.js')
  ],
  output: {
    path: path.join(__dirname, '/dist/'),
    filename: '[name].js',
    publicPath: '/'
  },
  plugins: [
    plugins
  ],
  module: {
    loaders: [loaders]
  }
};

webpack.production.config.js

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var public_dir = "src/frontend";
var ModernizrWebpackPlugin = require('modernizr-webpack-plugin');
console.log(path.join(__dirname, 'src/frontend' , 'index.html'));

module.exports = {
  devtool: 'eval-source-map',
  entry: [
    'webpack-hot-middleware/client?reload=true',
    path.join(__dirname, 'src/frontend' , 'main.js')
  ],
  output: {
    path: path.join(__dirname, '/dist/'),
    filename: '[name].js',
    publicPath: '/'
  },
  plugins: [plugins],
  resolve: {
    root: [path.resolve('./src/frontend/utils'), path.resolve('./src/frontend')],
    extensions: ['', '.js', '.css']
  },

  module: {
    loaders: [loaders]
  }
};
Gilson PJ
la source
1
Avez-vous trouvé une réponse à votre dernière question? "Comment utiliser ces fichiers? Actuellement, j'utilise webpack-dev-server pour exécuter l'application."
Randy
4
Internet était tellement meilleur avant le webpack, il suffit de regarder cette question et la réponse.
Randy L

Réponses:

66

Vous pouvez ajouter les plugins comme suggéré par @Vikramaditya. Ensuite, pour générer la version de production. Vous devez exécuter la commande

webpack -p --config ./webpack.production.config.js

Le -pWebpack indique qu'il doit générer une version de production. Vous devez modifier le script de construction dans package.json pour inclure l'indicateur de production.

sandeep
la source
6
OK merci. mon prochain doute est de savoir comment exécuter le code de production? lorsque j'exécute la commande ci-dessus, il crée des fichiers dans le répertoire dist. ok il a été compilé avec succès. maintenant comment utiliser ces fichiers? en mode de développement, j'ai utilisé «npm start» et il a commencé.
Gilson PJ
Si vous allez à votre src/server/bin/server. Ensuite, vous pouvez comprendre comment il sert les fichiers et peut-être le modifier. Ce que je pense qu'il va faire, c'est exécuter webpack pour créer des fichiers et les servir. Jetez un œil au code de ce fichier.
sandeep
@Vikramaditya Pourriez-vous m'aider avec le scénario dans stackoverflow.com/questions/40993795/msbuild-and-webpack
lohiarahul
@GilsonPJ avez-vous compris comment utiliser ces fichiers d'interface utilisateur?
Randy
Vous devez d'abord installer webpack en utilisantnpm install webpack
Peter Rader
43

Après avoir observé le nombre de téléspectateurs à cette question, j'ai décidé de conclure une réponse de Vikramaditya et Sandeep.

Pour construire le code de production, la première chose que vous devez créer est la configuration de production avec des packages d'optimisation comme,

  new webpack.optimize.CommonsChunkPlugin('common.js'),
  new webpack.optimize.DedupePlugin(),
  new webpack.optimize.UglifyJsPlugin(),
  new webpack.optimize.AggressiveMergingPlugin()

Ensuite, dans le fichier package.json, vous pouvez configurer la procédure de construction avec cette configuration de production

"scripts": {
    "build": "NODE_ENV=production webpack --config ./webpack.production.config.js"
},

maintenant vous devez exécuter la commande suivante pour lancer la construction

npm run build

Selon ma configuration de construction de production, Webpack construira la source dans le ./distrépertoire.

Maintenant, votre code d'interface utilisateur sera disponible dans l' ./dist/annuaire. Configurez votre serveur pour servir ces fichiers en tant qu'actifs statiques. Terminé!

Gilson PJ
la source
7
Que voulez-vous dire dans votre dernière phrase? Comment fournir ces codes? Je sais que node.js construit un serveur en lui-même. Mais comment puis-je l'exécuter après avoir le fichier dans le ./dist/répertoire?
newguy
6
Juste une note, l'ajout de l'option -p au-dessus du plugin uglifyJS pose des problèmes car il tente de uglify deux fois. La suppression de l'option -p cli a résolu ces problèmes pour moi
timelf123
'NODE_ENV' n'est pas reconnu comme une commande interne ou externe, un programme utilisable ou un fichier de commandes.
Anton Duzenko
2
Cela devrait être la réponse acceptée, car personne ne disait comment servir le site Web. Maintenant, votre code d'interface utilisateur sera disponible dans le répertoire ./dist/. Configurez votre serveur pour qu'il fournisse ce code d'interface utilisateur pour la demande. et vous avez terminé.!
jperelli
2
Je ne comprends toujours pas comment "Configurer votre serveur pour fournir ces codes d'interface utilisateur pour la demande. Et vous avez terminé.". Je comprends ce que nous voulons faire ici mais je ne sais tout simplement pas comment le faire
Randy
42

Utilisez ces plugins pour optimiser votre version de production:

  new webpack.optimize.CommonsChunkPlugin('common'),
  new webpack.optimize.DedupePlugin(),
  new webpack.optimize.UglifyJsPlugin(),
  new webpack.optimize.AggressiveMergingPlugin()

J'ai récemment découvert le plugin compression-webpack-plugin qui gzips votre bundle de sortie pour réduire sa taille. Ajoutez-le également dans la liste des plugins listés ci-dessus pour optimiser davantage votre code de production.

new CompressionPlugin({
      asset: "[path].gz[query]",
      algorithm: "gzip",
      test: /\.js$|\.css$|\.html$/,
      threshold: 10240,
      minRatio: 0.8
})

La compression gzip dynamique côté serveur n'est pas recommandée pour servir des fichiers statiques côté client en raison d'une utilisation intensive du processeur.

Vikramaditya
la source
1
que fait la partie 'common.js' sur commonschuckplugin? ce plugin est facilement le plus difficile à saisir pour moi.
Echiban
2
CommonsChunkPlugin extrait le code commun de tous vos morceaux et le place dans un fichier séparé common.js.
Vikramaditya
3
Cette réponse n'est plus valable pour la version 4 du webpack
Dennis
20

J'apprends ça moi-même. Je vais répondre à la deuxième question:

  1. Comment utiliser ces fichiers? Actuellement, j'utilise webpack-dev-server pour exécuter l'application.

Au lieu d'utiliser webpack-dev-server, vous pouvez simplement lancer un "express". utilisez npm install "express" et créez un server.js dans le répertoire racine du projet, quelque chose comme ceci:

var path = require("path");
var express = require("express");

var DIST_DIR = path.join(__dirname, "build");
var PORT = 3000;
var app = express();

//Serving the files on the dist folder
app.use(express.static(DIST_DIR));

//Send index.html when the user access the web
app.get("*", function (req, res) {
  res.sendFile(path.join(DIST_DIR, "index.html"));
});

app.listen(PORT);

Ensuite, dans le package.json, ajoutez un script:

"start": "node server.js"

Enfin, lancez l'application: npm run startpour démarrer le serveur

Un exemple détaillé peut être vu sur: https://alejandronapoles.com/2016/03/12/the-simplest-webpack-and-express-setup/ (l'exemple de code n'est pas compatible avec les derniers packages, mais cela fonctionnera avec de petits ajustements)

Siyuan Jiang
la source
2
Si vous avez commencé à apprendre des choses sur nodejs, expressjs, etc., je veux vous le dire. Cette question est une question de niveau avancé. Ce n'est pas seulement pour comment exécuter ces fichiers. C'est pour Comment minimiser (compresser) le code de production et comment exécuter ce code compressé
Arpit
1
@Arpit Merci de l'avoir signalé. Je suis très nouveau dans ce domaine. J'ai supposé qu'une fois le code compressé généré, la méthode en cours d'exécution devrait être la même.
Siyuan Jiang
9

Vous pouvez utiliser le module argv npm (installez-le en exécutant npm install argv --save ) pour obtenir des paramètres dans votre fichier webpack.config.js et comme pour la production, vous utilisez -p flag "build": "webpack -p" , vous pouvez ajouter une condition dans le fichier webpack.config.js comme ci-dessous

plugins: [
    new webpack.DefinePlugin({
        'process.env':{
            'NODE_ENV': argv.p ? JSON.stringify('production') : JSON.stringify('development')
        }
    })
]

Et c'est tout.

Hayk Aghabekyan
la source
1
Utilisez plutôtprocess.argv.indexOf('-p') != -1
AjaxLeung
@AjaxLeung: vous devez inclure argvdans le fichier de configuration du webpack:const argv = require('argv');
kadam
6

Cela vous aidera.

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
      },
      output: {
        comments: false,
      },
      exclude: [/\.min\.js$/gi] // skip pre-minified libs
    }),
    new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), ///programming/25384360/how-to-prevent-moment-js-from-loading-locales-with-webpack
    new CompressionPlugin({
      asset: "[path].gz[query]",
      algorithm: "gzip",
      test: /\.js$|\.css$|\.html$/,
      threshold: 10240,
      minRatio: 0
    })
  ],
Khalid Azam
la source
5

En plus de la réponse de Gilson PJ:

 new webpack.optimize.CommonsChunkPlugin('common.js'),
 new webpack.optimize.DedupePlugin(),
 new webpack.optimize.UglifyJsPlugin(),
 new webpack.optimize.AggressiveMergingPlugin()

avec

"scripts": {
    "build": "NODE_ENV=production webpack -p --config ./webpack.production.config.js"
},

car il essaie de modifier votre code deux fois. Voir https://webpack.github.io/docs/cli.html#production-shortcut-p pour plus d'informations.

Vous pouvez résoudre ce problème en supprimant UglifyJsPlugin de plugins-array ou en ajoutant OccurrenceOrderPlugin et en supprimant le drapeau "-p". donc une solution possible serait

 new webpack.optimize.CommonsChunkPlugin('common.js'),
 new webpack.optimize.DedupePlugin(),
 new webpack.optimize.UglifyJsPlugin(),
 new webpack.optimize.OccurrenceOrderPlugin(),
 new webpack.optimize.AggressiveMergingPlugin()

et

"scripts": {
    "build": "NODE_ENV=production webpack --config ./webpack.production.config.js"
},
Putzi San
la source
2

Si vous avez beaucoup de code dupliqué dans votre webpack.dev.config et votre webpack.prod.config, vous pouvez utiliser un booléen isProdpour activer certaines fonctionnalités uniquement dans certaines situations et n'avoir qu'un seul fichier webpack.config.js.

const isProd = (process.env.NODE_ENV === 'production');

 if (isProd) {
     plugins.push(new AotPlugin({
      "mainPath": "main.ts",
      "hostReplacementPaths": {
        "environments/index.ts": "environments/index.prod.ts"
      },
      "exclude": [],
      "tsConfigPath": "src/tsconfig.app.json"
    }));
    plugins.push(new UglifyJsPlugin({
      "mangle": {
        "screw_ie8": true
      },
      "compress": {
        "screw_ie8": true,
        "warnings": false
      },
      "sourceMap": false
    }));
  }

Au fait: le plugin DedupePlugin a été supprimé de Webpack. Vous devez le supprimer de votre configuration.

METTRE À JOUR:

En plus de ma réponse précédente:

Si vous souhaitez masquer votre code pour la publication, essayez enclosejs.com . Il vous permet de:

  • créer une version commerciale de votre application sans sources
  • créer une archive auto-extractible ou un programme d'installation
  • Créer une application GUI source fermée
  • Mettez vos actifs dans l'exécutable

Vous pouvez l'installer avec npm install -g enclose

MatthiasSommer
la source