How to handle multiple domains and subdomains in your Nuxt.js project

NuxtJS is a framework based on Vue.js to create applications that can be everything from static landing pages to enterprise web applications. My favorite target is the server-side rendered website. We get all the benefits of the Vue.js ecosystem with SEO optimization and static page speed on different devices.

One of the not obvious part for of Nuxt for typical Vue.js developer is router configuration:

Nuxt.js automatically generates the vue-router configuration based on your file tree of Vue files inside the pages directory.

https://nuxtjs.org/guide/routing

It means that we don’t maintain router.js file with complete list of routing. So what we can do if we need nonstandard behavior of our application? Handle multiple domains or subdomains for instance? In my case I want a separate page components for subdomains, because they are completely different to the main page and I want all code base to look clean. Let’s how how to do that!

Let’s start with an empty Nuxt.js project and create subdomain1 and subdomain2 sub-directories with index.vue components in pages folder:

When we start the project with standard configuration these pages are available at the following URLs:

  • http://localhost:3000
  • http://localhost:3000/subdomain1
  • http://localhost:3000/subdomain2

But my goal is to make them available after deploying to web server under URLs listed below:

  • http://nubisoft.io
  • http://subdomain1.nubisoft.io
  • http://subdomain2.nubisoft.io

In your local environment open /etc/hosts file (or %SystemRoot%\system32\drivers\etc\hosts on Windows) and add lines for testing purposes:

127.0.0.1 subdomain1.nubisoft.io
127.0.0.1 subdomain2.nubisoft.io

To change the default configuration of Nuxt router install @nuxtjs/router module:

$ npm install --save-dev @nuxtjs/router

Next add just installed build module to nuxt.config.js and set location and file name of router configuration which we will create later:

buildModules: [
    // Doc: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module',
    [
      '@nuxtjs/router',
      {
        path: 'router',
        fileName: 'index.js',
        keepDefaultRouter: true,
      },
    ],
  ],

The keepDefaultRouter property disables or enables automatic generation of router configuration based on your file tree. It’s time to add router/index.js file to the project and paste code with console.log() to preview the default router options:

import Vue from 'vue';
import Router from 'vue-router';

Vue.use(Router);

export function createRouter(ssrContext, createDefaultRouter, routerOptions) {
  const options = routerOptions || createDefaultRouter(ssrContext).options;

  console.log(options.routes);

  return new Router({
    ...options,
    routes: options.routes,
  });
}

After starting our project the browser console should print routes list as we would expect in standard Nuxt.js project:

[
  {
    path: '/subdomain1',
    component: [Function: _7148fb8a],
    name: 'subdomain1'
  },
  {
    path: '/subdomain2',
    component: [Function: _5c4034fc],
    name: 'subdomain2'
  },
  { path: '/', component: [Function: _5eb7a297], name: 'index' }
]

Now we can implement fixRoutes() function which will change paths in subdomain routes:

export function createRouter(ssrContext, createDefaultRouter, routerOptions) {
  const options = routerOptions || createDefaultRouter(ssrContext).options;
  const hostname = ssrContext ? ssrContext.req.headers.host : location.host;

  return new Router({
    ...options,
    routes: fixRoutes(options.routes, hostname),
  });
}

function fixRoutes(defaultRoutes, hostname) {
  if (hostname.includes('subdomain1')) return subdomain1Routes(defaultRoutes);
  if (hostname.includes('subdomain2')) return subdomain2Routes(defaultRoutes);
  return nubisoftRoutes(defaultRoutes);
}

function nubisoftRoutes(defaultRoutes) {
  return defaultRoutes.filter(r => r.name !== 'subdomain1' && 'subdomain2');
}

function subdomain1Routes(defaultRoutes) {
  const route = defaultRoutes.find(r => r.name === 'subdomain1');
  route.path = '/';
  return [route];
}

function subdomain2Routes(defaultRoutes) {
  const route = defaultRoutes.find(r => r.name === 'subdomain2');
  route.path = '/';
  return [route];
}

The hostname variable is set depending on whether the source code is running on server-side or in browser so we can use request header or location.host property, respectively. If we detect one of our subdomains we should find the proper route and replace path property. After applying the above changes, we should see our separate components while visiting http://subdomain1.nubisoft.io

That’s it! If you have some cache mechanism be sure it is configured properly – i.e. it can’t use only path property from routes list. The complete example is available on GitHub: https://github.com/nubisoft/nuxtjs-multiple-domains

Leave a Reply

Your email address will not be published. Required fields are marked *