Load different libraries for different pages

Hi and happy new year to everyone.

I’m trying to understand if there is a way to load diffente libraries for different pages. In my application I’ve got some libraries that I need to use for every pages for example jquery and bootstrap and then I’ve got some lobraries that should be loaded only for a specifica page. I’m thinking to generate a single js file also to easily mantain all the libraries updated.

This is is what I’ve achieved so far, not sure if is the right way to do it.

var baseUrl = window.location.origin;
var pathArray = window.location.pathname.split('/');

// Generic plugins
var jquery = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js";
var bootstrap = "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js";
var slimscroll = "https://cdnjs.cloudflare.com/ajax/libs/jQuery-slimScroll/1.3.8/jquery.slimscroll.min.js";
var km_app = baseUrl+"/km-template/km-assets/global/scripts/app.js";
var km_functions = baseUrl+'/km-template/km-js/km-functions.js';
var km_constants = baseUrl+'/km-template/km-js/km-constants.js';
var km_layout = baseUrl+'/km-template/km-assets/layouts/scripts/layout.js';
var km_demo = baseUrl+'/km-template/km-assets/layouts/scripts/demo.js';

// Page plugins
var air_datepicker = "https://cdnjs.cloudflare.com/ajax/libs/air-datepicker/2.2.3/js/datepicker.min.js";
var jquery_validate = "https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/jquery.validate.min.js";
var bootstrap_select = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.10/js/bootstrap-select.min.js";
var jquery_datatable = "https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.19/js/jquery.dataTables.min.js";
var bootstrap_datatable = "https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.19/js/dataTables.bootstrap.min.js";
var bootstrap_wizard = "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap-wizard/1.2/jquery.bootstrap.wizard.min.js";
var bootstrap_sweetalert = "https://cdn.jsdelivr.net/npm/sweetalert2@8.0.7/dist/sweetalert2.all.min.js";
var km_groups = baseUrl+"/km-template/km-js/km-groups.js";

// General list of global files
var scriptsToLoad = [
                        jquery,
                        bootstrap,
                        slimscroll,
                        km_app,
                        km_functions,
                        km_constants,
                        km_layout,
                        km_demo
                    ]; 


// Load specific files if in the controller km-groups
if(pathArray[1] == 'km-groups') {

    scriptsToLoad.push (
                            jquery_validate,
                            bootstrap_select,
                            jquery_datatable,
                            bootstrap_datatable,
                            bootstrap_wizard,
                            bootstrap_sweetalert,
                            km_groups
                        );

}

scriptsToLoad.forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.body.appendChild(script);
});

Consider whether you’re making more work for yourself than just putting <script> tags into the individual pages.

Your script is already 60 lines long;
You will have to add for each page (to maintain styling):

  • An if statement
  • A Push statement
  • A line per item
  • Two statement closing lines

Or… you add a line per item to the individual page.

Hi @m_hutley thanks for your reply. I’m also trying to find a way to quickly update the dependencies in the future, that is why I thought a single entry point would be easier to manage

Yes that is certainly a good point. However it looks like you’re kind of reinventing AMD here… I’d suggest to use an actual module loader or bundler instead (webpack being the current quasi-standard), or even native modules. If the library you’re requiring does not support native modules but just exposes itself to the global namespace, you can still import them like so:

import '/static/jquery.js'
import '/static/some-plugin.js'
// ...

That would already work without any additional loading logic.

I’m sort of 50/50. I see the value in a ‘single entry point’, but it’s just going to end up being a very cluttered file for ‘javascript dependencies’ that could probably be better managed by either naming conventions or symlinking files.

“What if i update the version of jquery?” “Download the jquery file rather than loading it out of a CDN, name it ‘jquery.js’, and when you want to update your version of jquery… download a new version and replace the one you’ve got. All your files instantly use the new version.”

Or better yet, just use a package manager from the start. ^^ Anyway versioning is one aspect of course, but another is when dependencies will change altogether; e.g. if you’re deciding to remove or replace a given library in the future. So I’d still argue that it’s preferable to maintain the dependencies in a single place – either in the script that actually uses them, or in a central webpack.config.js (or similar).

Thanks for your precious advices. I’ve tried to use the plugin require.js in the past but I find it really confusing to apply it for multi pages. Is Webpack easier ? How would you use it to load different dependencies for different pages? Many thanks

I have barely worked with requirejs myself, but with webpack you’d define an entry point for every page-specific script… e.g.

// webpack.config.js
module.exports = {
  entry: {
    'foo-script': './src/foo.js',
    'bar-script': './src/bar.js'
  }
}

This would generate a dist/foo-script.js and dist/bar-script.js as per the webpack defaults; in order to keep shared vendor scripts separate (and thus allow more efficient browser caching), you might also want to fiddle with the split chunks settings.

Hi,
I’ve opted to use requirejs plugn and this is what I’ve built so far:

const pathArray = window.location.pathname.split('/');

require.config({
    
    baseUrl: window.location.origin+'/km-template/',
    
    paths: {

        // Start general plugins dependencies
        jquery: 'https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min',
        bootstrap: 'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min',
        slimscroll: 'https://cdn.jsdelivr.net/npm/jquery-slimscroll@1.3.8/jquery.slimscroll.min',
        app: 'km-assets/global/scripts/app',
        layout: 'km-assets/layouts/scripts/layout',
        demo: 'km-assets/layouts/scripts/demo',
        functions: 'km-js/km-functions',
        constants: 'km-js/km-constants',

        // Start page specific plugins dependencies
        air_datepicker: 'https://cdn.jsdelivr.net/npm/air-datepicker@2.2.3/src/js/air-datepicker.min',
        jquery_validate: 'https://cdn.jsdelivr.net/npm/jquery-validation@1.19.1/dist/jquery.validate.min',
        bootstrap_select: 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.10/js/bootstrap-select.min',
        jquery_datatables: 'https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.19/js/jquery.dataTables.min',
        jquery_datatables_net: 'https://cdn.jsdelivr.net/npm/datatables.net-dt@1.10.20/js/dataTables.dataTables.min',
        bootstrap_datatables: 'https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap.min',
        bootstrap_datatables_rowgroup: '//cdn.datatables.net/rowgroup/1.1.1/js/rowGroup.dataTables.min',
        bootstrap_wizard: 'https://cdn.jsdelivr.net/npm/twitter-bootstrap-wizard@1.2.0/jquery.bootstrap.wizard.min',
        sweetalert: 'https://cdn.jsdelivr.net/npm/sweetalert2@9.5.4/dist/sweetalert2.all.min',
        bootstrap_jasny: 'https://cdn.jsdelivr.net/npm/jasny-bootstrap@4.0.0/dist/js/jasny-bootstrap.min',

        // Start specific pages plugins
        km_page_plugin: 'km-js/km-apps/'+pathArray[1]+'/'+pathArray[2]
    },

    shim: {

        bootstrap: {
            deps: ["jquery"]
        },

        slimscroll: {
            deps: ["jquery"]
        },

        app: {
            deps: ["jquery", "bootstrap"]
        },

        demo: {
            deps: ["app"]
        },

        layout: {
            deps: ["app"]
        },

        functions: {
            deps: ["jquery", "bootstrap_select"]
        },

        bootstrap_datatables: {
            deps: ["jquery_datatables"]
        },

        bootstrap_select: {
            deps: ["bootstrap"]
        }
    },

    map: {

      // This is important to make AMD bootstrap datatables working with custom datatables path name
      '*': {
        'datatables.net': 'jquery_datatables',
        'datatables.net-dt': 'jquery_datatables_net',
        'datatables.net-rowgroup': 'bootstrap_datatables_rowgroup'
      }
    }

});

// This is to load general plugins
require(['jquery', 'bootstrap', 'slimscroll', 'app', 'layout', 'demo', 'constants'], function($) { 

    require(['km_page_plugin'], function() {});

});
1 Like