Webpack, wie man Produktionscode erstellt und wie man ihn verwendet

92

Ich bin sehr neu in Webpack. Ich habe festgestellt, dass wir in der Produktion die Größe des gesamten Codes reduzieren können. Derzeit erstellt Webpack ca. 8 MB Dateien und main.js ca. 5 MB. Wie kann die Größe des Codes im Produktions-Build reduziert werden? Ich habe eine Beispiel-Webpack-Konfigurationsdatei aus dem Internet gefunden und für meine Anwendung konfiguriert. Ich führe sie aus npm run buildund sie wird erstellt, und es werden einige Dateien im ./dist/Verzeichnis generiert .

  1. Trotzdem sind diese Dateien schwer (wie die Entwicklungsversion)
  2. Wie verwende ich diese Dateien? Derzeit verwende ich den Webpack-Dev-Server, um die Anwendung auszuführen.

package.json Datei

{
  "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
quelle
1
Haben Sie eine Antwort auf Ihre letzte Frage gefunden? "Wie verwende ich diese Dateien? Derzeit verwende ich den Webpack-Dev-Server, um die Anwendung auszuführen."
Randy
4
Das Internet war vor dem Webpack so viel besser. Schauen Sie sich nur diese Frage und die Antwort an.
Randy L

Antworten:

64

Sie können die Plugins wie von @Vikramaditya vorgeschlagen hinzufügen. Dann, um den Produktionsaufbau zu generieren. Sie müssen den Befehl ausführen

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

Das -pweist das Webpack an, einen Produktionsbuild zu generieren. Sie müssen das Build-Skript in package.json ändern , um das Produktionsflag einzuschließen .

Sandeep
quelle
6
OK danke. Mein nächster Zweifel ist, wie man den Produktionscode ausführt. Wenn ich den obigen Befehl ausführe, werden einige Dateien im Verzeichnis dist erstellt. ok es wurde erfolgreich kompiliert. Wie verwende ich diese Dateien? Im Entwicklungsmodus habe ich 'npm start' verwendet und es wurde gestartet.
Gilson PJ
Wenn du zu deinem gehst src/server/bin/server. Dann können Sie herausfinden, wie die Dateien bereitgestellt werden, und sie möglicherweise ändern. Ich denke, es wird Webpack ausführen, um Dateien zu erstellen und sie dann bereitzustellen. Schauen Sie sich den Code dieser Datei an.
Sandeep
@ Vikramaditya Könnten Sie mir mit dem Szenario in stackoverflow.com/questions/40993795/msbuild-and-webpack
lohiarahul
@GilsonPJ Haben Sie herausgefunden, wie diese UI-Dateien verwendet werden?
Randy
Sie müssen Webpack zuerst mitnpm install webpack
Peter Rader
42

Nachdem ich die Anzahl der Zuschauer auf diese Frage beobachtet hatte, beschloss ich, eine Antwort von Vikramaditya und Sandeep abzuschließen.

Um den Produktionscode zu erstellen, müssen Sie zunächst die Produktionskonfiguration mit Optimierungspaketen wie:

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

Anschließend können Sie in der Datei package.json die Erstellungsprozedur mit dieser Produktionskonfiguration konfigurieren

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

Jetzt müssen Sie den folgenden Befehl ausführen, um den Build zu starten

npm run build

Gemäß meiner Produktions-Build-Konfiguration erstellt das Webpack die Quelle in das ./distVerzeichnis.

Jetzt ist Ihr UI-Code im ./dist/Verzeichnis verfügbar . Konfigurieren Sie Ihren Server so, dass diese Dateien als statische Assets bereitgestellt werden. Getan!

Gilson PJ
quelle
7
Was meinst du in deinem letzten Satz? Wie werden diese Codes angegeben? Ich weiß, dass node.js einen Server für sich baut. Aber wie kann ich es ausführen, nachdem ich die Datei im ./dist/Verzeichnis habe?
Newguy
6
Nur eine Anmerkung: Das Hinzufügen der Option -p über dem uglifyJS-Plugin verursacht Probleme, da es versucht, zweimal zu uglifizieren. Das Entfernen der Option -p cli hat diese Probleme für mich
behoben
'NODE_ENV' wird nicht als interner oder externer Befehl, bedienbares Programm oder Batchdatei erkannt.
Anton Duzenko
2
Dies sollte die akzeptierte Antwort sein, da niemand sagte, wie die Website zu bedienen ist. Jetzt ist Ihr UI-Code im Verzeichnis ./dist/ verfügbar. Stellen Sie Ihren Server so ein, dass er diesen UI-Code für die Anforderung bereitstellt. und du bist fertig.!
Jperelli
2
Ich verstehe immer noch nicht, wie ich "Ihren Server so einstellen soll, dass er diesen UI-Code für die Anforderung bereitstellt. Und Sie sind fertig." Ich verstehe, was wir hier machen wollen, aber ich weiß einfach nicht, wie es geht
Randy
41

Verwenden Sie diese Plugins, um Ihren Produktionsaufbau zu optimieren:

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

Ich habe kürzlich das Komprimierungs-Webpack-Plugin kennengelernt, das Ihr Ausgabepaket komprimiert , um seine Größe zu reduzieren. Fügen Sie dies ebenfalls in die oben aufgeführte Liste der Plugins ein, um Ihren Produktionscode weiter zu optimieren.

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

Die serverseitige dynamische gzip-Komprimierung wird wegen der hohen CPU-Auslastung nicht für die Bereitstellung statischer clientseitiger Dateien empfohlen.

Vikramaditya
quelle
1
Was macht der Teil 'common.js' auf commonschuckplugin? Dieses Plugin ist für mich am schwersten zu verstehen.
Echiban
2
CommonsChunkPlugin extrahiert den allgemeinen Code aus all Ihren Blöcken und legt ihn in einer separaten Datei ab common.js.
Vikramaditya
3
Diese Antwort ist nicht mehr gültig für Webpack Version 4
Dennis
20

Ich lerne das einfach selbst. Ich werde die zweite Frage beantworten:

  1. Wie verwende ich diese Dateien? Derzeit verwende ich den Webpack-Dev-Server, um die Anwendung auszuführen.

Anstatt den Webpack-Dev-Server zu verwenden, können Sie einfach einen "Express" ausführen. Verwenden Sie npm install "express" und erstellen Sie eine server.js im Stammverzeichnis des Projekts.

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);

Fügen Sie dann in der Datei package.json ein Skript hinzu:

"start": "node server.js"

Führen Sie abschließend die App aus: npm run startum den Server zu starten

Ein detailliertes Beispiel finden Sie unter: https://alejandronapoles.com/2016/03/12/the-simplest-webpack-and-express-setup/ (der Beispielcode ist nicht mit den neuesten Paketen kompatibel, funktioniert jedoch mit kleinen Änderungen)

Siyuan Jiang
quelle
2
Wenn Sie angefangen haben, Nodejs, Expressjs usw. zu lernen, dann möchte ich es Ihnen sagen. Diese Frage ist eine Frage für Fortgeschrittene. Es ist nicht nur für die Ausführung dieser Dateien. Es ist für das Minimieren (Komprimieren) von Produktionscode und das Ausführen dieses komprimierten Codes
Arpit
1
@Arpit Danke, dass du darauf hingewiesen hast. Ich bin sehr neu in diesem Bereich. Ich ging davon aus, dass die Ausführungsmethode dieselbe sein sollte, sobald der komprimierte Code generiert wurde.
Siyuan Jiang
9

Sie können mit argv npm Modul (installieren Sie es , indem Sie npm installieren argv --save ) für params in Ihrer webpack.config.js Datei bekommen und wie für die Produktion verwenden Sie -p Flag „build“: „webpack -p“ können Sie Fügen Sie die Bedingung in der Datei webpack.config.js wie unten hinzu

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

Und das ist es.

Hayk Aghabekyan
quelle
1
Verwenden process.argv.indexOf('-p') != -1
Sie
@ AjaxLeung: Sie müssen argvin die Webpack-Konfigurationsdatei aufnehmen:const argv = require('argv');
Kadam
6

Das wird dir helfen.

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
quelle
5

Zusätzlich zu Gilson PJ Antwort:

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

mit

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

Ursache, dass es versucht, Ihren Code zweimal zu hässlich zu machen. Weitere Informationen finden Sie unter https://webpack.github.io/docs/cli.html#production-shortcut-p .

Sie können dies beheben, indem Sie das UglifyJsPlugin aus dem Plugins-Array entfernen oder das OccurrenceOrderPlugin hinzufügen und das "-p" -Flag entfernen. Eine mögliche Lösung wäre also

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

und

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

Wenn Ihre webpack.dev.config und Ihre webpack.prod.config viel doppelten Code enthalten, können Sie einen Booleschen Wert verwenden, isProdum bestimmte Funktionen nur in bestimmten Situationen zu aktivieren, und nur eine einzige webpack.config.js-Datei haben.

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

Übrigens: Das DedupePlugin- Plugin wurde aus Webpack entfernt. Sie sollten es aus Ihrer Konfiguration entfernen.

AKTUALISIEREN:

Zusätzlich zu meiner vorherigen Antwort:

Wenn Sie Ihren Code für die Veröffentlichung ausblenden möchten, versuchen Sie es mit enclosejs.com . Es ermöglicht Ihnen:

  • Erstellen Sie eine Release-Version Ihrer Anwendung ohne Quellen
  • Erstellen Sie ein selbstextrahierendes Archiv oder Installationsprogramm
  • Erstellen Sie eine Closed-Source-GUI-Anwendung
  • Legen Sie Ihr Vermögen in die ausführbare Datei

Sie können es mit installieren npm install -g enclose

MatthiasSommer
quelle