简体   繁体   中英

Converting global import module pattern to ES6 modules

For the past few years I've been working using the global import method of JavaScript. Usually working with a set of utility functions wrapped up and passed to another site module that contained a separate function for each piece of web functionality:

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

    // Example Module
    m.example = function(){
        // Do stuff, the m.example module gets auto initialized.
};

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

In this sample I pass along the modules that we add to, the utilities, user interface object (aliased gsap mostly) and other things like jQuery.

As you can see it can get big and a mess especially on larger sites with lots and lots of functionality.

I'd like to move over to ES6 and NPM and while I have seen dozens of articles and examples for how to make a module, how to import a module, bringing in modules with NPM I can't find a single example or article on actually pulling it all together.

For a simple example. I import slick-carousel with NPM. I have a single page website with a banner carousel and a carousel of tweets. How should I go about checking those elements exist and initializing 2 separate carousels?

Using anonymous closure I would just have a separate auto initiated function that looks up a DOM element and then initializes a carousel with different options.

Edit

For an example of my current workflow, I define a site object that has multiple reused static variables and some items reused across the site such as animation variables, reference to window, auto updating variables to access viewport properties etc.

Then in a separate file unique to the each built website I have the main file where I create separate 'modules' for each chunk of implemented functionality on the site. Utilizing jQuery and plain JavaScript plugins included on the page along with utils and main js files.

utils.js

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


var Site = (function($) {

    // DOM caching
    var win = window;

    // Globals
    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(){
        ... example check cookies for marker and show cookie notice if not present.
    }

    ... rest of the websites js, maps, menus, custom reused items etc

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

Don't think in the "everything is global" way. The global scope is one of the biggest js design mistakes. Eg:

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

I dont think that the global scope is totally useless, but its usecases are very limited. You should think of it as the webpages / servers state. This means that it should contain no code (= functions) in the best case. The more functionality (code) you expose to the global scope its more likely that you will have a bad inference between two scripts, and those bugs are really hard to spot. Instead your code should encapsulate itself. It should expose and change as few as possible to the global scope. That means that if you want to share a certain functionality between two different files of your page ( eg menu.js and slider.js both require a Button class) then this functionality should go into a module, which is then imported by both scripts. So every separate file should have the imports at the top and the exports at the end, and should encapsulate itself:

import {functionality1, functionality2} from "module";

let somevariable; // variables declared with let or const do not appear on the global scope, although they are "global"

Don't fear to import the same module multiple times in different files on the same page. Modules are only loaded once, and with tree shaking (which most Bundlers such as Webpack do), just including a few functions from a large module might not even load the whole large module but just a few chunks of it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM