-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
module2.require is not a function when bundling for node #455
Comments
That's the first time I've seen something like this. It looks like they are deliberately trying to mess with the bundler's import logic. Perhaps
This is because Perhaps |
I certainly think that's true for |
My only concern about just changing |
Yes. Because of Even I think the easiest way to fix this particular package would actually be to forward |
module.require and require are semantically equivalent. This is why webpack
created __non_webpack_require__ for the host require. This forwarding
implemented is incorrect.
…On Tue, Oct 13, 2020 at 22:25 Evan Wallace ***@***.***> wrote:
Closed #455 <#455> via 9dbe4c8
<9dbe4c8>
.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#455 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAESFSQKXI4UV4DQ4GCQSY3SKUY4FANCNFSM4SPN5IHA>
.
|
The confusion might be that the ‘module’ object identity is never typically
shared in the CJS ecosystem between modules such that the common case
always remains contextual.
…On Wed, Oct 14, 2020 at 03:51 Guy Bedford ***@***.***> wrote:
module.require and require are semantically equivalent. This is why
webpack created __non_webpack_require__ for the host require. This
forwarding implemented is incorrect.
On Tue, Oct 13, 2020 at 22:25 Evan Wallace ***@***.***>
wrote:
> Closed #455 <#455> via 9dbe4c8
> <9dbe4c8>
> .
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <#455 (comment)>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAESFSQKXI4UV4DQ4GCQSY3SKUY4FANCNFSM4SPN5IHA>
> .
>
|
One problem is that var m = module;
m.require('./file'); I assume Webpack can handle this because it can emulate the file system in the bundle, but emulating the file system is a non-goal in esbuild. |
Given that the examples we've seen so far have specifically been designed to stop bundlers from doing anything, is there a way to just leave such usages of |
@evanw the assumptions are mostly heuristical conventions. I've never seen arbitrary module assignment like that in the wild. Module construction is used for custom require virtualization ( |
It all makes sense now :) Note that a scoped module binding is very different to the contextual one of course! |
Hmmm? This is still just doing |
Oh, interesting. Someone else has been maintaining Unrelated, I also found a similar open issue for Parcel: parcel-bundler/parcel#3776. It looks like this library actually expects Really the problem is that these packages aren't following the recommended way to do this, which is to use the
Do you have any examples of such code? I was unable to find any examples that don't just want the host's |
There was an earlier version of module.require('./locale/' + name); and the tool I was working on at the time was designed to handle these cases via globbing analysis. So I guess in theory it was an attempt to use it as the opt-out actually. But it's not really a reliable opt-out unless we want to explictly decide to make it one and actively drive that. If it's only explicit CallExpression cases for the unbound scope I think it's fine - it would still be undefined in other cases. In short, if esbuild aims to build for Node.js equally then it probably should detect it. Otherwise it could be ok to leave out. |
Note to self: I think a better version of my initial approach would be something like this: export var __commonJS = (callback, module) => () => {
if (!module) {
- module = {exports: {}}
+ module = __platform === 'node' ? {exports: {}, require} : {exports: {}}
callback(module.exports, module)
}
return module.exports
} That way |
@evanw I hope we can treat building for Node.js ES modules as first class. |
What do you mean by that? |
As in not needing to rely on |
Ah, I see. Do you mean that you'd expect esbuild to polyfill import { createRequire } from 'module'
var require = createRequire(import.meta.url) Actually, why doesn't that already happen in node? Why is |
@evanw what's your stance on just leaving |
FWIW, |
@evanw I think avoiding require internalization is ideal. Even avoiding createRequire is ideal. It's not always possible, but in many cases there are techniques. For example the
The benefit of converting CommonJS modules into full ES modules that are platform independent is the same build techniques can then be used to eg virtualize CommonJS modules for Node.js in environments like Deno. The universal semantics and all. Eg converting There are of course cases that don't convert, and then falling back to some environment require gets the final compatibility. But right up until that point to build for ESM entirely without relying on an environment require helps the ecosystem IMO. Lines to be drawn though of course, but I always push for the universal side when possible. |
I just did a survey of the major bundlers. Should have done that at the start, sorry. Here's what I tested: // index.js
require('./nested') // nested.js
function req(mod, path) { return mod.require(path) }
console.log(`require('fs'):`, !!require('fs'))
console.log(`module.require('fs'):`, !!module.require('fs'))
console.log(`mod.require('fs'):`, !!req(module, 'fs'))
Webpack appears to be unusual in that it replaces
Right now I am leaving |
Well, you're not. It's being changed to I meant literally leaving it as |
Can confirm this no longer throws in 0.7.16 – thanks @evanw ! |
I am encountering code that uses |
Given:
test.js:
test2.js:
And running:
When I look at the bundled output, it seems that no arguments are passed in to
require_test2
:This pattern is used in the real world, for example here:
https://github.com/apollographql/apollo-server/blob/570f548b88750a06fbf5f67a4abe78fb0f870ccd/packages/apollo-server-core/src/utils/createSHA.ts#L5-L7
I've also tried passing
--define:module.require=require
and--define:module2.require=require
but neither of them seem to have any effect (should I open a separate bug for that?)The text was updated successfully, but these errors were encountered: