Error "require is not defined" when running bundled files
Closed this issue · 3 comments
I'm using esbuild to bundle the files in a folder. One of those files is a jquery plugin, that will check for the exports object, and if the exports object is defined, then will call the require
method. Something like this:
!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports?e(require("jquery")):e(window.jQuery||window.Zepto)}
Now, esbuild bundles that file like this:
(
var __commonJS = function(callback, module) {
return function() {
if (!module) {
module = {exports: {}};
callback(module.exports, module);
}
return module.exports;
};
};
(...)
var require_jquery_magnific_popup_min = __commonJS(function(exports) {
!function(e) {
typeof define == "function" && define.amd ? define(["jquery"], e) : typeof exports == "object" ? e(require("jquery")) : e(window.jQuery || window.Zepto);
}(function(d) {
So the exports object is passed in to the module, and the module then tries to call require()
, which throws an error because i'm not using requireJs on this project. Something like this:
If i manually set the exports object to false on the output file, the bundled code works as expected, without throwing an error.
(
var __commonJS = function(callback, module) {
return function() {
if (!module) {
module = {exports: false};
callback(module.exports, module);
}
return module.exports;
};
};
So, how can override this exports object for every build i make, or can i have an option to set the value of the exports object?
Data
main.js
esbuild.build({
entryPoints: ["imports.js"],
bundle: true,
//minify: true,
format: 'iife',
platform: 'browser',
target: [
'es5',
],
outfile:"outfile.js",
external: ['jquery',"window"],
}).catch((err) => {
console.log(err)
})
imports.js
import("./src/js/jquery-magnific-popup.min.js")
This happens because esbuild supports CommonJS modules, so exports
is an object. Marking a file as external means that it is considered available in the host environment instead of included in the bundle. For esbuild that means it's assumed that it can be loaded using require
. This is sometimes useful as an escape hatch since you can provide your own window.require
implementation.
Some ideas for what to do here:
-
You could rewrite the code for this jQuery plugin to omit the
require("jquery")
code. -
You could install the
jquery
package instead of marking it as external. I'm assuming you marked thejquery
package as external because it's not supposed to be bundled, but I thought I'd include this option in case that's not a requirement. -
Instead of marking
jquery
as external, you can shim it for the browser by adding this to yourpackage.json
file:"browser": { "jquery": "./jquery-shim.js" },
and creating a file called
jquery-shim.js
that looks like this:// jquery-shim.js module.exports = window.jQuery || window.Zepto
This causes esbuild to transform
require("jquery")
intowindow.jQuery || window.Zepto
. Does that work for you? -
You could run some code like this before importing this plugin:
window.require = name => { if (name === 'jquery') return window.jQuery || window.Zepto else throw new Error(`Cannot require ${name}`) }
So, how can override this exports object for every build i make
The exports
variable is important for CommonJS modules, so overwriting it would probably break other packages you're using.
I eventually worked around this, but i think i found another bug. I will try the solutions provided. Thanks!
Closing. Sounds like this was resolved.