parcel icon indicating copy to clipboard operation
parcel copied to clipboard

parcel build produces wrong minified js

Open moky80 opened this issue 1 year ago • 19 comments

🐛 bug report

I used https://github.com/TimTCrouch/WordList-JS in my app (which basically involves including https://github.com/TimTCrouch/WordList-JS/blob/master/src/wordList.js and https://github.com/TimTCrouch/WordList-JS/blob/master/src/wordBank.js in my index.html) and used "parcel build" to produce a bundle for browsers.

"parcel build" produced a wrong minified js for wordList.js with 2 issues:

  • the global variable Word_List https://github.com/TimTCrouch/WordList-JS/blob/master/src/wordList.js#L10 was stripped
  • the return statement https://github.com/TimTCrouch/WordList-JS/blob/master/src/wordList.js#L71 was stripped

After the 2 mentioned issues were manually fixed, my bundle worked. I reproduced the same error using the original https://github.com/TimTCrouch/WordList-JS/blob/master/testing.html instead of my index.html

🎛 Configuration (.babelrc, package.json, cli command)

The test setup I cloned https://github.com/TimTCrouch/WordList-JS to add my setup for using parcel here: https://github.com/minnie80/test-build-wordlistjs/blob/test-build-with-parcel/package.json

cli commands Build: npm run build Test: npm run prod

The test app http://localhost:3000/testing.html

🤔 Expected Behavior

The minified js in the bundle produced by "parcel build" should be correct. The corrected script:

var Word_List = (function () {
    var t = {},
      o = [];
    (t.isInList = function (t) {
      return o[(t = t.toLowerCase()).charAt(0)].indexOf(t) > -1;
    }),
      (t.getRandomWord = function (t) {
        0 == (t = t || 0) && (t = Math.floor(7 * Math.random()) + 4),
          t < 4 && (t = 4),
          t > 10 && (t = 10);
        var r,
          n,
          a = String.fromCharCode(Math.floor(26 * Math.random()) + 97);
        do (r = Math.floor(Math.random() * o[a].length)), (n = o[a][r]);
        while (n.length != t);
        return n;
      }),
      (t.loadBank = function (t) {
        var r = t[12].charAt(0);
        if (!r)
          throw "Not able to get first letter from word to determine word bank.";
        o[r] = t;
      });
      return t;
  })();

😯 Current Behavior

The incorrect script produced by "parcle build" (re-formatted by prettier.io):

!(function () {
  var t = {},
    o = [];
  (t.isInList = function (t) {
    return o[(t = t.toLowerCase()).charAt(0)].indexOf(t) > -1;
  }),
    (t.getRandomWord = function (t) {
      0 == (t = t || 0) && (t = Math.floor(7 * Math.random()) + 4),
        t < 4 && (t = 4),
        t > 10 && (t = 10);
      var r,
        n,
        a = String.fromCharCode(Math.floor(26 * Math.random()) + 97);
      do (r = Math.floor(Math.random() * o[a].length)), (n = o[a][r]);
      while (n.length != t);
      return n;
    }),
    (t.loadBank = function (t) {
      var r = t[12].charAt(0);
      if (!r)
        throw "Not able to get first letter from word to determine word bank.";
      o[r] = t;
    });
})();

💁 Possible Solution

🔦 Context

💻 Code Sample

🌍 Your Environment

Software Version(s)
Parcel v2.9.3
Node v18.16.1
npm/Yarn npm v9.5.1
Operating System Windows 10

moky80 avatar Jul 07 '23 07:07 moky80

I think I may be experiencing something similar with our project. The local dev server will run/build the code properly, but the minified build output is missing a symbol for react-router which breaks the entire app. This is a problem for us in 2.9.2 and 2.9.3 but not in 2.8.1. Out of curiosity, does your example work in 2.8.1?

mellodev avatar Jul 07 '23 17:07 mellodev

Does it work with the --no-optimize CLI flag?

devongovett avatar Jul 08 '23 05:07 devongovett

@devongovett yes, it works with --no-optimize flag.

moky80 avatar Jul 10 '23 05:07 moky80

I think I may be experiencing something similar with our project. The local dev server will run/build the code properly, but the minified build output is missing a symbol for react-router which breaks the entire app. This is a problem for us in 2.9.2 and 2.9.3 but not in 2.8.1. Out of curiosity, does your example work in 2.8.1?

Yes, it works with 2.8.1. The minified for https://github.com/minnie80/test-build-wordlistjs/blob/test-build-with-parcel/src/wordList.js formatted by prettier.io

var Word_List = (function () {
  var r = {},
    t = new Array();
  return (
    (r.isInList = function (r) {
      var o = (r = r.toLowerCase()).charAt(0);
      return t[o].indexOf(r) > -1;
    }),
    (r.getRandomWord = function (r) {
      0 == (r = r || 0) && (r = Math.floor(7 * Math.random()) + 4),
        r < 4 && (r = 4),
        r > 10 && (r = 10);
      var o,
        a,
        n = Math.floor(26 * Math.random()),
        e = String.fromCharCode(n + 97);
      do {
        (o = Math.floor(Math.random() * t[e].length)), (a = t[e][o]);
      } while (a.length != r);
      return a;
    }),
    (r.loadBank = function (r) {
      var o = r[12].charAt(0);
      if (!o)
        throw "Not able to get first letter from word to determine word bank.";
      t[o] = r;
    }),
    r
  );
})();
//# sourceMappingURL=testing.8ef956dc.js.map

moky80 avatar Jul 10 '23 05:07 moky80

I don't mean to hijack this thread, but I feel like I have a similar issue. It's hard to create a reproducible repo, as it seems to be a combination of many factors (and after a full day of debugging, I'm still unsure what).

I'm building a React app, with Orval, TanStack, React Query, Axios, and the dev build works fine. The production build however produces a an error within Axios because of a missing import (link to the specific line that fails in the production build, validator.assertOptions is undefined, thus crashing). In watch mode, or when running with --no-optimize this problem does not occur.

ErikBooij avatar Jul 16 '23 12:07 ErikBooij

The next question is whether this is a bug in Parcel itself or in the new SWC minifier that we switched to in v2.9. Could you all try building your project with @parcel/optimizer-terser instead and see if that fixes the issue? To do that, install @parcel/optimizer-terser with npm and add this to your .parcelrc:

{
  "extends": "@parcel/config-default",
  "optimizers": {
    "*.js": ["@parcel/optimizer-terser"]
  }
}

devongovett avatar Jul 19 '23 21:07 devongovett

Thanks @devongovett, appreciate it! For me that yields a perfectly valid bundle that passes all tests 👌 Hope that helps in your investigation.

ErikBooij avatar Jul 19 '23 22:07 ErikBooij

{
  "extends": "@parcel/config-default",
  "optimizers": {
    "*.js": ["@parcel/optimizer-terser"]
  }
}

yes, that fixed my issue with [email protected]. Thanks!

moky80 avatar Jul 20 '23 13:07 moky80

As I mentioned in #9119, using the terser optimiser also resolved the problem for me. Does that indicates a problem in the swc minifier?

nclemeur avatar Jul 20 '23 23:07 nclemeur

Same problem and resolution here:

  • ✅ dev build works fine
  • ❌ production build with @parcel/optimizer-swc has missing symbols
  • ✅ production build with @parcel/optimizer-terser works fine

shepmaster avatar Jul 21 '23 18:07 shepmaster

Are you all using <script> elements in your HTML without type="module"? I noticed this in the original reproduction, and SWC appears to generate different output depending on the module flag. Is that a common thread here?

devongovett avatar Jul 21 '23 19:07 devongovett

I am using a <script> tag with type="module".

ErikBooij avatar Jul 21 '23 19:07 ErikBooij

Are you all using <script> elements in your HTML without type="module"? I noticed this in the original reproduction, and SWC appears to generate different output depending on the module flag. Is that a common thread here?

We're using type="module" as well

mellodev avatar Jul 21 '23 19:07 mellodev

Likewise, I'm using type="module":

<script type="module" src="app.ts"></script>

That being said, I have noticed that I get two output JS files:

ui/dist/ui.0a6c46e3.js        415 KB    1.63s
ui/dist/ui.6eb97b68.js     415.06 KB    1.65s

Which appears to be differential bundling:

<script type="module" src="/assets/ui.6eb97b68.js"></script>
<script src="/assets/ui.0a6c46e3.js" nomodule defer></script>

I'm surprised that this is happening as I attempted to only target very recent browsers:

  "targets": {
    "default": {
      "distDir": "ui/dist",
      "publicUrl": "/assets",
      "engines": {
        "browsers": "since 2023"
      }
    }
  },

I was testing with Chrome Canary when I noticed the problem, so I'd expect that it was using the type="module" version.

shepmaster avatar Jul 21 '23 20:07 shepmaster

Same error for me, and I fixed it using "@parcel/optimizer-terser"

Jmzp avatar Oct 04 '23 17:10 Jmzp

Following this advice (see also https://github.com/parcel-bundler/parcel/issues/9179), I changed to using the terser optimiser. Is there an update of the swc minifier? Should I now revert to using the swc minifier?

micrology avatar Feb 07 '24 15:02 micrology

I am still using the terser optimiser. Should I revert to the swc minifer now?

micrology avatar Aug 06 '24 10:08 micrology

I removed my usage of @parcel/optimizer-terser and don't appear to have any minification issues. However, that's not a ringing endorsement because I recall that the error was hard to trigger and I have multiple projects using Parcel and some needed this workaround and others didn't. At least at this point, it appears to work for me. 🤷

shepmaster avatar Aug 06 '24 21:08 shepmaster

I've also now removed the optimizer-terser call and it seems to be working for me.

micrology avatar Aug 07 '24 16:08 micrology