'jQuery is not defined' when use ES6 import
Asked Answered
B

2

16

My code:

import $ from 'jquery'
import jQuery from 'jquery'
import owlCarousel from '../../node_modules/owlcarousel/owl-carousel/owl.carousel'

class App {
    …
    _initSlider() {
        $("#partners-carousel").owlCarousel();
    }
}

I have 'jQuery is not defined' in browser console. What's wrong? I can use jQuery as $ in methods of this class, but not with name 'jQuery'.

Betty answered 12/2, 2016 at 9:9 Comment(4)
What are you using to load/transpile your code?Bute
browserify & babelify. Here is gulp task: gulp.task('compile', () => { return browserify( { entries: files.source.script, debug: !production, transform: [babelify.configure({ 'presets': ['es2015'] })] } ) .bundle() .pipe(source('script.js')) .pipe(buffer()) .pipe(production ? uglify() : gutil.noop()) .pipe(gulp.dest(files.dest.scripts)) .pipe(production ? gutil.noop() : livereload()); });Betty
If you are doing this in a browser: developer.mozilla.org/en/docs/web/javascript/reference/…Southeastwardly
@Betty did you find a solution for this?Harcourt
R
44

According to this comment and apply it to your case, when you're doing:

import $ from 'jquery'
import jQuery from 'jquery'

you aren't actually using a named export.

The problem is that when you do import $ ..., import jQuery ... and then import 'owlCarousel' (which depends on jQuery), these are evaluated before, even if you declare window.jQuery = jquery right after importing jquery. That's one of the ways ES6 module semantics differs from CommonJS' require.

One way to get around this is to instead do this:

Create file jquery-global.js

// jquery-global.js
import jquery from 'jquery';
window.jQuery = jquery;
window.$ = jquery;

then import it in you main file:

// main.js
import './jquery-global.js';
import 'owlCarousel' from '../../node_modules/owlcarousel/owl-carousel/owl.carousel'

class App {
  ...
  _initSlider() {
    $("#partners-carousel").owlCarousel();
  }
}

That way you make sure that the jQuery global is defined before owlCarousel is loaded.

Repercussion answered 2/10, 2016 at 19:19 Comment(2)
Indeed this works, but can you please tell us more? Why is the ordering only guaranteed with your method? Is it documented somewhere? Thanks!Weathersby
This seems to be the solution that worked for me. Can you please explain a little more why it happens this way? thanks so much for this solution by the way.Reiss
A
1

@Serge You should have mentioned in your question that you are using browserify & babelify to bundle/transpile your code (I knew it from comments), this will help people find the correct answer to your question.

As of 2021, ECMA2015+/ES6+ don't allow the use of import-maps/bare-module-path natively in the browser. So basically you can't do the following directly in the browser, because the browser doesn't behave like nodejs, it doesn't understand how/where to fetch for the source of your scripts, you can't just say:

import $ from 'jquery'  
import jQuery from 'jquery'

However, you can do this by the help of bundlers like WebPack which opens that door for import-maps/bare-module-path to be used in the browser. Besides, huge work is currently being done to support the implementation of import-maps directly in the browser without the need of bundlers, but it's not implemented yet. I know that this question is old enough for the OP to follow, but in general, you can use WebPack to bundle your code and import your dependencies the way you mentioned.

P.S. Regarding the answer proposed by @egel in Oct 2016 (which is an old answer with limited solutions at that time) some people asked for more clarifications. Please note the following statement by Nicolás Bevacqua regarding the scope of ES6+ modules:

Declarations in ES6 modules are scoped to that module. That means that any variables declared inside a module aren’t available to other modules unless they’re explicitly exported as part of the module’s API (and then imported in the module that wants to access them).

ES6+ module system is awesome and makes things much more organized, but can we fully implement ES6+ modules in the browser without the need of bundlers/transpilers? This is a tough question. Things may get harder when some of your JavaScript dependencies are just old/classic scripts that do not support the ES6+ modules system, and do not use the export keyword to export functions/values for you. Here, developers tend to do some workarounds to solve the problem in hand. The window object is used to attach functions/variables in order to use them across all modules. Here the window object is used as a carrier to transfer functions/data across different modules within your code base, and this is not a recommended approach though.

Below is quoted from javascript.info:

If we really need to make a window-level global variable, we can explicitly assign it to window and access as window.user. But that’s an exception requiring a good reason.

Acoustician answered 5/3, 2021 at 14:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.