Como criar pacote compactado e descompactado com o webpack?

233

Aqui está o meu 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})
  ]
};

Estou construindo com

$ webpack

Na minha distpasta, só estou recebendo

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

Eu também gostaria de ver os descomprimidos bundle.js

Obrigado
fonte

Respostas:

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 o Webpack 4, webpack.optimize.UglifyJsPluginfoi preterido e seu uso resulta em erro:

webpack.optimize.UglifyJsPlugin foi removido, use config.optimization.minimize

Como o manual explica, o plug-in pode ser substituído pela minimizeopção A configuração personalizada pode ser fornecida ao plug-in especificando a UglifyJsPlugininstância:

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

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

Isso faz o trabalho para uma configuração simples. Uma solução mais eficaz é usar o Gulp junto com o Webpack e fazer a mesma coisa de uma só vez.

Estus Flask
fonte
1
@FeloVilches Eu nem mencionei que isso é feito no webpack.config.js, mas isso é presumido quando estamos no Node.js e usamos o Webpack.
Estus Flask
3
Hmm, no webpack 4 eu tenho:Error: webpack.optimize.UglifyJsPlugin has been removed, please use config.optimization.minimize instead.
entithat
3
Atualização: agora você pode usar o terser-webpack-plugin webpack.js.org/plugins/terser-webpack-plugin
ijse
156

Você pode usar um único arquivo de configuração e incluir o plug-in UglifyJS condicionalmente usando uma variável de ambiente:

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 }
    })
  ] : []
};

e, em seguida, basta definir essa variável quando desejar reduzi-la:

$ PROD_ENV=1 webpack


Editar:

Conforme mencionado nos comentários, NODE_ENVgeralmente é usado (por convenção) para indicar se um ambiente específico é um ambiente de produção ou desenvolvimento. Para verificar, você também pode definir var PROD = (process.env.NODE_ENV === 'production')e continuar normalmente.

lyosef
fonte
6
O nó possui uma variável "padrão" para isso, chamada NODE_ENV.
JCM 15/02
2
A opção não é chamada em compressvez de minimize?
Slava Fomin II 31/03
1
Apenas uma pequena dica: quando você chama o webpack com argumentos, como webpack -pas configurações de webpack.optimize.UglifyJsPlugin na sua configuração do webpack serão (pelo menos parcialmente) ignoradas (pelo menos a configuração mangle: falseé ignorada).
Christian Ulbrich
2
Observe que isso gera apenas um arquivo por vez. Portanto, para que isso funcione para a pergunta, deve haver vários passes do Webpack webpack && webpack -p,.
Estus Flask
1
Para quem definePluginestiver lendo isso, sugiro o uso , que acho que está instalado por padrão no Webpack.
Ben Gubler
54

Você pode executar o webpack duas vezes com argumentos diferentes:

$ webpack --minimize

verifique os argumentos da linha de comando em 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());
}

...

exemplo webpack.config.js

Gordon Freeman
fonte
2
Parece uma solução muito simples para mim; exatamente como no webpack v3.5.5, ele possui um switch interno chamado --optimize-minimize ou -p.
synergetic
A idéia é legal, mas não funciona agora, o webpack gritará "Argumento desconhecido: minimize" Solução: use --env.minimize mais detalhes no link a seguir github.com/webpack/webpack/issues/2254
Zhli
Pode usar uma maneira mais padrão de passar a indicação do ambiente no webpack: stackoverflow.com/questions/44113359/…
MaMazav
40

Para adicionar outra resposta, o sinalizador -p(abreviação de --optimize-minimize) habilitará o UglifyJS com argumentos padrão.

Você não obterá um pacote compactado e minificado de uma única execução nem gerará pacotes nomeados de forma diferente, para que o -psinalizador não atenda ao seu caso de uso.

Por outro lado, a -dopção é abreviação de--debug --devtool sourcemap --output-pathinfo

Meus webpack.config.js omite devtool, debug, pathinfo, eo minmize plugins a favor destas duas bandeiras.

everett1992
fonte
Obrigado @ everett1992, esta solução funciona muito bem. Na grande maioria das vezes que executo a compilação do desenvolvedor, quando termino, uso o sinalizador -p para criar uma compilação de produção minificada. Não há necessidade de criar duas configurações separadas do Webpack!
pmont
36

Talvez eu esteja atrasado aqui, mas tenho o mesmo problema, então escrevi um plug-in-webpack-unminified para esse fim.

Instalação

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

Fazendo o acima, você obterá dois arquivos library.min.js e library.js. Não há necessidade de executar o webpack duas vezes, ele simplesmente funciona! ^^

Howard
fonte
Este plugin parece não ser compatível com o SourceMapDevToolPlugin. Alguma sugestão para manter os mapas de origem?
BhavikUp
@BhavikUp, não é suportado. Você acha que realmente precisa que o mapa de origem seja produzido junto com o arquivo js final?
Howard
1
"Não há necessidade de executar o webpack duas vezes [...]" Bom, mas a solução da estus também não exige "executar o webpack duas vezes" e, além disso, não exige a adição de um plug-in de terceiros.
Louis Louis
@ Howard Howard, você está na hora certa :). Pelo menos para mim. Muito obrigado pelo ótimo plug-in! Parece funcionar perfeitamente com a opção webpack 2 e -p.
Gaperton
34

Na minha opinião, é muito mais fácil usar a ferramenta UglifyJS diretamente:

  1. npm install --save-dev uglify-js
  2. Use o webpack normalmente, por exemplo, criando um ./dst/bundle.jsarquivo.
  3. Adicione um buildcomando ao seu package.json:

    "scripts": {
        "build": "webpack && uglifyjs ./dst/bundle.js -c -m -o ./dst/bundle.min.js --source-map ./dst/bundle.min.js.map"
    }
  4. Sempre que desejar criar um pacote configurável, bem como códigos e mapas de origem uglificados, execute o npm run buildcomando

Não é necessário instalar o uglify-js globalmente, basta instalá-lo localmente para o projeto.

Dave Kerr
fonte
sim esta é uma solução fácil que permite que você construa apenas uma vez
Flion
15

Você pode criar duas configurações para o webpack, uma que reduz o código e outra que não o faz (basta remover a linha optimize.UglifyJSPlugin) e executar as duas configurações ao mesmo tempo $ webpack && webpack --config webpack.config.min.js

trekforever
fonte
2
Obrigado, isso funciona muito bem, mas com certeza seria bom se houvesse uma maneira melhor de fazer isso do que manter dois arquivos de configuração, pois esse é um caso de uso tão comum (praticamente qualquer construção de biblioteca).
21317 Rick Sthl
12

De acordo com esta linha: https://github.com/pingyuanChen/webpack-uglify-js-plugin/blob/master/index.js#L117

deve 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 fato, você pode ter várias compilações exportando diferentes configurações de acordo com suas estratégias env / argv.

Ideabile
fonte
Obrigado pela sua resposta útil sobre uma pergunta antiga, mas de alguma forma ainda relevante, Mauro ^ _ ^
Obrigado
1
Não foi possível encontrar a opção minimizenos documentos. Talvez seja preterido?
adi518
@ adi518 Talvez você esteja usando uma versão mais recente do plug-in e não a que acompanha o pacote webpack?
precisa saber é
4

webpack entry.jsx ./output.js -p

trabalha para mim, com -pbandeira.

gdfgdfg
fonte
4

Você pode formatar seu webpack.config.js assim:

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 }),
    ],
};'

E, em seguida, para compilá-lo, execute uma execução não minuciosa (enquanto estiver no diretório principal do projeto):

$ webpack

Para compilá-lo, execute minified:

$ NODE_ENV=production webpack

Notas: Certifique-se de que, para a versão não minificada, altere o nome do arquivo de saída para library.jse para o minificado, library.min.jspara que não se substituam.

cnzac
fonte
3

Eu tive o mesmo problema e tive que atender a todos esses requisitos:

  • Versão minificada + não minificada (como na pergunta)
  • ES6
  • Plataforma cruzada (Windows + Linux).

Finalmente resolvi da seguinte maneira:

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"
    }
}

Então eu posso construir por (Não esqueça npm installantes):

npm run-script build
MaMazav
fonte
Eu tenho esse erro erro no desconhecido: valor typeof inválido
Kushal Jain
3

Encontrei uma nova solução para esse problema.

Isso usa uma matriz de configuração para permitir que o webpack construa a versão reduzida e não reduzida em paralelo. Isso torna a construção mais rápida. Não há necessidade de executar o webpack duas vezes. Não há necessidade de plugins extras. Apenas 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;
  }
};

A execução webpackcriará apenas a versão não minificada.

A execução webpack --env=productioncriará a versão minificada e não minificada ao mesmo tempo.

Rannie Aguilar Peralta
fonte
1

Você deve exportar uma 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
fonte
0

Você pode definir dois pontos de entrada na configuração do webpack, um para seus js normais e o outro para js minificados. Em seguida, você deve exibir seu pacote configurável com seu nome e configurar o plug-in UglifyJS para incluir arquivos min.js. Veja o exemplo de configuração do webpack para mais detalhes:

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

Após executar o webpack, você terá bundle.js e bundle.min.js na pasta dist, sem a necessidade de plug-ins extras.

dyg
fonte
explicação obsoleta
Olaf