evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
37.94k stars 1.13k forks source link

Build including bootstrap-multiselect, Uncaught TypeError: Cannot read properties of undefined (reading 'fn') #1733

Closed hamilton-keisuke closed 2 years ago

hamilton-keisuke commented 2 years ago

Excuse me. I want to build with esbuild including bootstrap-multiselect.

However, I get the following error in browser's js console.

index.js:7069 Uncaught TypeError: Cannot read properties of undefined (reading 'fn')
    at index.js:7069
    at index.js:5923
    at node_modules/bootstrap-multiselect/dist/js/bootstrap-multiselect.js (index.js:5925)
    at __require2 (index.js:17)
    at index.js:7099
    at index.js:7101

Here is sample code, reproducing this problem. https://github.com/hamilton-keisuke/esbuild-bootstrap-multiselect-sample

In webpack, I solved it with imports-loader as below.

module.exports = {
  module: {
    rules: [
      {
        test: /bootstrap-multiselect/,
        use: [
          {
            loader: 'imports-loader',
            options: {
              wrapper: 'window',
              additionalCode: 'var define = false;'
            },
          },
        ],
      }
    ],
  }
}

I want to resolve this probrem. Is there any way?

hyrious commented 2 years ago

The bootstrap-multiselect does not export a valid commonjs module, in which case esbuild won't handle it well. If you look at the top of that library, it does handle AMD and global variable cases.

At the esbuild side, a top level this will be changed to exports in commonjs context, see it in action. This allows some no-dependency libraries to partially work. But bootstrap-multiselect depends on a global name $, in which case exports.$ (originally this.$) does not exist in such isolated context.

I think you can write a plugin to edit that library to a valid commonjs module, or just replace the global this to window by --define:this=window.

hamilton-keisuke commented 2 years ago

Thanks a lot. define:this=window works well. I will try write plugin, too :D