165

I'm writing a new app using (JavaScript) ES6 syntax through babel transpiler and the preset-es2015 plugins, as well as semantic-ui for the style.

index.js

import * as stylesheet from '../assets/styles/app.scss';
import * as jquery2 from '../dist/scripts/jquery.min';
import * as jquery3 from '../node_modules/jquery/dist/jquery.min';

console.log($('my-app'));

index.html

<!DOCTYPE html>
<html lang="fr">
<head>
<body>
<script src="dist/app.js"></script>
</body>
</html>

Project structure

.
├── app/
│   ├── index.js
├── assets/
├── dist/
│   ├── scripts/
│   │   ├── jquery.min.js
├── index.html
├── node_modules/
│   ├── jquery/
│   │   ├── dist/
│   │   │   ├── jquery.min.js
├── package.json
└── tests/

package.json

  …
  "scripts": {
    "build:app": "browserify -e ./app/index.js -o ./dist/app.js",
    "copy:jquery": "cpy 'node_modules/jquery/dist/jquery.min.js' ./dist/scripts/",
    …
  },
  "devDependencies": {
    "babel-core": "6.3.x",
    "babel-preset-es2015": "6.3.x",
    "babelify": "7.2.x",
    "cpy": "3.4.x",
    "npm-run-all": "1.4.x",
    "sassify": "0.9.x",
    "semantic-ui": "2.1.x",
    …
  },
  "browserify": {
    "transform": [
      [ "babelify", { "presets": [ "es2015"]}],
      [ "sassify", { "auto-inject": true}]
    ]
  }

Question

Using classic <script> tag to import jquery works fine, but I'm trying to use the ES6 syntax.

  • How do I import jquery to satisfy semantic-ui using ES6 import syntax?
  • Should I import from the node_modules/ directory or my dist/ (where I copy everything)?
Muhammad Reda
  • 26,379
  • 14
  • 93
  • 105
Édouard Lopez
  • 40,270
  • 28
  • 126
  • 178
  • 2
    Well, importing from `dist` doesn't make sense since that is your distribution folder with production ready app. Building your app should take what's inside node modules and add it to the dist folder, jQuery included. – nem035 Dec 17 '15 at 15:42
  • Nor does importing from an *scss* file. Unless there's some awesome plugin I'm missing out on! – CodingIntrigue Dec 17 '15 at 15:58
  • @RGraham it's called [sassify](https://www.npmjs.com/package/sassify), a browserify plugin. I'm inspiring myself from [oncletom gist](https://gist.github.com/oncletom/1e233f2100c4e0877922) – Édouard Lopez Dec 17 '15 at 15:59
  • I will check that out, thanks! – CodingIntrigue Dec 17 '15 at 16:00
  • @RGraham - the syntax looks odd, but using "require" for css / sass files is encouraged with build tools like webpack + babel. eg. require("../node_modules/bootstrap/dist/css/bootstrap.min.css"); – arcseldon Dec 18 '15 at 10:31
  • @arcseldon Agreed, that's an interesting approach to modularisation - glad I asked! – CodingIntrigue Dec 18 '15 at 10:33
  • no worries, appreciate here we are discussing ES6 syntax for module import and not commonjs but ultimately same concepts at play. – arcseldon Dec 18 '15 at 10:40
  • Why not use it globally. What is the problem with that? – Ali Gajani Sep 03 '16 at 04:08

18 Answers18

165

index.js

import {$,jQuery} from 'jquery';
// export for others scripts to use
window.$ = $;
window.jQuery = jQuery;

First, as @nem suggested in comment, the import should be done from node_modules/:

Well, importing from dist/ doesn't make sense since that is your distribution folder with production ready app. Building your app should take what's inside node_modules/ and add it to the dist/ folder, jQuery included.

Next, the glob –* as– is wrong as I know what object I'm importing (e.g. jQuery and $), so a straigforward import statement will work.

Last you need to expose it to other scripts using the window.$ = $.

Then, I import as both $ and jQuery to cover all usages, browserify remove import duplication, so no overhead here! ^o^y

Édouard Lopez
  • 40,270
  • 28
  • 126
  • 178
  • 6
    Not sure if any y'all still around but could you explain the need for `window.$ = $`. I don't understand why that's needed. Won't other scripts be automatically bundled into a single `js` script when browserify does it's magic? – qarthandso Aug 20 '16 at 12:36
  • May be for development purpose? – Asim K T Sep 04 '16 at 10:44
  • 2
    @qarthandso `window` is a global object so attaching `jquery` or `$` to it make it available to everywhere (see http://stackoverflow.com/a/9895261/802365) – Édouard Lopez Sep 06 '16 at 08:27
  • 14
    Why not just have `import {$,jQuery} from 'jquery';`? Why so many imports? – Jackie Sep 09 '16 at 13:16
  • 4
    How you find the name exact class name , ie `jQuery` ? – Avinash Raj Oct 09 '16 at 08:59
  • @AvinashRaj it's in the [source of jQuery](https://github.com/jquery/jquery/blob/52e24471c89b80e6208b4987bb76994e64c1e489/src/exports/global.js#L31) – Édouard Lopez Oct 10 '16 at 09:11
  • 18
    I either get ```Module '"jquery"' has no exported member 'jQuery'``` or ```Module '"jquery"' has no default export``` what am I missing please? – daslicht Nov 11 '16 at 18:29
  • 6
    Older versions of jQuery don't use named exports. Newer versions do. The method of import depends on which version of jQuery you're using. – pmont Jan 03 '18 at 06:57
  • 1
    How do we achieve this with jQuery 2.x then? – IronSean Jan 15 '18 at 20:15
  • @IronSean I would say import {jQuery} from 'jquery'; window.$ = jQuery; window.jQuery = jQuery; – user210757 Oct 11 '18 at 17:20
  • ```import "../node_modules/jquery/dist/jquery.js"; const element = $("#abc");``` – koalix May 29 '19 at 06:42
  • I get the same error as daslicht even though I'm using the most recent version (3.5.1). – Galactic Ketchup May 14 '20 at 00:50
  • @ÉdouardLopez and if I don't want make it available to everywhere I can not assign it to window? I created [question here](https://stackoverflow.com/questions/63247885/why-import-as-from-jquery-doesnt-work) but it was closed. I don't understand why lodash working and jquery not. –  Aug 04 '20 at 15:16
77

Based on the solution of Édouard Lopez, but in two lines:

import jQuery from "jquery";
window.$ = window.jQuery = jQuery;
ha7ilm
  • 1,433
  • 13
  • 11
40

You can create a module converter like below:

// jquery.module.js
import 'https://code.jquery.com/jquery-3.6.0.min.js'
export default window.jQuery.noConflict(true)

This will remove global variables introduced by jQuery (jQuery & $) and export jQuery object as default.

Then use it in your script:

// script.js
import $ from "./jquery.module.js";
    
$(function(){
  $('body').text('youpi!');
});

Do not forget to load it as a module in your document:

<script type='module' src='./script.js'></script>

http://plnkr.co/edit/a59ETj3Yo2PJ0Aqkxbeu?p=preview

Yukulélé
  • 15,644
  • 10
  • 70
  • 94
  • 2
    This one helped! I generally like to try out basics before using any IDE/DevEnv. Without using Node/NPM/Babble I wanted to understand ES6 import and export. I had managed to get basic import and export working but was struggling with jquery inclusion. I had my custom code written as module but kept referencing jquery in its traditional way using the script tag in html. So I ended up having 2 script tags one to include jquery and other to include app.js. With your answer, I could get rid of my first jquery script tag and used the intermediate jquery.module.js as you suggested. – sidnc86 May 29 '19 at 17:43
  • 1
    This solution also allows to extend jquery with libraries that build on top of it. `import "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js"; import "https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"; import "https://cdnjs.cloudflare.com/ajax/libs/notify/0.4.2/notify.js"; // export jquery with cookies and notify export default window.jQuery.noConflict(true);` – 8ctopus Feb 15 '22 at 04:49
  • 1
    This one works in TypeScript. – Huanhuan Kuo Jul 10 '22 at 11:17
18

Import the entire JQuery's contents in the Global scope. This inserts $ into the current scope, containing all the exported bindings from the JQuery.

import * as $ from 'jquery';

Now the $ belongs to the window object.

ivan hertz
  • 185
  • 1
  • 6
  • 2
    this worked for me. The top "import {jQuery as $} from 'jquery';" gives an error saying "jQuery" not found. – SpaceMonkey Jan 29 '18 at 17:20
  • I tested all the above codes and just this worked for me. also, I added `window.$ = window.jQuery = $;` for those codes that are before load event – Armin.G Nov 24 '21 at 11:57
  • ReferenceError: jQuery is not defined ! Why? – albert Apr 11 '22 at 05:14
10

webpack users, add the below to your plugins array.

let plugins = [
  // expose $ and jQuery to global scope.
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery'
  })
];
Muhammad Reda
  • 26,379
  • 14
  • 93
  • 105
  • 4
    What's the pro of this approach ? Cause you're binding yourself to your building tool here. – Édouard Lopez Jul 24 '17 at 12:51
  • this is the only way I got it working. I tried `import {$, jQuery} from 'jquery';` but id didn't work, I believe because it's not defined (imported) in other modules. – Muhammad Reda Jul 25 '17 at 06:47
  • 2
    This is the best solution for webpack users because jQuery should available globally in all files, without the redundant import statements. – Amir Aug 15 '18 at 20:06
10

If it helps anyone, javascript import statements are hoisted. Thus, if a library has a dependency (eg bootstrap) on jquery in the global namespace (window), this will NOT work:

import {$,jQuery} from 'jquery';
window.$ = $;
window.jQuery = jQuery;
import 'bootstrap/dist/js/bootstrap.min';

This is because the import of bootstrap is hoisted and evaluated before jQuery is attached to window.

One way to get around this is to not import jQuery directly, but instead import a module which itself imports jQuery AND attaches it to the window.

import jQuery from './util/leaked-jquery';
import 'bootstrap/dist/js/bootstrap.min';

where leaked-jquery looks like

import {$,jQuery} from 'jquery';
window.$ = $;
window.jQuery = jQuery;
export default $;
export { jQuery };

EG, https://github.com/craigmichaelmartin/weather-app--birch/blob/4d9f3b03719e0a2ea3fb5ddbbfc453a10e9843c6/javascript/util/leak_jquery.js

sandre89
  • 5,218
  • 2
  • 43
  • 64
craigmichaelmartin
  • 6,091
  • 1
  • 21
  • 25
  • Why there is `import jQuery from './util/leaked-jquery';` and not `import $ from './util/leaked-jquery';` – Čamo Jul 22 '21 at 08:39
  • If I call `log( window.$ )` inside the leaked-jquery file it is undefined. Why? – Čamo Jul 22 '21 at 09:10
9

The accepted answer did not work for me
note : using rollup js dont know if this answer belongs here
after
npm i --save jquery
in custom.js

import {$, jQuery} from 'jquery';

or

import {jQuery as $} from 'jquery';

i was getting error : Module ...node_modules/jquery/dist/jquery.js does not export jQuery
or
Module ...node_modules/jquery/dist/jquery.js does not export $
rollup.config.js

export default {
    entry: 'source/custom',
    dest: 'dist/custom.min.js',
    plugins: [
        inject({
            include: '**/*.js',
            exclude: 'node_modules/**',
            jQuery: 'jquery',
            // $: 'jquery'
        }),
        nodeResolve({
            jsnext: true,
        }),
        babel(),
        // uglify({}, minify),
    ],
    external: [],
    format: 'iife', //'cjs'
    moduleName: 'mycustom',
};

instead of rollup inject, tried

commonjs({
   namedExports: {
     // left-hand side can be an absolute path, a path
     // relative to the current directory, or the name
     // of a module in node_modules
     // 'node_modules/jquery/dist/jquery.js': [ '$' ]
     // 'node_modules/jquery/dist/jquery.js': [ 'jQuery' ]
        'jQuery': [ '$' ]
},
format: 'cjs' //'iife'
};

package.json

  "devDependencies": {
    "babel-cli": "^6.10.1",
    "babel-core": "^6.10.4",
    "babel-eslint": "6.1.0",
    "babel-loader": "^6.2.4",
    "babel-plugin-external-helpers": "6.18.0",
    "babel-preset-es2015": "^6.9.0",
    "babel-register": "6.9.0",
    "eslint": "2.12.0",
    "eslint-config-airbnb-base": "3.0.1",
    "eslint-plugin-import": "1.8.1",
    "rollup": "0.33.0",
    "rollup-plugin-babel": "2.6.1",
    "rollup-plugin-commonjs": "3.1.0",
    "rollup-plugin-inject": "^2.0.0",
    "rollup-plugin-node-resolve": "2.0.0",
    "rollup-plugin-uglify": "1.0.1",
    "uglify-js": "2.7.0"
  },
  "scripts": {
    "build": "rollup -c",
  },

This worked :
removed the rollup inject and commonjs plugins

import * as jQuery from 'jquery';

then in custom.js

$(function () {
        console.log('Hello jQuery');
});
Ritin
  • 401
  • 6
  • 15
8

I did not see this exact syntax posted yet, and it worked for me in an ES6/Webpack environment:

import $ from "jquery";

Taken directly from jQuery's NPM page. Hope this helps someone.

Stephen Shank
  • 362
  • 3
  • 8
3

If you are not using any JS build tools/NPM, then you can directly include Jquery as:

import  'https://code.jquery.com/jquery-1.12.4.min.js';
const $ = window.$;

You may skip import(Line 1) if you already included jquery using script tag under head.

VNN456
  • 137
  • 8
  • I don't know why, but this one worked for me when no others did. Any import statement other than the bare `import 'filepath/jquery.js'` threw some error about the module not exporting the function I wanted or $ not being a function or just a SyntaxError at the sight of the word `from`. – Galactic Ketchup May 14 '20 at 00:47
  • @GalacticKetchup I also agree, mine worked too while the rest didnt. @VNN456 kindly explain why use `const $ = window.$` because in my code it doesnt affect the functionality whether I include that const or not. so probably there is something I'm missing out unknowingly by not reassigning the window object. – Wahinya Brian Oct 15 '20 at 02:45
3

Pika is a CDN that takes care of providing module versions of popular packages

<script type='module'>
    import * as $ from 'https://cdn.skypack.dev/jquery';

    // use it!
    $('#myDev').on('click', alert);
</script>

Skypack is Pika, so you could also use: import * as $ from 'https://cdn.pika.dev/jquery@^3.5.1';

SamGoody
  • 13,758
  • 9
  • 81
  • 91
1
import {jQuery as $} from 'jquery';
Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
Farshid Ashouri
  • 16,143
  • 7
  • 52
  • 66
  • 2
    it says jQuery not found. The other answer worked "import * as $ from 'jquery';". Do you know why that happens? My JS file where I'm importing jquery is part of an Angular/Typescript file – SpaceMonkey Jan 29 '18 at 17:21
1

My project stack is: ParcelJS + WordPress

WordPress got jQuery v1.12.4 itself and I have also import jQuery v3^ as module for other depending modules as well as bootstrap/js/dist/collapse, for example... Unfortunately, I can’t leave only one jQuery version due to other WordPress modular dependencies. And ofcourse there is conflict arises between two jquery version. Also keep in mind we got two modes for this project running Wordpress(Apache) / ParcelJS (NodeJS), witch make everything little bit difficulty. So at solution for this conflict was searching, sometimes the project broke on the left, sometimes on the right side. SO... My finall solution (I hope it so...) is:

    import $ from 'jquery'
    import 'popper.js'
    import 'bootstrap/js/dist/collapse'
    import 'bootstrap/js/dist/dropdown'
    import 'signalr'

    if (typeof window.$ === 'undefined') {
        window.$ = window.jQ = $.noConflict(true);
    }

    if (process) {
        if (typeof window.jQuery === 'undefined') {
            window.$ = window.jQuery = $.noConflict(true);
        }
    }

    jQ('#some-id').do('something...')    

    /* Other app code continuous below.......... */

I still didn’t understand how myself, but this method works. Errors and conflicts of two jQuery version no longer arise

north.inhale
  • 483
  • 2
  • 9
  • 20
1
import $ from 'jquery'

// export for others scripts to use
window.$ = window.jQuery = $
Sky Yip
  • 1,059
  • 12
  • 10
0

First of all, install and save them in package.json:

npm i --save jquery
npm i --save jquery-ui-dist

Secondly, add a alias in webpack configuration:

resolve: {
  root: [
    path.resolve(__dirname, '../node_modules'),
    path.resolve(__dirname, '../src'),
  ],
  alias: {
    'jquery-ui': 'jquery-ui-dist/jquery-ui.js'
  },
  extensions: ['', '.js', '.json'],
}

It work for me with the last jquery(3.2.1) and jquery-ui(1.12.1).

See my blog for detail: http://code.tonytuan.org/2017/03/webpack-import-jquery-ui-in-es6-syntax.html

cwtuan
  • 1,718
  • 1
  • 18
  • 20
0

Import jquery (I installed with 'npm install jquery@1.9.1')

import 'jquery/jquery.js';

Put all your code that depends on jquery inside this method

+function ($) { 
    // your code
}(window.jQuery);

or declare variable $ after import

var $ = window.$
Yoseph
  • 2,356
  • 1
  • 13
  • 18
0

I wanted to use the alread-buildy jQuery (from jquery.org) and all the solutions mentioned here didn't work, how I fixed this issue was adding the following lines which should make it work on nearly every environment:

 export default  ( typeof module === 'object' && module.exports && typeof module.exports.noConflict === 'function' )
    ? module.exports.noConflict(true)
    : ( typeof window !== 'undefined' ? window : this ).jQuery.noConflict(true)
Ivan Castellanos
  • 8,041
  • 1
  • 47
  • 42
0

You can import like this

import("jquery").then((jQuery) => {
  window.$ = jQuery;
  window.jQuery = jQuery;
  import("bootstrap").then((_bs)=>{
    $(function() {});
  })
});
0

If you are using Webpack 4, the answer is to use the ProvidePlugin. Their documentation specifically covers angular.js with jquery use case:

new webpack.ProvidePlugin({
  'window.jQuery': 'jquery'
});

The issue is that when using import syntax angular.js and jquery will always be imported before you have a chance to assign jquery to window.jQuery (import statements will always run first no matter where they are in the code!). This means that angular will always see window.jQuery as undefined until you use ProvidePlugin.

Martin Konecny
  • 57,827
  • 19
  • 139
  • 159