Wondering how to replicate the Apache vhost feature in Express.js? Virtual hosting is a method for hosting multiple domain names on a single server. In case you are new to vhost, it allows a web server to listen on a single port and serve different web apps depending on the domain name or the subdomain. Implementing such a feature in Express.js is very easy.
I will be using Heroku as a cloud hosting provider with Namecheap as a domain registrar and Node.js (Express.js) for the Back-End displaying my portfolio which is made with Vue.js.
The goal
- Create and connect subdomain on the services
- Directory structure
- Node.js server setup
Requirements
- Basic node.js/ express.js knowledge
- Payed Dyno (hobby)
- The will to learn
Lets get started!
Create and connect subdomain
Lets start with Heroku where you need to be logged in:
After login your dynos will be displayed...
- Pick the one you want to use.
- Go to settings
- Scroll down to domains
- Click on "Add domain"
- Enter wished subdomain
- for the sake of this tutorial it will be test.ahmedaltaai.com
- Click next
- Copy DNS Target
It will show you "waiting" on heroku until you connect it to a domain with DNS Target
Now lets head to namecheap to connect DNS Target
- Login
- Go to Domain List
- choose your domain and click on "manage"
- Click on advanced DNS and scroll down to "host records"
- Click "add new record"
- Select "CNAME" from the dropdown menu in the type column
- Enter your subdomain in the "host" column
- Paste in your "DNS Target" in The "value" column
- Click on the "greenish" check mark to save
That was it for the registeration of the subdomain
Now on heroku there would be a red flag because of the SSL certificate. It will take some time for it to be activated on the subdomain (5-10 min).
After some time has passed it will say that everything is OK
Directory structure
- Root folder
- server.js
- public (main website)
- index.html
- style.css
- main.js
- subdomains
- test (project directory)
- server.js
- public
- index.html
- style.css
- main.js
In the root directory a creation of an express app is needed
npm init
then
npm install express
. Now we create our server.js file which if not changed during the "npm package initialization process" will be named index.js by default.
It can be checked in the package.json file.
"scripts": {
"start": "node server.js"
}
Every website needs its own express app to be rendered by. In the root directory there is the one express app to rule them all. In our case to route the views for the specified URL.
As seen above every project directory has a server.js file which is the node server (express app) and the public directory where the website is which will be rendered in the browser.
to serve are the website files e.g. index.html / style.css / main.js. It is needed to put them all in one directory e.g. public / client / frontend because we will be serving/ rendering the view from server.js.
The subdomain directory will hold all the other directories of the individual projects which will be rendered when visiting the registered subdomain in our case it will be test.ahmedaltaai.com
Nodejs server setup
Lets take a look at server.js for displaying the main website
// importing express
const express = require('express')
// The path module provides utilities for working with
// file and directory paths
const path = require('path')
// app is an instance of express
// why app? I DON'T KNOW it is the law
const app = express()
// serves files from public directory
// which contains the main website
const website = express.static(path.join(__dirname, '/public')
// Mounts the specified middleware function or functions
// at the specified path: the middleware function is executed
// when the base of the requested path matches path.
app.use(website)
// routes an HTTP request, where METHOD is the HTTP
// method of the request, such as
// GET, PUT, POST, and so on, in lowercase.
app.get('/', (req, res) => {
// The path.join() method joins all given path segments together
// using the platform-specific separator as a delimiter,
// then normalizes the resulting path.
res.render(path.join(__dirname, '/public'))
})
// in many environments (e.g. Heroku), and as a convention,
// you can set the environment variable PORT
// to tell your web server what port to listen on.
const port = process.env.PORT || 8080
// binds and listens for connections on the specified host and port.
app.listen(port)
// just logging out on which port the app is listening
console.log("listening on... " + port)
Now when visiting yourwebsite.com the index.html inside the public directory will be rendered.
Now lets use vhost to display the subdomains
To display the subdomains we need to create a module out of the test directory's express app which is named server.js
It is nearly the same as a normal express app except we won't use
app.listen(...)
rather we will export it as a module and make it run on the same port and server which is being used for the main website.
test subdomains express app
const express = require('express')
const path = require('path')
const app = express()
app.use(express.static(path.join(__dirname, './public')))
app.get('/', (req, res) => {
res.render(path.join(__dirname, './public'))
})
module.exports = app
Now lets configure vhost in the root express app.
vhost needs to be installed through npm in the root directory
npm install vhost
then import it as we did with express and path with
#### main express app
const express = require('express')
const path = require('path')
const vhost = require('vhost')
const app = express()
const website = express.static(path.join(__dirname, '/public')
// it is important to have it at the top
// before app.use(website) otherwise it wont work
// the express app which we exported
// is being requires thus it is being executed
// also the code says it should render a view
app.use(vhost('test.ahmedaltaai.com', require('./subdomains/test/public/app')))
app.use(website)
app.get('/', (req, res) => {
res.render(path.join(__dirname, '/public'))
})
const port = process.env.PORT || 8080
app.listen(port)
console.log("listening on... " + port)
The repository can be found [here](https://github.com/ahmedaltaai/portfolio-vuejs)
# I hope you learned something new
Top comments (0)