Confusing setup of a downloaded website template with a webpack ES6 project

Viewed 85

My boss coworker insisted to buy a beautiful HTML/CSS/JS external template to use it as a base design for a website. This website is a big project which we develop using Laravel, SASS and ES6 through Webpack.

The template we bought provides a complete set of features developed in SASS and ES5 JS. I have no trouble using the provided SASS and editing it because I also uses it, but I'm quite stuck with the Javascript part.

In the first part, I use files from the downloaded template:

  • core.min.js
  • script.js

script.js contains around 1k not minified lines with things like this:

plugins = {
    bootstrapTooltip: $("[data-toggle='tooltip']"),
    bootstrapModalDialog: $('.modal'),
    captcha: $('.recaptcha'),
    rdNavbar: $(".rd-navbar"),
    wow: $(".wow"),
    owl: $(".owl-carousel"),
    swiper: $(".swiper-slider"),
    counter: $(".counter"),
    twitterfeed: $(".twitter"),
    isotope: $(".isotope"),
    viewAnimate: $('.view-animate'),
    selectFilter: $(".select2"),
    rdInputLabel: $(".form-label"),
    bootstrapDateTimePicker: $("[data-time-picker]"),
    customWaypoints: $('[data-custom-scroll-to]'),
    stepper: $("input[type='number']"),
    radio: $("input[type='radio']"),
    checkbox: $("input[type='checkbox']"),
    customToggle: $("[data-custom-toggle]"),
    regula: $("[data-constraints]"),
    search: $(".rd-search"),
    searchResults: $('.rd-search-results'),
    copyrightYear: $(".copyright-year"),
    materialParallax: $(".parallax-container"),
    dateCountdown: $('.DateCountdown'),
    flickrfeed: $(".flickr"),
    responsiveTabs: $(".responsive-tabs")
};

// [...]

if (plugins.copyrightYear.length) {
    plugins.copyrightYear.text(initialDate.getFullYear());
}
// [...]

core.min.js contains tons of JS dependencies, it looks like this:

/**
 * @module       jQuery Migrate
 * @author       jQuery Foundation and other contributors
 * @see          https://code.jquery.com/jquery/
 * @license      MIT
 * @version      3.0.0
 */
"undefined"==typeof jQuery.migrateMute&&(jQu[...]

/**
 * @module       jQuery Cookie Plugin
 * @see          https://github.com/carhartl/jquery-cookie
 * @license      MIT
 */
!function(e){"function"==typeof define&&de

And so on for maybe 30 more libraries!

And in the second part, I use my own files which mainly are ES6 modules.

The problem is that some of the libraries used by the template are also used in my ES6 modules, so it ends with getting the same libs imported multiple times (once in core.min.js, once in ES6 webpack bundle). For example, jQuery is used in script.js (through window) and in ES6 modules (through imports). And sometimes I have different versions of the same lib!

So what I began to do is creating a vendor.js file and imported all libs in common and set them on window :

import $ from 'jquery';
import moment from 'moment';
import 'bootstrap';

window.$ = window.jQuery = $;
window.moment = moment;

But, I think that's quite a bad practice, and also it's not enough and it leads to errors with some libraries. For example DataTables which is tricky to initialize on a global scoped jQuery object and more. Moreover, I can't do that with all libraries, and some of them do not exist in npm/yarn..

I don't know how to deal with this stuff, Is there a way to handle all the legacy stuff properly while keeping a working ES6 structure? Or should I stop using the downloaded template completely?

1 Answers

Option 1:

How about letting webpack do those imports for you? And you just use the global variables without importing them anywhere.

Implemented by ProvidePlugin

For example:

plugins: [
   new webpack.ProvidePlugin({
      $: 'jquery',
      moment: 'moment',
      moduleNotInNpm: '/path/to/module/location.js/'
   });
]

This way webpack will handle the bundling of those modules in a different way.

Option 2:

Put all those modules in one (or two, three, not to much) root folder, for example under custom modules:

node_modules/

custom_modules/

src/

and utilize cacheGroups to create a chunk specifically for them. Anyone who would want to use them will need to download this chunk. This has an advantage for performance as as this chunk bytes won't differ from build to build so probably will be served from user cache almost allways.

optimization: {
    splitChunks: {
        cacheGroups: {
            thirdpartylibraries: {
                test: /custom_modules|node_modules/,
                name: 'custom_modules',
            },
        }
    }
}
Related