Dynamic Serving with Electrode

Aseem Upadhyay
Javascript Bits
Published in
3 min readJul 30, 2019

Long debates usually take place when one needs to decide how their website needs to be designed, should it be incorporating responsive designs or host a separate mobile website on a different URL or somehow implement dynamic serving.

So, after a good long discussion, we finally decided upon implementing dynamic serving.

What is dynamic serving?

Dynamic serving is a setup where the server responds with different HTML (and CSS) on the same URL depending on which user agent requests the page (mobile, tablet, or desktop). It serves different code to each device, but on the same URL.

Photo by Caspar Camille Rubin on Unsplash

The challenge:

Internet is an immense pool of information where whatever you search, you’ll eventually find a sample implementation of the same. Surprisingly, there weren’t many references regarding dynamic serving (at least at the time of implementation). Hence, was the start of the quest of finding the solutions to our own questions.

Question 1.
How can we break the main javascript bundle into two different parts?

Question 2.
What should be the entry file for each of these bundles?

Question 3.
How can we serve the correct bundle at runtime depending on the user agent?

How can we break the main javascript bundle into two different parts?

In order to define multiple entry points in an application, you need to create an entry file in client/entry.config.js, which tells electrode that the main bundle is to be split and each bundle is identified by the keys represented in the object given below:

Once, the entry.config.js file is in place, we need to create a file in server/chunks-selector.js that would determine what chunk should be served

This only returns a specified chunk at the moment. We will modify it to return dynamic bundles in the forthcoming question

Now, the electrode framework needs to take this newly added chunk-selector file into consideration :)
To do that, you need to add a key bundleChunkSelector in the options object of the config/default.js file. Electrode merges this object with its original options object to generate a setting for your application. The default settings object looks like this:

This object is in the function setupOptions in node-modules/electrode-react-webapp/lib/react-webapp.js

So, after adding the key bundleChunkSelector, your default.js should look something like this:

This sets up your basic bundle splitting in electrode. Now, you must be wondering what should be the splitting point that will enable us to serve two complete bundles for both desktop and mobile, which is precisely our next question to be answered.

What should be the entry file for each of these bundles?

Since the desktop and mobile versions of the application should represent a different website, so, essentially the bundle of each of these variants should be complete on its own. In order to do that, our main file app.js needs to be broken down into two pieces (one piece for desktop and mobile each). Let’s call them app.desktop.js and app.mobile.js.
We planned on isolating logical components and sharing presentational ones, so, ended up making different versions of the files for routes and reducers as well!
Now, that the basic structure in place (eg — app.desktop.js calls routes.desktop.js and reducers.desktop.js), we proceed to inform electrode about our new creation.
The altered entry.config.js file looks something like this:

Electrode now has information about what bundles it has to build. The question now arises, as to which bundle has to be served at what time.

How can we serve the correct bundle at runtime depending on the user agent?
To answer this, the chunks-selector.js file would be altered a bit. So, our improved version of the file looks something like this -

Selects the bundle based on the incoming request user agent. Currently, it assumes everything to be desktop if the user agent doesn’t contain a mobile keyword.

Once, we have established what bundles will be served at runtime, management of the views and actions of each of its variant is the next requirement. Luckily, there is an abstraction available in the default.js file.

The path key (in default.js) generally means that for every route that is being hit (denoted by *), the request is to be served by the file present in ./{{env.APP_SRC_DIR}}/server/views/index-view.

In order to achieve what we seek, we’ll try to put each of the variants in its own scoped variable, resulting in the following

Since the server, rendering both of these variants is the same, the two different variables return the same/new instance of the version (desktop/mobile) requested based on the user agent.

Now, inspect your bundle to see the magic :)

References —
For electrode documentation refer here:
https://www.electrode.io/docs/get_started.html

A demo project of dynamic serving:
https://github.com/Bryze/electrode-chunk-test

Dynamic serving definition:
https://developers.google.com/search/mobile-sites/mobile-seo/dynamic-serving

--

--