How to split DOM-based Routing in multiple files

I’ve been working on my own version of the Sage theme for a while now,
customising it to suit my basic project needs.

The Sage implementation of DOM-based Routing is excellent,
but for larger projects I like to split the routing to be one class/route per file

##My solution

1. Every route has it’s own JS file:
assets/scripts/routing/example.js contains:

var routingExample = {
    // All pages with body class 'example'
    'example': {
        init: function() {
            // JavaScript to be fired on all pages
        },
        finalize: function() {
            // JavaScript to be fired on all pages, after page specific JS is fired
        }
    }
};

2. Every route’s JS file is added as a file dependency:
assets/manifest.json contains the following main.js dependency, before scripts/main.js:

"main.js": {
  "files": [
    "scripts/routing/common.js",
    "scripts/routing/example.js",
    "scripts/main.js"
  ], 
  "main": true
},

3. Object content of every route’s JS file is merged in Sage variable
assets/scripts/main.js contains the following variable for :

var Sage = $.extend(
   routingCommon,
   routingExample,
);

##My questions

  • Has anyone solved the problem of splitting routing in separate files in a different way?
  • Does anyone have proposals to make the splitting/merging more efficient?
1 Like

I like your solution, but i prefer to split the javascript “components”. For example (following your process):

1. Every component has it’s own JS file:
assets/scripts/products-carousel.js contains:

function productCarousel() {
  ...
}

2. Every component’s JS file is added as a file dependency:
assets/manifest.json contains the following main.js dependency, before scripts/main.js:

"main.js": {
  "files": [
    "scripts/products-carousel.js",
    "scripts/main.js"
  ], 
  "main": true
},

3. Every component’s function is called in Sage routes
assets/scripts/main.js calls function in different routes:

var Sage = {
    'common': {
      init: function() {
      }
    },
    'template_page_products': {
      init: function() {
        productCarousel();
      }
    }
  };

What do you think of this approach?

The best thing would be to have a single JS file per component in witch declare its routing.

I’m very new to Sage (also, not really experienced in javascript) and I’m trying to figure out the best way to write maintainable JS.
I feel like yours is a great solution, with only one problem: since I need to use jQuery in my script I have to wrap my extras.js’s code in an anonymous function “(function($) { … })(jQuery);”.
This also means I won’t be able to access the variables I define on that file in the main.js router. Is there any way to solve this?

This is really only relevant to Sage 8, where routing took place in a single file. In Sage 9, there is a routes directory, in which you can declare your route-based JS in separate files and import into a main.js file.

1 Like