parcel-bundler / parcel

The zero configuration build tool for the web. 📦🚀
https://parceljs.org
MIT License
43.38k stars 2.27k forks source link

Experimental scope hoisting is not working correctly and throws error $jJqx$export$utils is not defined #1996

Closed Stradivario closed 1 year ago

Stradivario commented 6 years ago

🐛 bug report

🎛 Configuration

🤔 Expected Behavior

Application should build correctly with --experimental-scope-hoisting argument

😯 Current Behavior

Take a look at the following example: https://github.com/rxdi/starter-client-side

This is a simple starter for Reactive Extension Dependency Injection and when i build this client starter i decided to work and bundle my application with ParcelJS i love it!!!! Since then nothing unusual happens i can start and build my application and everything work flowless!

Then i found out one command --experimental-scope-hoisting this command create bundle size 35% smaller than the original one.So far so good! But when i try to load my application it says some strange error

Uncaught ReferenceError: $jJqx$export$utils is not defined
  ;
    var Vn = {}
      , NK = (e(),
    a)
      , X = $jJqx$export$utils
      , Yn = $jJqx$export$Cipher;
    function KK() {
        this.tmp = new Array(2),
        this.keys = null
    }
    function hb($) {
        Yn.call(this, $);
        var t = new KK;
        this._desState = t,
        this.deriveKeys(t, $.key)
    }
    NK(hb, Yn),
    Vn = hb,

If you want you can try by yourself

git clone  https://github.com/rxdi/starter-client-side

UPDATE: 17:23 12.09.2018 Updated dependency from @rxdi/core@0.0.259 to @rxdi/core@0.0.264 Changes include removing 'crypto' module from the @rxdi/core To face the same bug you need to reset to particular SHA

git reset --hard 713b2bb3d1f878d8f085c7f11eb89d3b321c6b17
npm install

This is passing

parcel build ./src/index.html --target browser

Refresh the page and everything is working!

This is not

parcel build ./src/index.html --target browser --experimental-scope-hoisting

What is the case here ? Does anyone knows anything about it ? Is this intended ?

I think it is comming from Crypto module because in the next line we have 'Cipher' just guessing what is happening.

      , Yn = $jJqx$export$Cipher;

Thanks to all of you!

💁 Possible Solution

Not have anything to say here

🔦 Context

I am trying to create smaller bundle size of my application

💻 Code Sample

@rxdi https://github.com/rxdi/main

@client-side-example - https://github.com/rxdi/starter-client-side

🌍 Your Environment

Software Version(s)
Parcel 1.9.7
Node 8.9.4
npm 6.2.0
Operating System Ubuntu 18.04.1 LTS
Stradivario commented 6 years ago

@DeMoorJasper I commit inside this repository version without 'crypto' module: To face the same bug you need to do is reset branch to particular commit sha:

git clone https://github.com/rxdi/starter-client-side
git reset --hard 713b2bb3d1f878d8f085c7f11eb89d3b321c6b17

RXJS@^6.3.1

git clone https://github.com/rxdi/starter-client-side
npm i
parcel build ./src/index.html --target browser --experimental-scope-hoisting

Try to build application again with experimental hoisting from the latest commit

main.9bb10e35.js:1 Uncaught TypeError: Rj.BehaviorSubject is not a constructor
    at new 87e7140f180c968941d91dfac25474f64fb5223629faf54939f9cf87a9614e9f (main.9bb10e35.js:1)
    at new 7a6346151ce9fa4f8b18cbe9632b92a1956b1c4f29cebb78fea353d534a8400d (main.9bb10e35.js:1)
    at ov.getServiceValue (main.9bb10e35.js:1)
    at ov.get (main.9bb10e35.js:1)
    at Function.get (main.9bb10e35.js:1)
    at main.9bb10e35.js:1
    at Kk (main.9bb10e35.js:1)
    at main.9bb10e35.js:1
    at main.9bb10e35.js:1
    at main.9bb10e35.js:1

Here after i removed 'crypto' module which causing this issue i faced other bug with RXJS.

Should we create other issue or it is related with this one ?

As far as i see because i am using RXJS it is not related with crypto module and bundle for it, we need to create separated issue for it.

Regards, K.T.

n0v1 commented 5 years ago

I get a similar error in a simple Vue.js app (that uses parcel-plugin-inlinesvg) only with --experimental-scope-hoisting:

js.8a80f62d.js:1 ReferenceError: $rLiX$$interop$default is not defined
    at i.data (js.8a80f62d.js:1)
    at Ad (js.8a80f62d.js:1)
    at zd (js.8a80f62d.js:1)
    at xd (js.8a80f62d.js:1)
    at i.Ld.e._init (js.8a80f62d.js:1)
    at new i (js.8a80f62d.js:1)
    at je (js.8a80f62d.js:1)
    at init (js.8a80f62d.js:1)
    at js.8a80f62d.js:1
    at o (js.8a80f62d.js:1)

The bundled source code contains this:

var uf = {};
uf = "<svg width=\"24\" height=\"24\"><path d=\"M20 8h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z\"/></svg>";
var Qg = Ag(uf);
var tf = {
    name: "SvgIcon",
    data: ()=>({
        svg: $rLiX$$interop$default.d
    })
};

but that's the only place where $rLiX$$interop$default.d occurs.

Here is a reproduction repo: https://github.com/n0v1/parcel-scope-hoisting-bug/tree/isolate-icon-bug (see branch isolate-icon-bug branch)

mischnic commented 5 years ago

@n0v1 Your issue isn't related but already fixed in master (so in the next release)

mischnic commented 5 years ago

Reproduction for the original issue, caused by a circular dependency (here: lib.js and lib_des.js)

// index.js
var des = require("./lib.js");
console.log(des.utils);
console.log(des.DES);

// lib.js
exports.utils = require('./lib_utils.js');
exports.DES = require('./lib_des.js');

// lib_des.js
var des = require('./lib.js');
var utils = des.utils;
module.exports = "DES" + utils.permute;

// lib_utils.js
exports.permute = "-PERMUTE!";
n0v1 commented 5 years ago

Thank you @mischnic. I can confirm that my problem is fixed when using parcel-bundler from master.

franciscotln commented 5 years ago

Yesterday I run into a very similar error after building the production version of a react app using the experimental scope hoisting flag. After a few minutes of investigation I noticed that such undeclared variables like Uncaught ReferenceError: $someName$export is not defined occurred in 3 places in my code base and all of them were in directories where I used barrel exports:

src
|__ some-directory
    |__ index.js
    |__ some-file1.js
    |__ some-file2.js
    |__ some-file3.js
|__ some-other-directory
    |__ index.js
    |__ some-file-a.js
    |__ some-file-b.js

where in the files index.js I had something like:

export * from './some-file1'
export * from './some-file2'
export * from './some-file3'

After removing the barrels (index.js files like those) and fixing the imports in other files I could finally run parcel build --experimental-scope-hoisting and the app was properly built, minified and tree-shaken

loganpowell commented 4 years ago

After removing the barrels (index.js files like those) and fixing the imports in other files I could finally run parcel build --experimental-scope-hoisting and the app was properly built, minified and tree-shaken

I may be facing this same issue as I also frequently use barrels. Is this a no-no with --experimental-scope-hoisting? I'm getting cryptic:

Uncaught ReferenceError: $KxTz$exports is not defined

on parcel build with the flag

mdunisch commented 4 years ago

i'm running into to same issue when using Vuetify. They using the same export * from statements (see here: https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/services/index.ts)

My problem now is: i can't change this in Vuetify but only need a few modules of vuetify. When i don't use the --experimental-scope-hoisting flag my js is HUGE.

Any other solution for this? I would really hate to go back to webpack because of this issue

@devongovett or is tree shaking not a Feature for v2?

emirotin commented 4 years ago

Same issue


Input:

import { checkbox } from "material-components-web";
console.log(checkbox.MDCCheckbox);

Output:

parcelRequire = (function (e) {
  var r = "function" == typeof parcelRequire && parcelRequire,
    n = "function" == typeof require && require,
    i = {};
  function u(e, u) {
    if (e in i) return i[e];
    var t = "function" == typeof parcelRequire && parcelRequire;
    if (!u && t) return t(e, !0);
    if (r) return r(e, !0);
    if (n && "string" == typeof e) return n(e);
    var o = new Error("Cannot find module '" + e + "'");
    throw ((o.code = "MODULE_NOT_FOUND"), o);
  }
  return (
    (u.register = function (e, r) {
      i[e] = r;
    }),
    (i = e(u)),
    (u.modules = i),
    u
  );
})(function (require) {
  console.log($f7XH$export$MDCCheckbox);
  return { WSmw: {} };
});

Also a surprisingly different result:

Input:

import { checkbox } from "material-components-web";
console.log(checkbox);

Output:

parcelRequire = (function (e) {
  var r = "function" == typeof parcelRequire && parcelRequire,
    n = "function" == typeof require && require,
    i = {};
  function u(e, u) {
    if (e in i) return i[e];
    var t = "function" == typeof parcelRequire && parcelRequire;
    if (!u && t) return t(e, !0);
    if (r) return r(e, !0);
    if (n && "string" == typeof e) return n(e);
    var o = new Error("Cannot find module '" + e + "'");
    throw ((o.code = "MODULE_NOT_FOUND"), o);
  }
  return (
    (u.register = function (e, r) {
      i[e] = r;
    }),
    (i = e(u)),
    (u.modules = i),
    u
  );
})(function (require) {
  function b(dest, source) {
    Object.keys(source).forEach(function (key) {
      if (key === "default" || key === "__esModule") {
        return;
      }
      Object.defineProperty(dest, key, {
        enumerable: true,
        get: function get() {
          return source[key];
        },
      });
    });
    return dest;
  }
  var a = {};
  b(a, {}), b(a, {}), b(a, {});
  console.log(a);
  return { WSmw: {} };
});
puema commented 3 years ago

I have the same issue with a generated axios client when having the --experimental-scope-hoisting flag on. Without minifying, it works fine.

$dZBD$$interop$default is not defined

  class Qb {
    constructor(r, $ = kb, e = $dZBD$$interop$default.d) {
      (this.basePath = $),
        (this.axios = e),
        r && ((this.configuration = r), (this.basePath = r.basePath || this.basePath));
    }
  }

This is the original class:

export class BaseAPI {
    protected configuration: Configuration | undefined;

    constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) {
        if (configuration) {
            this.configuration = configuration;
            this.basePath = configuration.basePath || this.basePath;
        }
    }
};

@devongovett @mischnic Any idea what the issue is about? I'd love to stick to parcel, but without a working minified tree shaken bundle it's hard...

mischnic commented 1 year ago

Should be fixed with Parcel 2