¿Cómo construir un paquete minimizado y sin comprimir con webpack?

233

Aquí está mi webpack.config.js

var webpack = require("webpack");

module.exports = {

  entry: "./entry.js",
  devtool: "source-map",
  output: {
    path: "./dist",
    filename: "bundle.min.js"
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({minimize: true})
  ]
};

Estoy construyendo con

$ webpack

En mi distcarpeta, solo recibo

  • bundle.min.js
  • bundle.min.js.map

También me gustaría ver el descomprimido bundle.js

Gracias
fuente

Respuestas:

151

webpack.config.js :

const webpack = require("webpack");

module.exports = {
  entry: {
    "bundle": "./entry.js",
    "bundle.min": "./entry.js",
  },
  devtool: "source-map",
  output: {
    path: "./dist",
    filename: "[name].js"
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      include: /\.min\.js$/,
      minimize: true
    })
  ]
};

Desde Webpack 4, webpack.optimize.UglifyJsPluginha quedado en desuso y su uso da como resultado un error:

webpack.optimize.UglifyJsPlugin se ha eliminado, utilice config.optimization.minimize en su lugar

Como explica el manual , el complemento se puede reemplazar con la minimizeopción. Se puede proporcionar una configuración personalizada al complemento especificando la UglifyJsPlugininstancia:

const webpack = require("webpack");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
  // ...
  optimization: {
    minimize: true,
    minimizer: [new UglifyJsPlugin({
      include: /\.min\.js$/
    })]
  }
};

Esto hace el trabajo para una configuración simple. Una solución más efectiva es usar Gulp junto con Webpack y hacer lo mismo de una sola vez.

Estus Flask
fuente
1
@FeloVilches Ni siquiera menciono que esto se hace en webpack.config.js, pero esto se presume una vez que estamos en Node.js land y usamos Webpack.
Estus Flas
3
Hmm, en webpack 4 tengo:Error: webpack.optimize.UglifyJsPlugin has been removed, please use config.optimization.minimize instead.
entithat
3
Actualización: ahora puede usar terser-webpack-plugin webpack.js.org/plugins/terser-webpack-plugin
ijse
156

Puede usar un solo archivo de configuración e incluir el complemento UglifyJS condicionalmente usando una variable de entorno:

var webpack = require('webpack');

var PROD = JSON.parse(process.env.PROD_ENV || '0');

module.exports = {

  entry: './entry.js',
  devtool: 'source-map',
  output: {
    path: './dist',
    filename: PROD ? 'bundle.min.js' : 'bundle.js'
  },
  plugins: PROD ? [
    new webpack.optimize.UglifyJsPlugin({
      compress: { warnings: false }
    })
  ] : []
};

y luego simplemente configura esta variable cuando quieras minificarla:

$ PROD_ENV=1 webpack


Editar:

Como se menciona en los comentarios, NODE_ENVgeneralmente se usa (por convención) para indicar si un entorno particular es un entorno de producción o de desarrollo. Para verificarlo, también puede configurar var PROD = (process.env.NODE_ENV === 'production')y continuar normalmente.

lyosef
fuente
66
El nodo tiene una variable "predeterminada" para eso, se llama NODE_ENV.
JCM
2
¿No se llama a la opción en compresslugar de minimize?
Slava Fomin II
1
Solo un pequeño problema: cuando llama a webpack con argumentos, como webpack -pla configuración de webpack.optimize.UglifyJsPlugin en su configuración de webpack se ignorará (al menos parcialmente) (al menos mangle: falsese ignora la configuración ).
Christian Ulbrich
2
Tenga en cuenta que esto genera solo un archivo a la vez. Así que para hacer este trabajo para la cuestión debe haber múltiples pases webpack, webpack && webpack -p.
Estus Flas
1
Para cualquiera que lea esto, sugeriría usar en su definePluginlugar, que creo que está instalado de forma predeterminada con Webpack.
Ben Gubler
54

Puede ejecutar webpack dos veces con diferentes argumentos:

$ webpack --minimize

luego verifique los argumentos de la línea de comando en webpack.config.js:

var path = require('path'),
  webpack = require('webpack'),
  minimize = process.argv.indexOf('--minimize') !== -1,
  plugins = [];

if (minimize) {
  plugins.push(new webpack.optimize.UglifyJsPlugin());
}

...

ejemplo webpack.config.js

Gordon Freeman
fuente
2
Parece una solución muy simple para mí; solo que a partir de webpack v3.5.5 tiene un conmutador incorporado llamado --optimize-minimizar o -p.
sinérgico
La idea es genial, pero no funciona ahora, webpack gritará "Argumento desconocido: minimizar" Solución: use --env.minimize más detalles en el siguiente enlace github.com/webpack/webpack/issues/2254
Zhli
Puede usar una forma más estándar de pasar la indicación del entorno en el paquete web: stackoverflow.com/questions/44113359/…
MaMazav
40

Para agregar otra respuesta, la bandera -p(abreviatura de --optimize-minimize) habilitará el UglifyJS con argumentos predeterminados.

No obtendrá un paquete minificado y sin procesar de una sola ejecución ni generará paquetes con nombres diferentes, por lo que la -pbandera puede no cumplir con su caso de uso.

Por el contrario, la -dopción es la abreviatura de--debug --devtool sourcemap --output-pathinfo

Mis webpack.config.js omite devtool, debug, pathinfo, y el plugin de minmize a favor de estas dos banderas.

everett1992
fuente
Gracias @ everett1992, esta solución funciona muy bien. La gran mayoría de las veces ejecuto la compilación de desarrollo, luego, cuando termino, uso el indicador -p para escupir una compilación de producción minificada. ¡No es necesario crear dos configuraciones de Webpack separadas!
pmont
36

Tal vez llego tarde aquí, pero tengo el mismo problema, así que escribí un plugin de paquete web nominificado para este propósito.

Instalación

npm install --save-dev unminified-webpack-plugin

Uso

var path = require('path');
var webpack = require('webpack');
var UnminifiedWebpackPlugin = require('unminified-webpack-plugin');

module.exports = {
    entry: {
        index: './src/index.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'library.min.js'
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        }),
        new UnminifiedWebpackPlugin()
    ]
};

Al hacer lo anterior, obtendrá dos archivos library.min.js y library.js. No es necesario ejecutar webpack dos veces, ¡simplemente funciona! ^^

Howard
fuente
Este complemento parece no ser compatible con SourceMapDevToolPlugin. ¿Alguna sugerencia para retener mapas de origen?
BhavikUp
@BhavikUp, no es compatible. ¿Crees que realmente necesitas un mapa fuente para que salga junto con el archivo js final?
Howard
1
"No es necesario ejecutar el paquete web dos veces" [...] Agradable, pero la solución de estus tampoco requiere "ejecutar el paquete web dos veces" y, además, no requiere agregar un complemento de terceros.
Louis
@Howard Man, llegaste justo a tiempo :). Al menos para mi. ¡Muchas gracias por el excelente complemento! Parece funcionar perfectamente con la opción webpack 2 y -p.
gaperton
34

En mi opinión, es mucho más fácil usar la herramienta UglifyJS directamente:

  1. npm install --save-dev uglify-js
  2. Use el paquete web de forma normal, por ejemplo, creando un ./dst/bundle.jsarchivo.
  3. Agregue un buildcomando a su package.json:

    "scripts": {
        "build": "webpack && uglifyjs ./dst/bundle.js -c -m -o ./dst/bundle.min.js --source-map ./dst/bundle.min.js.map"
    }
    
  4. Cada vez que desee construir un paquete, así como código y mapas fuente uglified, ejecute el npm run buildcomando.

No es necesario instalar uglify-js globalmente, solo instálelo localmente para el proyecto.

Dave Kerr
fuente
sí, esta es una solución fácil que le permite construir solo una vez
Flion
15

Puede crear dos configuraciones para webpack, una que minimice el código y otra que no (simplemente elimine la línea optimizar.UglifyJSPlugin) y luego ejecute ambas configuraciones al mismo tiempo $ webpack && webpack --config webpack.config.min.js

trekforever
fuente
2
Gracias, esto funciona muy bien, pero seguramente sería bueno si hubiera una mejor manera de hacerlo que mantener dos archivos de configuración dado que este es un caso de uso tan común (casi cualquier compilación de biblioteca).
Rick Strahl el
12

De acuerdo con esta línea: https://github.com/pingyuanChen/webpack-uglify-js-plugin/blob/master/index.js#L117

debería ser algo como:

var webpack = require("webpack");

module.exports = {

  entry: "./entry.js",
  devtool: "source-map",
  output: {
    path: "./dist",
    filename: "bundle.js"
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
     minimize: true,
     compress: false
    })
  ]
};

De hecho, puede tener múltiples compilaciones exportando diferentes configuraciones de acuerdo con sus estrategias env / argv.

Ideabile
fuente
Gracias por su útil respuesta a una pregunta antigua pero de alguna manera relevante, Mauro ^ _ ^
Gracias el
1
No se puede encontrar la opción minimizeen documentos. Tal vez está en desuso?
adi518
@ adi518 ¿Quizás está utilizando una versión más nueva del complemento y no la que se incluye en el paquete web?
thexpand
4

webpack entry.jsx ./output.js -p

funciona para mí, con -pbandera.

gdfgdfg
fuente
4

Puede formatear su webpack.config.js de esta manera:

var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');

module.exports = {
    context: __dirname,
    devtool: debug ? "inline-sourcemap" : null,
    entry: "./entry.js",
    output: {
        path: __dirname + "/dist",
        filename: "library.min.js"
    },
    plugins: debug ? [] : [
        new webpack.optimize.DedupePlugin(),
        new webpack.optimize.OccurenceOrderPlugin(),
        new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
    ],
};'

Y luego, para construirlo, ejecute sin minificar (mientras está en el directorio principal del proyecto):

$ webpack

Para construirlo, ejecuta minified:

$ NODE_ENV=production webpack

Notas: Asegúrese de que para la versión no minificada cambie el nombre del archivo de salida a library.jsy para el minificado library.min.jspara que no se sobrescriban entre sí.

cnzac
fuente
3

Tuve el mismo problema y tuve que cumplir con todos estos requisitos:

  • Versión minificada + no minificada (como en la pregunta)
  • ES6
  • Multiplataforma (Windows + Linux).

Finalmente lo resolví de la siguiente manera:

webpack.config.js:

const path = require('path');
const MinifyPlugin = require("babel-minify-webpack-plugin");

module.exports = getConfiguration;

function getConfiguration(env) {
    var outFile;
    var plugins = [];
    if (env === 'prod') {
        outFile = 'mylib.dev';
        plugins.push(new MinifyPlugin());
    } else {
        if (env !== 'dev') {
            console.log('Unknown env ' + env + '. Defaults to dev');
        }
        outFile = 'mylib.dev.debug';
    }

    var entry = {};
    entry[outFile] = './src/mylib-entry.js';

    return {
        entry: entry,
        plugins: plugins,
        output: {
            filename: '[name].js',
            path: __dirname
        }
    };
}

package.json:

{
    "name": "mylib.js",
    ...
    "scripts": {
        "build": "npm-run-all webpack-prod webpack-dev",
        "webpack-prod": "npx webpack --env=prod",
        "webpack-dev": "npx webpack --env=dev"
    },
    "devDependencies": {
        ...
        "babel-minify-webpack-plugin": "^0.2.0",
        "npm-run-all": "^4.1.2",
        "webpack": "^3.10.0"
    }
}

Entonces puedo construir por (No olvides npm installantes):

npm run-script build
MaMazav
fuente
Recibí este error ERROR en desconocido: tipo de valor no válido
Kushal Jain
3

Encontré una nueva solución para este problema.

Esto usa una matriz de configuración para permitir que webpack construya la versión minificada y no minificada en paralelo. Esto hace que la construcción sea más rápida. No es necesario ejecutar el paquete web dos veces. No necesita complementos adicionales. Solo webpack.

webpack.config.js

const devConfig = {
  mode: 'development',
  entry: { bundle: './src/entry.js' },
  output: { filename: '[name].js' },
  module: { ... },
  resolve: { ... },
  plugins: { ... }
};

const prodConfig = {
  ...devConfig,
  mode: 'production',
  output: { filename: '[name].min.js' }
};

module.exports = (env) => {
  switch (env) {
    case 'production':
      return [devConfig, prodConfig];
    default:
      return devConfig;
  }
};

La ejecución webpacksolo generará la versión no minificada.

La ejecución webpack --env=productiongenerará la versión minificada y no minificada al mismo tiempo.

Rannie Aguilar Peralta
fuente
1

Debería exportar una matriz como esta:

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

const libName = 'YourLibraryName';

function getConfig(env) {
  const config = {
    mode: env,
    output: {
      path: path.resolve('dist'),
      library: libName,
      libraryTarget: 'umd',
      filename: env === 'production' ? `${libName}.min.js` : `${libName}.js`
    },
    target: 'web',
    .... your shared options ...
  };

  return config;
}

module.exports = [
  getConfig('development'),
  getConfig('production'),
];
Dominic
fuente
0

Puede definir dos puntos de entrada en la configuración de su paquete web, uno para sus js normales y el otro para js minificados. Luego, debe generar su paquete con su nombre y configurar el complemento UglifyJS para incluir archivos min.js. Vea el ejemplo de configuración de paquete web para más detalles:

module.exports = {
 entry: {
   'bundle': './src/index.js',
   'bundle.min': './src/index.js',
 },

 output: {
   path: path.resolve(__dirname, 'dist'),
   filename: "[name].js"
 },

 plugins: [
   new webpack.optimize.UglifyJsPlugin({
      include: /\.min\.js$/,
      minimize: true
   })
 ]
};

Después de ejecutar webpack, obtendrá bundle.js y bundle.min.js en su carpeta dist, sin necesidad de un complemento adicional.

dyg
fuente
explicación obsoleta
Olaf