Webpack cómo construir código de producción y cómo usarlo

95

Soy muy nuevo en webpack, descubrí que en la compilación de producción podemos reducir el tamaño del código general. Actualmente, el paquete web tiene alrededor de 8 MB de archivos y main.js alrededor de 5 MB. ¿Cómo reducir el tamaño del código en la construcción de producción? Encontré un archivo de configuración de paquete web de muestra de Internet y lo configuré para mi aplicación y lo ejecuté npm run buildy comenzó a compilarse y generó algunos archivos en el ./dist/directorio.

  1. Aún así, estos archivos son pesados ​​(igual que la versión de desarrollo)
  2. ¿Cómo utilizar estos archivos? Actualmente estoy usando webpack-dev-server para ejecutar la aplicación.

archivo 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
fuente
1
¿Encontraste una respuesta a tu última pregunta? "¿Cómo usar estos archivos? Actualmente estoy usando webpack-dev-server para ejecutar la aplicación".
Randy
4
Internet era mucho mejor antes del paquete web, solo mira esta pregunta y la respuesta.
Randy L

Respuestas:

66

Puede agregar los complementos como lo sugiere @Vikramaditya. Luego, para generar la construcción de producción. Tienes que ejecutar el comando

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

Le -pdice al paquete web que genere una compilación de producción. Debe cambiar el script de compilación en package.json para incluir la marca de producción.

sandeep
fuente
6
OK gracias. mi siguiente duda es ¿cómo ejecutar el código de producción? cuando ejecuto el comando anterior, crea algunos archivos en el directorio dist. ok, se compiló correctamente. ahora, ¿cómo usar estos archivos? en el modo de desarrollo utilicé 'npm start' y comenzó.
Gilson PJ
Si va a su src/server/bin/server. Entonces puede averiguar cómo está sirviendo los archivos y tal vez cambiarlo. Lo que creo que hará es ejecutar el paquete web para compilar archivos y luego servirlos. Eche un vistazo al código de este archivo.
sandeep
@Vikramaditya ¿Podrías ayudarme con el escenario en stackoverflow.com/questions/40993795/msbuild-and-webpack
lohiarahul
@GilsonPJ, ¿descubrió cómo usar estos archivos de interfaz de usuario?
Randy
Primero debe instalar el paquete web usando npm install webpack
Peter Rader
43

Después de observar la cantidad de espectadores a esta pregunta, decidí concluir una respuesta de Vikramaditya y Sandeep.

Para construir el código de producción, lo primero que debe crear es la configuración de producción con paquetes de optimización como,

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

Luego, en el archivo package.json puede configurar el procedimiento de compilación con esta configuración de producción

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

ahora tienes que ejecutar el siguiente comando para iniciar la compilación

npm run build

Según mi configuración de compilación de producción, el paquete web compilará la fuente en el ./distdirectorio.

Ahora su código de IU estará disponible en ./dist/ directorio. Configure su servidor para que sirva estos archivos como activos estáticos. ¡Hecho!

Gilson PJ
fuente
7
¿Qué quieres decir en tu última oración? ¿Cómo suministrar estos códigos? Sé que node.js construye un servidor en sí mismo. Pero, ¿cómo puedo ejecutarlo después de tener el archivo en el ./dist/directorio?
Newguy
6
Solo una nota, agregar la opción -p en la parte superior del complemento uglifyJS causa problemas ya que intenta uglify dos veces. Eliminar la opción -p cli solucionó estos problemas para mí
timelf123
'NODE_ENV' no se reconoce como un comando interno o externo, programa operable o archivo por lotes.
Anton Duzenko
2
Esta debería ser la respuesta aceptada, porque nadie decía cómo servir el sitio web. Ahora su código de IU estará disponible en el directorio ./dist/. Configure su servidor para que proporcione estos códigos de IU para la solicitud. y listo.!
jperelli
2
Sigo sin entender cómo "Configurar su servidor para que proporcione estos códigos de IU para la solicitud y listo". Entiendo lo que queremos hacer aquí, pero no sé cómo hacerlo
Randy
42

Utilice estos complementos para optimizar su construcción de producción:

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

Recientemente me enteré de la compresión-webpack-plugin que comprime su paquete de salida para reducir su tamaño. Agregue esto también en la lista de complementos enumerados anteriormente para optimizar aún más su código de producción.

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

La compresión gzip dinámica del lado del servidor no se recomienda para entregar archivos estáticos del lado del cliente debido al uso intensivo de la CPU.

Vikramaditya
fuente
1
¿Qué hace la parte 'common.js' en commonschuckplugin? ese complemento es fácilmente el más difícil de entender para mí.
Echiban
2
CommonsChunkPlugin extrae el código común de todos sus fragmentos y lo coloca en un archivo separado common.js.
Vikramaditya
3
Esta respuesta ya no es válida para la versión 4 del paquete web
Dennis
20

Solo estoy aprendiendo esto yo mismo. Responderé a la segunda pregunta:

  1. ¿Cómo utilizar estos archivos? Actualmente estoy usando webpack-dev-server para ejecutar la aplicación.

En lugar de utilizar webpack-dev-server, puede ejecutar un "express". use npm install "express" y cree un server.js en el directorio raíz del proyecto, algo como esto:

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

Luego, en package.json, agregue un script:

"start": "node server.js"

Finalmente, ejecute la aplicación: npm run start para iniciar el servidor

Se puede ver un ejemplo detallado en: https://alejandronapoles.com/2016/03/12/the-simplest-webpack-and-express-setup/ (el código de ejemplo no es compatible con los últimos paquetes, pero funcionará con pequeños retoques)

Siyuan Jiang
fuente
2
Si empezaste a aprender cosas de nodejs, expressjs, etc., entonces quiero decirte. Esta pregunta es una pregunta de nivel avanzado. No se trata solo de cómo ejecutar estos archivos. Es para Cómo minimizar (comprimir) el código de producción y cómo ejecutar ese código comprimido
Arpit
1
@Arpit Gracias por señalar esto. Soy muy nuevo en esto. Supuse que una vez que se genera el código comprimido, el método de ejecución debería ser el mismo.
Siyuan Jiang
9

Puede usar el módulo argv npm (instálelo ejecutando npm install argv --save ) para obtener parámetros en su archivo webpack.config.js y para la producción, use -p flag "build": "webpack -p" , puede agregue la condición en el archivo webpack.config.js como se muestra a continuación

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

Y eso es.

Hayk Aghabekyan
fuente
1
En su lugar, useprocess.argv.indexOf('-p') != -1
AjaxLeung
@AjaxLeung: debe incluir argven el archivo de configuración del paquete web:const argv = require('argv');
kadam
6

Esto te ayudara.

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

Además de la respuesta de Gilson PJ:

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

con

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

porque intenta fechar su código dos veces. Consulte https://webpack.github.io/docs/cli.html#production-shortcut-p para obtener más información.

Puede solucionar este problema eliminando UglifyJsPlugin de plugins-array o agregando OccurrenceOrderPlugin y eliminando el indicador "-p". así que una posible solución sería

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

y

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

Si tiene mucho código duplicado en su webpack.dev.config y su webpack.prod.config, puede usar un booleano isProdpara activar ciertas funciones solo en ciertas situaciones y solo tener un solo archivo 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
    }));
  }

Por cierto: el complemento DedupePlugin se eliminó de Webpack. Deberías eliminarlo de tu configuración.

ACTUALIZAR:

Además de mi respuesta anterior:

Si desea ocultar su código para su publicación, pruebe enclosejs.com . Te permite:

  • hacer una versión de lanzamiento de su aplicación sin fuentes
  • crear un archivo o instalador autoextraíble
  • Crear una aplicación GUI de código cerrado
  • Pon tus activos dentro del ejecutable

Puedes instalarlo con npm install -g enclose

MatthiasSommer
fuente