Switching from the global import module pattern to ES6 modules

In recent years, my approach to JavaScript development has involved using the global import method. Typically, I work with a set of utility functions packaged and passed to a separate site module containing individual functions for each web functionality:

(function(m, u, ui, w, a, $){

    // Sample Module
    m.example = function(){
        // Perform actions, the m.example module is automatically initialized.
};

})(Site.modules = Site.modules || {}, Site.utils, Site.ui, Site.w, Site.anim, jQuery);

In this scenario, I pass on various modules that we extend, utilities, user interface object (often aliased gsap), and other dependencies like jQuery.

However, as these projects grow in size, the process can become cumbersome and messy.

I am now considering transitioning to ES6 and using NPM. While there are numerous resources available on creating and importing modules, as well as utilizing NPM, I have yet to find detailed guidance on bringing everything together.

For instance, if I import slick-carousel via NPM and want to incorporate two distinct carousels on a single-page website - a banner carousel and a tweet carousel - how should I verify the existence of these elements and initialize the carousels separately?

In the past, using an anonymous closure, I would create auto-initialized functions individually looking up DOM elements and initializing carousels with unique options.

Edit

To illustrate my current workflow, I establish a site object with reusable static variables and shared items across the project such as animation variables, window references, and auto-updating variables for viewport properties access.

Subsequently, within a dedicated file specific to each developed website, I define the main structure where distinct 'modules' are created for each functional aspect implemented on the site. This involves employing jQuery alongside plain JavaScript plugins embedded on the page, along with utility and primary JS files.

utils.js

jQuery(document).ready(function($) {
    Site.init();
});


var Site = (function($) {

    // DOM caching
    var win = window;

    // Global items
    var w = {
        width:  win.innerWidth,
        height: win.innerHeight,
        scroll: win.pageYOffset
    };

    var ui = {
        fast: 0.2,
        slow: 0.4,
        step: 0.03,
        easeout: Power4.easeOut,
        easein: Power4.easeIn
    };

    function updateGlobals(){
        w.width  = win.innerWidth;
        w.height = win.innerHeight;
        w.scroll = win.pageYOffset;
    }

    win.addEventListener('resize', updateGlobals, true);
    win.addEventListener('scroll', updateGlobals, true);
    win.addEventListener('load', updateGlobals, true);

    return {
        init: function(){

            for (var prop in this.modules) {
                if ( this.modules.hasOwnProperty(prop) ) {
                    this.modules[prop]();
                }
            }

            for (var props in this.autoInits) {
                if ( this.autoInits.hasOwnProperty(props) ) {
                    var $selector = $(props);

                    if ($selector.length) {
                        this.autoInits[props]($selector);
                    }
                }
            }
        },
        ui: ui,
        w: w
    };

})(jQuery);

main.js

(function(m, $){

    m.homepageCarousel = function(){
        var element = $('.js-homepage-carouel');
        
        $(element).slick({
            dots: true,
            speed: 500,
            arrows: false
        });
    };

    m.productsCarousel = function(){
        var element = $('.js-products-carouel');
        
        $(element).slick({
            dots: false,
            speed: 500,
            arrows: true
        });
    };

    m.showcookieNotice = function(){
        ... logic to check cookies for a marker and display cookie notice if not present.
    }

    ... handling additional website functionalities like maps, menus, custom elements, etc.

})(Site.modules = Site.modules || {}, jQuery);

Answer №1

Avoid relying on the "everything is global" mindset. The global scope in JavaScript is considered a major design flaw. For example:

    var name = 1;
    console.log(name + 1); // 2, right? No, try it ...

While the global scope has its uses, they are limited. It's best to view it as the state of webpages or servers. Ideally, the global scope should not contain any code (functions). Exposing too much functionality to the global scope can lead to conflicts between scripts, resulting in difficult-to-troubleshoot bugs. Instead, your code should be self-contained and minimize its impact on the global scope. When sharing functionality between different files (e.g., menu.js and slider.js, both requiring a Button class), that functionality should be placed in a module that is then imported by both scripts. Each file should handle imports at the top and exports at the end, encapsulating itself:

import {functionality1, functionality2} from "module";

let somevariable; // Variables declared with let or const do not pollute the global scope, even though they are "global"

Do not hesitate to import the same module multiple times in different files on the same page. Modules are only loaded once, and through tree shaking (a feature in most bundlers like Webpack), only necessary chunks of a large module may be included instead of loading the entire module.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the accurate user agent for Windows Phone?

Can someone explain why PHP and JavaScript produce different user agents? Which one is considered the accurate user agent? PHP User Agent Output: <?php print_r($_SERVER['HTTP_USER_AGENT']); ?> User Agent: Mozilla/5.0 (Mobile; Windows Ph ...

Utilizing the ng-if directive to choose the second element within an iteration of an ng-repeat loop

I am currently working on a project where I need to organize and group content by day. While the grouping function is working fine, I am facing an issue with treating the first two items in the loop differently from the rest. I have experimented with using ...

The value is not getting set after calling React Hook UseState

I am currently working on a React component that handles payment processing. There is a part of my code where I utilize the useEffect hook alongside useState to set certain values. Check out the code snippet below: React.useEffect(()=>{ axiosFetch ...

Retrieve the heading of a click-able element using jQuery

My challenge involves a list of selectable buttons with names generated dynamically from a JSON file. Each time a button is clicked, I aim to retrieve its title, which corresponds to row["name"]. Below is my relevant code snippet and the JSON data provided ...

The auto-refresh feature of DataTables is not functioning as expected

Having trouble with the reload feature of DataTables. This is the code I'm using to load and reload the table on the server-side: $( document ).ready(function() { $('#dienst_tabelle').DataTable( { "ajax": "getData ...

Eliminable Chips feature in the Material UI Multiple Select component

The Material UI documentation showcases a multiple select example where the selected options are displayed using the Chip component and the renderValue prop on the Select. By default, clicking on the current value opens the list of available options. I am ...

What is the best way to mix up the middle letters within certain positions of a word?

Here is what I have managed to achieve so far: mounted() { const randomVariants = [...Array(3)].map(() => this.baseWord .split('') .sort(() => 0.5 - Math.random()) .join('') ) const variantsWithoutIniti ...

Creating a bezel design in CSS or Vue: A step-by-step guide

Embedding: Is there a CSS property that can be used to create the same angle as shown in the layout? I looked everywhere in the program but couldn't find this specific property. Tried searching here !: ...

Guide to dynamically load external JavaScript script in Angular 2 during runtime

Currently, I am integrating Twitter digits for authentication purposes. To implement this feature, a small .js script needs to be downloaded and initialized. The recommended approach is to directly fetch the file from the Twitter server. In order to succe ...

The Ultimate Slider: Highlighting Custom Navigation Link as Active While Navigating with Arrows

I have implemented custom navigation links for my slick slider in order to navigate to specific slides. The functionality works perfectly, but I encountered an issue when I added the built-in arrows provided by the slider. Whenever I use these arrows to n ...

Configure webpack to source the JavaScript file locally instead of fetching it through HTTP

Using webpack.config.js to fetch remote js for Module Federation. plugins: [ new ModuleFederationPlugin({ remotes: { 'mfe1': "mfe1@http://xxxxxxxxxx.com/remoteEntry.js" } }) ], Is it possible to incorporate a local JS ...

Checkbox enabled Bootstrap image

I am encountering a minor issue where I am attempting to incorporate a simple image that can be toggled on and off by clicking on it. After coming across some bootstrap code online, I decided to test it in my project. Unfortunately, the code does not seem ...

I have successfully established a new channel, but I am having difficulty retrieving the unique identifier for it

After using the provided code to create a channel, I'm having trouble locating the channel ID needed for the next step in my function. This function is meant to move to a specific category and send a message to it. const buyid = generateID message. ...

Is there a way to dynamically apply styles to individual cells in a React Table based on their generated values?

I'm having trouble customizing the style of a table using react table, specifically changing the background color of each cell based on its value. I attempted to use the getProps function in the column array as suggested by the react table API documen ...

recording the results of a Node.js program in PHP using exec

I'm attempting to retrieve the output from my node.js script using PHP exec wrapped within an ajax call. I am able to make the call and receive some feedback, but I can't seem to capture the console.log output in the variable. This is how I exec ...

Guide to updating 2 iframes simultaneously with a single link/button using HTML and JavaScript

Just joined the community and looking for help on how to refresh two different iframes within a single page. I came across a solution on Google that involves using getElementById. However, I've heard Firefox can be tricky with IDs. Appreciate any as ...

Utilizing a library that solely enhances the functionality of the Array object

I have a library with type definitions structured like this: declare global { interface Array<T> { addRange<T>(elements: T[]): void; aggregate<U>(accumulator: (accum: U, value?: T, index?: number, list?: T[]) => an ...

What is the reason for $http.get not requiring a return value?

I am currently developing an angular application and I have a controller that interacts with a service. The controller sends a URL to the service, which then makes a GET request to that URL and receives JSON data in return. Within this JSON data is a URI f ...

Breaking down a number using JavaScript

Similar Question: JavaScript Method for Separating Thousands I'm looking to find a way to separate numbers by a thousand using JavaScript. For example, I would like to turn "1243234" into "1 243 234", or "1000" into "1 000" and so on. (sorry for ...

"Encountered issue while trying to use Meteor as a dependency in an npm module: Module 'meteor/mongo' could not be located

I have two separate meteor projects that both use the same models. I am interested in merging the model schemas into a private module on NPM. Here is an example of what my module contains: import { Mongo } from 'meteor/mongo'; import { packageS ...