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

Error "require is not defined" when running bundled files #506

Closed
alicescfernandes opened this issue Nov 5, 2020 · 3 comments
Closed

Error "require is not defined" when running bundled files #506

alicescfernandes opened this issue Nov 5, 2020 · 3 comments

Comments

@alicescfernandes
Copy link

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 requiremethod. 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")
@evanw
Copy link
Owner

evanw commented Nov 5, 2020

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 the jquery 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 your package.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") into window.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.

@alicescfernandes
Copy link
Author

I eventually worked around this, but i think i found another bug. I will try the solutions provided. Thanks!

@evanw
Copy link
Owner

evanw commented Nov 13, 2020

Closing. Sounds like this was resolved.

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

2 participants