Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.10.2 appears to produce circular references where __commonJS is not defined #1070

Closed
pheuter opened this issue Mar 27, 2021 · 13 comments
Closed

Comments

@pheuter
Copy link

pheuter commented Mar 27, 2021

TypeError: undefined is not a function (near '...__commonJS...')

image

This likely has to do with the breaking changes in v0.10.0, No longer support module or exports in an ESM file. I'm guessing at some point in the dependency chain there's an isarray npm module being required and it has some problematic usage of module exports?

The problem is I have no control over this particular dependency.

@pheuter
Copy link
Author

pheuter commented Mar 27, 2021

UPDATE: Upon further debugging, it appears that this issue only comes up in v0.10.2, and appears to work fine in v0.10.0.

@pheuter pheuter changed the title v0.10.0 appears to break deeply nested npm module isarray v0.10.2 appears to break deeply nested npm module isarray Mar 27, 2021
@evanw
Copy link
Owner

evanw commented Mar 27, 2021

Is it possible to provide a code sample that would allow me to reproduce the problem?

@pheuter
Copy link
Author

pheuter commented Mar 27, 2021

Having difficulties reproducing in an isolated code sample, but have some more info from digging deeper.

Two files are generated: index.js and chunk-xyz.js:

index.js (sample from top of file)

import {
  DeveloperMode,
  PrivateRoute,
  ProvideAuth,
  QueryClientProvider,
  React,
  Subscribable,
  __commonJS,
  __toModule,
  _extends,
  _inheritsLoose,
  _objectWithoutPropertiesLoose,
  // ... more app-specific dependencies
} from "/build/chunk-xyz";

// ../node_modules/isarray/index.js
var require_isarray = __commonJS((exports, module) => { // NOTE: this is where the error is thrown
  module.exports = Array.isArray || function(arr) {
    return Object.prototype.toString.call(arr) == "[object Array]";
  };
});

chunk-xyz.js (sample from top of file)

import {
  Route,
  define_BUILD_ENV_default,
  useMutation
} from "/build//.//index.js";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
var __commonJS = (cb, mod) => () => (mod || cb((mod = {exports: {}}).exports, mod), mod.exports);
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, {get: all[name], enumerable: true});
};

If I'm understanding correctly, there's a possible circular reference here between index.js and chunk-xyz.js, so when index depends on __commonJS coming from chunk, it isn't actually defined yet?

@pheuter pheuter changed the title v0.10.2 appears to break deeply nested npm module isarray v0.10.2 appears to produce circular references where __commonJS is not defined Mar 27, 2021
@evanw
Copy link
Owner

evanw commented Mar 27, 2021

The bug here seems to be that a circular reference is generated in the first place. I believe one shouldn't ever be generated at all. The bug is presumably something to do with the Route, define_BUILD_ENV_default, and useMutation imports. If these symbols are used from another entry point other than index.js, then they should be moved into the shared output file chunk-xyz.js instead of residing in the entry point output file index.js. Unfortunately this is going to be tough for me to fix without a way to reproduce it myself. I checked and I can't reproduce this on any of my test projects.

Independent of that, this part of your reply also had me confused:

Two files are generated: index.js and chunk-xyz.js:

Is that true? If so, are you attempting to load chunk-xyz.js instead of loading index.js? That would give you this error:

$ cat index.mjs 
import { __commonJS } from "./chunk-xyz.mjs";
var require_isarray = __commonJS();

$ cat chunk-xyz.mjs 
import "./index.mjs";
export var __commonJS = () => {};

$ node index.mjs 

$ node chunk-xyz.mjs 
index.mjs:2
var require_isarray = __commonJS();
                      ^

TypeError: __commonJS is not a function

But the entry point index.js should be loaded first because it's the entry point.

@pheuter
Copy link
Author

pheuter commented Mar 27, 2021

I have a single entrypoint:

entryPoints: ['./src/index.tsx'],
bundle: true,
splitting: true,
format: 'esm'

that's loaded like so:

<body>
  <div id="app"></div>
  <script src="build/index.js" type="module"></script>
</body>

Within that entrypoint, I do make use of lazy loading to create chunks for routes that have large dependencies, like the Dashboard view that pulls in a charting library:

(snippet simplified for the purposes of sharing—React Suspense is loaded properly here)

import './styles/base.css';

const Dashboard = lazy(() => import('./modules/Dashboard'));

function App() {
  return (
    <Route path="/dashboard">
      <Dashboard />
    </Route>
  );
}

After esbuild runs, it generates all of these files:

  • index.js
  • index.css
  • chunk-xyz.js
  • modules/Dashboard/index.js

Both index.js and modules/Dashboard/index.js import from chunk-xyz.js, and for some reason at the very top of chunk it imports those 3 items you called out from the top level index.js.

@pheuter
Copy link
Author

pheuter commented Mar 28, 2021

One weird thing I'm noticing is simply changing the name of one of my global define variables removes it from the chunk import:

In esbuild config:

define: {
    global: JSON.stringify({}),
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
    __VERSION__: JSON.stringify(packageJson.version),
    __COMMIT_HASH__: JSON.stringify(commitHash),
    __BUILD_DATE__: JSON.stringify(new Date()),
    __BUILD_ENV__: JSON.stringify(clientBuildEnv)
}

Top of chunk:

import {
  Route,
  define_BUILD_ENV_default,
  useMutation
} from "/build//.//index.js";

And then top of chunk after renaming __BUILD_ENV__ to __BUILDENV__:

import {
  Route,
  useMutation
} from "/build//.//index.js";

@ggoodman
Copy link

ggoodman commented Mar 29, 2021

I'm also observing this issue but also don't have a small reproduction (yet).

Perhaps it's worth noting that I have a circular dependency loop but for type-only imports. @evanw maybe that bit of info could help identify the issue. That circular dependency is reported by separate tooling (rollup-plugin-dts). That being said, it seems as if the circular dependency is being produced by tsc and may not exist in the original source 🕵🏼.

EDIT: Spoke too soon. There was indeed a circular dependency in the code.

@pheuter
Copy link
Author

pheuter commented Mar 30, 2021

It looks like v0.11.2 fixes the issue I was having on v0.10.2 with no code changes in the app. There's still a couple of imports at the top of chunk.js but it no longer results in any runtime errors.

@evanw
Copy link
Owner

evanw commented Apr 3, 2021

This is likely a duplicate of #1081.

@evanw
Copy link
Owner

evanw commented Apr 3, 2021

Could you check again with version 0.11.5? I suspect that this issue will be resolved by the latest release.

@pheuter
Copy link
Author

pheuter commented Apr 4, 2021

@evanw 0.11.5 works 👍

@pheuter
Copy link
Author

pheuter commented Apr 4, 2021

fwiw it worked in 0.11.2 as well

@evanw
Copy link
Owner

evanw commented Apr 7, 2021

Closing as it sounds like this has been fixed.

@evanw evanw closed this as completed Apr 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants