parcel-bundler / parcel

The zero configuration build tool for the web. πŸ“¦πŸš€
https://parceljs.org
MIT License
43.47k stars 2.27k forks source link

parcel build produces wrong minified js #9124

Open moky80 opened 1 year ago

moky80 commented 1 year ago

πŸ› 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:

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
mellodev commented 1 year ago

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?

devongovett commented 1 year ago

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

moky80 commented 1 year ago

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

moky80 commented 1 year ago

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
ErikBooij commented 1 year ago

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.

devongovett commented 1 year ago

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"]
  }
}
ErikBooij commented 1 year ago

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

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

yes, that fixed my issue with parcel@2.9.3. Thanks!

nclemeur commented 1 year ago

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

shepmaster commented 1 year ago

Same problem and resolution here:

devongovett commented 1 year ago

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?

ErikBooij commented 1 year ago

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

mellodev commented 1 year ago

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

shepmaster commented 1 year ago

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.

Jmzp commented 1 year ago

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

micrology commented 8 months ago

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 commented 2 months ago

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

shepmaster commented 2 months ago

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. 🀷

micrology commented 2 months ago

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