[OT] Webpack/Terser build issue

Hi all,

This isn’t directly related to Elm, but as there is lots of helpful and friendly knowledge around here, I thought I’d ask.

I have an Elixir/Phoenix app that I’ve been working on for most of this year, and have just hit an issue that prevents me from deploying to production. The front end is an Elm SPA.

I would normally build my assets/js with Webpack using Terser to mangle the JS etc…

The build command is:

npm run deploy --prefix assets/

This would compile the Elm files to JS, minify and mangle the JS etc.

My issue is simple - if I change any of my Elm code, or my JS, npm run ... compiles Elm to JS, but then hangs - I’m guessing it’s a Terser issue, but not sure.

It doesn’t matter if I add, change or remove any code, simply changing a variable name, or changing a character in a string causes npm run... to hang and not complete - it’s almost as if there’s a cache somewhere that needs rebuilding - but I’ve not been able to find it.

Node: 14.2.0
Phoenix: 1.5.7
Webpack:

const path = require('path');
const glob = require('glob');
const TerserPlugin = require('terser-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = (env, options) => {
  const devMode = options.mode !== 'production';

  return {
    optimization: {
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            ecma: 5,
            compress: {
              pure_funcs: [
                "F2",
                "F3",
                "F4",
                "F5",
                "F6",
                "F7",
                "F8",
                "F9",
                "A2",
                "A3",
                "A4",
                "A5",
                "A6",
                "A7",
                "A8",
                "A9"
              ],
              pure_getters: true,
              keep_fargs: false,
              unsafe_comps: true,
              unsafe: true,
              passes: 2
            },
            mangle: true
          }
        }),
      ]
    },
    entry: {
      'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])
    },
    output: {
      filename: '[name].js',
      path: path.resolve(__dirname, '../priv/static/js'),
      publicPath: '/js/'
    },
    devtool: devMode ? 'eval-cheap-module-source-map' : undefined,
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader'
          }
        },
        {
          test: /\.elm$/,
          exclude: [/elm-stuff/, /node_modules/],
          use: {
            loader: 'elm-webpack-loader',
            options: {
              cwd: __dirname,
              debug: false, //options.mode === "development",
              optimize: options.mode === "production"
            }
          }
        }
      ]
    },
    plugins: [
      new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
    ]
  }
};

I’m struggling on how to resolve this, so any suggestions would be greatly appreciated.

What I don’t understand is why simply changing a character in a string would cause this process to fail, unless there’s some sort of lock file preventing the process from completing. :man_shrugging:

Hi, you could try running it by hand, to see if it is a terser version issue or a webpack issue?

script:

#!/bin/sh

set -e

js="dist/app.js"
min="dist/app.min.js"

elm make --optimize --output=$js $@

terser $js --compress "pure_funcs=[F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9],pure_getters,keep_fargs=false,unsafe_comps,unsafe" --mangle --output=$min

echo "Initial size: $(cat $js | wc -c) bytes  ($js)"
echo "Minified size:$(cat $min | wc -c) bytes  ($min)"
echo "Gzipped size: $(cat $min | gzip -c | wc -c) bytes"

save the above script to a file … for example optimize.sh then add execute permissions (I’m assuming you are on a *nix machine) chmod +x optimize.sh (or just run the commands from terminal)

Then run:

#change the argument to point to your Main.elm file
./optimize.sh src/Main.elm

If this works then the problem is on the webpack side … probably.

I’ve checked on 20 kloc elm spa (using terser@5.7.1) and it works … but maybe if your project is bigger then size might also be an issue?

1 Like

Thanks, that works, so it looks like webpack could be the culprit.

I don’t think size is an issue because it also happens if I remove code.

I think I may have narrowed it down to the terser-webpack-plugin namely node_modules/terser-webpack-plugin/dist/worker.js:10 . The line const result = minify(options); does not complete.

I’ve added the following to worker.js :

var stdout = require("stdout-stream");

and changed:

const result = minify(options);

to

stdout.write("\nworker, minify : start\n")

const result = minify(options);

stdout.write("\nworker, minify : end\n")

along with the following to minify.js :

var stdout = require("stdout-stream");

and changed

const minify = options => {
  const {
    file,
    input,
    inputSourceMap,
    minify: minifyFn
  } = options;

to

const minify = options => {
  stdout.write("minify")
  const {
    file,
    input,
    inputSourceMap,
    minify: minifyFn
  } = options;

So if all goes well, I should see the following output:

worker, minify : start
minify
worker, minify : end

But the only output I see is:

worker, minify : start

and then the process hangs without ever completing.

I thought I would at least see

worker, minify : start
minify

I think I’m truly at a dead end now, so any suggestions would be greatly appreciated.

At worst you can always try with Rollup (with the Terser plugin) instead of Webpack, if that’s a possible option for you.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.