Search code examples
javascriptbabeljswebpack-2uglifyjspreact

Unexpected Token error using UglifyJS with Preact, Webpack 2


I'm building a Chrome extension with Preact/ES6/Webpack. I pack using one of 2 configurations: debug uses ESLint, Babel and CSS + JSON loaders, prod adds 2 plugins: UglifyJS and Zip. Here's the webpack.config.js:

const webpack = require('webpack');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const WebpackCleanupPlugin = require('webpack-cleanup-plugin');
const ZipPlugin = require('zip-webpack-plugin');
const manifest = require('./src/manifest');

let options = {
    // entry file - starting point for the app
    entry: {
    popup: './src/scripts/popup.js',
    options: './src/scripts/options.js',
    background: './src/scripts/background.js'
  },

    // where to dump the output of a production build
    output: {
    path: path.join(__dirname, 'build'),
    filename: 'scripts/[name].js'
  },

    module: {
        rules: [
      {
        test: /\.jsx?/i,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        options: {
        },
        enforce: 'pre'
    },
    {
        test: /\.jsx?/i,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
            presets: [
            ['env', {
              'targets': {
                'chrome': 52
              }
            }]
          ],
            plugins: [
            ['transform-react-jsx'],
            ['module-resolver', {
              'root': ['.'],
              'alias': {
                'react': 'preact-compat',
                'react-dom': 'preact-compat'
              }
            }]
                    ]
                }
            },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.json$/,
        use: 'json-loader'
      }
        ]
    },

  plugins: [
    new WebpackCleanupPlugin(),
    new CopyWebpackPlugin([
      {from: './src/_locales', to: '_locales'},
      {from: './src/icons', to: 'icons'},
      {from: './src/manifest.json', flatten: true},
      {from: './src/*.html', flatten: true}
    ])
  ],

    // enable Source Maps
    devtool: 'source-map',
};

if(process.env.NODE_ENV === 'production') {
  options.plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
        drop_console: false,
        screw_ie8: true,
        conditionals: true,
        unused: true,
        comparisons: true,
        sequences: true,
        dead_code: true,
        evaluate: true,
        if_return: true,
        join_vars: true,
      },
      output: {
        comments: false,
      },
    }),
    new ZipPlugin({
      path: '../dist',
      filename: `${manifest.name} ${manifest.version}.zip`
    })
  );
}

console.log(`This is a ${process.env.NODE_ENV === 'production' ? 'production' : 'development'} build with ${options.plugins.length} plugins`);

module.exports = options;

But when I run the prod, I get the following errors:

ERROR in scripts/popup.js from UglifyJs
Unexpected token: name (getLatestValues) [scripts/popup.js:29428,4]

ERROR in scripts/options.js from UglifyJs
Unexpected token: name (getLatestValues) [scripts/options.js:29428,4]

ERROR in scripts/background.js from UglifyJs
Unexpected token: name (getLatestValues) [scripts/background.js:28678,4]

It's worth mentioning that getLatestResults is not the only the only function in my code that has await in front of it. Also, it should only appear in background.js as the other entry points are not supposed to call it.

Also worth mentioning is that if I just comment the UglifyJS code, the resulting zipped extension works well.

What configuration piece am I missing to make these errors go away?


Solution

  • It turns out that currently (5/2017) the built in webpack.optimize.UglifyJsPlugin does not support ES6. When Babel transpiles await/async it turns them into generators, which causes UglifyJS to throw an error.

    There are several alternatives to UglifyJS listed in this article, but I'm hoping that the Webpack guys will update the plugin, and I'd be able to leave my code intact.

    TL;DR: My code is OK; UglifyJS does not support ES6; Will support in the future, or will be replaced by alternative.