Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

vincej's avatar
Level 15

Node_Modules: When to use Require, and when to use Window Object

I have historically always just pulled in the JS libraries and placed them into the public/js folder . Now I am wanting to be a little more clever and use Node_modules, but I am unsure why L8 uses the window object in some cases and a simple require in another case. In L8 they have used the following:

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

    require('bootstrap');
} catch (e) {}

Secondly Why does L8 have an app.js file which then pulls in the bootstrap.js file? Why are there two files?? When do you use one over the other?

0 likes
13 replies
squibby's avatar

window.$ = window.jQuery = require('jquery'); is assigning jQuery to the global variable window.$ so it can be available anywhere in any scope. Generally polluting global scope is not a good idea, but if using jquery you would likely want this available everywhere via $.

vincej's avatar
Level 15

@squibby Hi! Thanks for helping out. I was aware that the window object applied a module to the global scope. So, using require does not? It applies it only to what specifically? Thanks !!

martinbean's avatar

@vincej It’s about scope, mainly. So importing a module using require just imports that module into the JavaScript file you’re working it, it doesn’t make it globally available, which is why the Laravel developers then explicitly assign the module (the default export of popper.js, and jquery) to named objects on the window instance. So long-hand, it would look like this:

// Following imports Popper.js; but into the script’s local scope only
const popper = require('popper.js');

// Following assigns the default export to window.Popper
// The .default syntax is just how the Popper developers built and organised the library
window.Popper = popper.default;

// Following imports the jQuery library, but again into script’s local scope only
const jquery = require('jquery');

// Following actually assigns jQuery library to named variables on window object
window.$ = jquery;
window.jQuery = jquery;

// Following imports Bootstrap
// I guess Bootstrap 4.x explicitly did stuff on window object internally,
// so no need to do it ourselves
require('bootstrap');

If you start using more and more modular JavaScript libraries, such as Vue, then you’ll be manually assigning libraries to the window object like this less and less as the intention is to use these libraries in JavaScript modules. So for example, with Vue components you only ever deal with the DOM within a Vue component template; you’re not manipulating the actual DOM by hand, so you don’t need the vue library to live in the window object.

If you’re just import libraries only to re-expose them on the window object, then you’re not really doing anything that requires modules. You may as well load jQuery et al from a CDN using a <script> tag and just carry on working with it as you were before.

vincej's avatar
Level 15

@martinbean Many thanks for your detailed explanation. As adopt Vue, I have come to realise that using CDN's is a bad strategy as I have maybe 6+ to deal with hence the desire to use node_modules instead. But as much as now things have cleared up, for reasons unknown, for days I could not get things to load correctly. No amount of view:clear and deleting cache would work. Now things are working - but who know why.

So - next question: If I am needing a node_module into a specific file when to use import vs require. Also why does L8 uses a try catch in app.js?

EDIIT: As much as it is a major paradigm shift, I am coming to the opinion that Vue offers a lot over raw JS /JQuery

martinbean's avatar

So - next question: If I am needing a node_module into a specific file when to use import vs require.

@vincej You should only use one and stick to it. They’re two different ways of importing modules:

  • import is the ECMAScript standard for import modules. So you can import modules using statements like import X from 'z'.
  • require comes from Node.js and is the Node way of importing modular code, so statements look like const x = require('x').

They both do the same thing under the hood, but I’d stick to imports for client-side JavaScript code. Laravel Mix will take care into importing the correct modules for you.

Also why does L8 uses a try catch in app.js?

Not sure to be honest. I guess in the bootstrap example you posted, requiring either Popper.js or jQuery could fail in which case a JavaScript error would be raised. If the error wasn’t caught then the rest of the build would fail, but I don’t really think the example they bundle is really helpful. Catching an error only to do nothing about it seems a bit… pointless. You want to see errors so you know what’s wrong.

vincej's avatar
Level 15

@martinbean Import is not working for me. I checked syntax on MDN, but I am getting errors. PLus it does not find bootstrap-datepicker What am I doing wrong?

import {bootstrap-datepicker} from "./node_modules/bootstrap-datepicker/bootstrap-datepicker.js";
martinbean's avatar

I checked syntax on MDN, but I am getting errors. PLus it does not find bootstrap-datepicker What am I doing wrong?

@vincej Not sure without knowing what error you’re getting.

martinbean's avatar

@vincej It seems because that library isn’t a modular library and is just a jQuery plugin: https://bootstrap-datepicker.readthedocs.io/en/latest/index.html#usage

The error you’re specifically getting though is because I don’t think the import name can contain dashes. Module exports are usually snake_case or camelCase, i.e.

import { bootstrapDatepicker } from 'bootstrap-datepicker';

Or:

import { bootstrap_datepicker } from 'bootstrap-datepicker';

You also don’t need to use that whole path for a module installed via NPM. You can just use the module name. You’d only specify a relative path if importing your own module code.

vincej's avatar
Level 15

@martinbean Thanks for that - I will play with that.

Lastly, and I will leave you alone: could you comment on the app.js question below?

Cheers!

martinbean's avatar

@vincej I don’t know the answer. There isn’t really a reason. You could just as well merge the two files together.

I guess the Laravel team extracted the bootstrap.js file in case you wanted multiple entry points (app.js, admin.js etc) so you didn’t have to import jQuery, Popper, and Bootstrap in them all.

vincej's avatar
Level 15

@martinbean Many thanks for all your help! Often I feel stupid for asking what are possibly obvious questions, however, I am always surprised by how few people know the answer to these basic questions. Moreover, I meet CS grads through my sons, and I am stunned by how little they know about real world coding /development. Putting that aside, I am always hugely impressed by people like yourself, Snapey, Cronix etc etc. Many thanks, Cheers! ps - bloody freezing here in Calgary - had our first snow fall here yesterday!

1 like
vincej's avatar
Level 15

OK I will use import thanks for that. Next question why do they have an app.Js file and a bootstrap.JS file? What is the point of that? And which one should I use for adding on my imports?

Please or to participate in this conversation.