floating-ui: Uncaught TypeError: Popper is not a constructor

I’m seeing the following error message when using Popper 1.9.8:

Uncaught TypeError: Popper is not a constructor

I’m trying to import Popper as a module using Webpack (Laravel Mix) and tried several combinations:

import Popper from 'popper.js';
require('popper.js/dist/popper.js' );
require('popper.js/dist/esm/popper.js' );
require('popper.js/dist/umd/popper.js' );
window.Popper = require('popper.js/dist/esm/popper.js' );

How can I import Popper, it doesn’t matter if I use import * from or require().

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 33 (13 by maintainers)

Most upvoted comments

I got into an event stranger situation:

My main file (stripped down):

import Popper from 'popper.js/dist/umd/popper.js';
window.Popper = Popper;

import 'bootstrap/js/src/util';
import 'bootstrap/js/src/dropdown';

This leads to an error: Uncaught Error: Bootstrap dropdown require Popper.js.

Adding the umd bundle as an alias in Mix’s autoload makes it work:

mix.autoload({
   jquery: ['jQuery'],
   'popper.js/dist/umd/popper.js': ['Popper']
});

Now, I’m actually happy that it works, but I don’t fully understand why it wont if I do not add it to webpack aliases (via mix.autoload). I’m not asking you to answer my question, I’m just leaving this here for the records.

I have the same issue as @tillkruss, and I’m using Laravel Mix as well.

I have tried every combination of import or require, set window.Popper to Popper or Popper.default, and so on. I also added autoloading options to Laravel Mix config file:

mix.autoload({
   jquery: ['jQuery'], // Bootstrap
   'popper.js': ['Popper'] // Bootstrap
});

However, the only way I got this working was by manually editing Bootstrap’s dropdown.js to use new Popper.default(...) instead of just new Popper(...).

Anybody knows its ways around this? What am I doing wrong?

Just to add to this discussion, I got popper.js working with bootstrap (latest version, bootstrap 4 beta) in my laravel 5.4 application by changing Laravel’s bootstrap.js file (located in path/to/app/resources/assets/js/) as follows:

try {
    window.$ = window.jQuery = require('jquery');
    window.Popper = require('popper.js').default; //for popper
   require('bootstrap'); //for bootstrap v4 instead of bootstrap-sass package
} catch (e) {}

This ensures popper is loaded before bootstrap, and seems to work fine. If I encounter any difficulties or gotchas with this approach I’ll report back.

I ended up doing the following

(<any>window).Popper  = require('popper.js').default;

…and things started suddenly working. It’s ugly, but at least it works. Popper.js is now available both for Popper and window.Popper and window.Popper returns the .ctor instead of an object.

As far as I understand, the reason seems to be how Popper.js is being exported:

export default class Popper {}

In this case, default is treated as a named export. When I invoke require('expose-loader?Popper!popper.js'), I get just the class (which ends up in window.Popper due to expose-loader) and not the default export, which is just a property. So I have to manually assign it to window.

This effect could be changed by writing:

module.exports = class Popper {}

I’m pretty much a beginner in JS, the various module systems and what not, so please correct me if I’m wrong on this assumption so I don’t confuse others. 😃

Webpack: 3.5.6

new webpack.ProvidePlugin({
    $: "jquery",
    jQuery: "jquery",
    Popper: 'popper.js/dist/umd/popper.js'
})

This works for me.

why is the .default needed?

You have to manually assign Popper to window.Popper since Bootstrap isn’t importing the dependency but just checking for its existence in window


window.jQuery = window.$ = require('jquery');

import Popper from 'popper.js';
window.Popper = Popper;

require('bootstrap/js/src/dropdown');

Here’s what worked for me using Laravel Mix

import 'jquery';
import Popper from 'popper.js'; //instead of import Popper from 'popper.js/dist/umd/popper.js'; for a small file size
window.Popper = Popper;
import 'bootstrap';

and in my webpack.mix.js file i auto them like so

 .autoload({
        'jquery': ['$', 'window.$', 'jQuery', 'window.jQuery'], //extract into the global variable space
        'popper.js': ['Popper', 'window.Popper']
    })

I said, next release, after the first beta. They have rewritten the way they manage the dependencies.

new webpack.ProvidePlugin({
    jQuery: 'jquery',
    Popper: ['popper.js', 'default'],
}),

Here is what fixed it for me:

mix.webpackConfig({
    resolve: {
        alias: {
            jquery: "jquery/src/jquery",
            'popper.js' : "popper.js/dist/umd/popper.js"
        }
    }
});

Now you can do autoload with no problems:

mix.autoload({
    'jquery': ['$', 'jQuery', 'window.jQuery'],
    'popper.js': ['Popper', 'window.Popper']
});

Yes, this could be done as one but I just like to separate it. Hope this helps someone

This works for me in my Laravel 5.4

bootstrap.js file

try {
    window.$ = window.jQuery = require('jquery');
    window.Popper = require('popper.js').default;
    require('bootstrap');
} catch (e) {}  

webpack.mix.js file

mix.autoload({
   jquery: ['$', 'jQuery', 'window.jQuery'],
   'popper.js': ['Popper', 'window.Popper'],
});