This is a simple way to server side render a home page without using a js framework. I wanted to build an app that meets the latest trend with minimal use of 3rd party modules. Embedded Javascript (EJS) was the simplest way I could solve my problem.
Demo - https://ejs-ssr.herokuapp.com/
* Node.js installed globally is required. I made this on a macbook pro.
cd desktop
mkdir simple-project
cd simple-project
touch server.ts package.json
//package.json
{
"name": "simple-project",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
}
}
npm install ejs express --save
//server.js
const express = require('express')
const ejs = require('ejs')
const port = 3000
let data = ['data 1', 'data 2', 'data 3']
app = express()
app.get('/', function (req, res) {
ejs.renderFile('views/home.ejs', {data}, {}, (err, template) => {
if (err) throw err
res.end(template)
})
})
app.listen(port, function(err) {
if(err) throw err
console.log('Server running on port '+port)
})
mkdir views
cd views
touch home.ejs
<!-- homr.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content=
"width=device-width, initial-scale=1.0">
</head>
<body>
<ul>
<% data.forEach((item) => { %>
<li><%= item %></li>
<% }); %>
</ul>
</body>
</html>
cd ..
- serve app
node server.js
http://localhost:3000/
* Heroku toolbet required. After I pushed to a new github repo I deployed to heroku with these steps.
touch Procfile
- specify server in Procfile
web: node server.js
- server.js edit line 3
const port = process.env.PORT || 3000;
git heroku login
git heroku create my-ssr
git push heroku main
git heroku open
I can make my own data to for loop in the ui by using a json file. I am using NHL goalie data that I started in a previous project, but you can use any data that you want to, I am just showing you how to import the json to the server from a separate file.
touch nhlGoalies.json
{
"Samsonov":{
"id": 5617,
"firstName": "Ilya",
"lastName": "Samsonov",
"teamId": 5,
"teamAbbreviation": "WSH",
"active": true,
"numberOne": true,
"nhlId": 0,
"nhlTeamId": 15,
"teamCity": "Washington",
"teamName": "Capitals",
"teamTwitter": "#ALLCAPS"
},
"Vanecek":{
"id": 14365,
"firstName": "Vitek",
"lastName": "Vanecek",
"teamId": 5,
"teamAbbreviation": "WSH",
"active": true,
"numberOne": false,
"nhlId": 0,
"nhlTeamId": 15,
"teamCity": "Washington",
"teamName": "Capitals",
"teamTwitter": "#ALLCAPS"
},
"Anderson": {
"id": 757,
"firstName": "Craig",
"lastName": "Anderson",
"teamId": 5,
"teamAbbreviation": "WSH",
"active": false,
"numberOne": false,
"nhlId": 8467950,
"nhlTeamId": 15,
"teamCity": "Washington",
"teamName": "Capitals",
"teamTwitter": "#ALLCAPS"
},
"Holtby":{
"id": 4863,
"firstName": "Braden",
"lastName": "Holtby",
"teamId": 21,
"teamAbbreviation": "VAN",
"active": true,
"numberOne": false,
"nhlId": 0,
"nhlTeamId": 23,
"teamCity": "Vancouver",
"teamName": "Canucks",
"teamTwitter": "#Canucks"
},
"Demko": {
"id": 13876,
"firstName": "Thatcher",
"lastName": "Demko",
"teamId": 21,
"teamAbbreviation": "VAN",
"active": true,
"numberOne": true,
"nhlId": 0,
"nhlTeamId": 23,
"teamCity": "Vancouver",
"teamName": "Canucks",
"teamTwitter": "#Canucks"
},
"Binnington": {
"id": 5908,
"firstName": "Jordan",
"lastName": "Binnington",
"teamId": 17,
"teamAbbreviation": "STL",
"active": true,
"numberOne": true,
"nhlId": 0,
"nhlTeamId": 23,
"teamCity": "St. Louis",
"teamName": "Blues",
"teamTwitter": "#STLBlues"
},
"Husso": {
"id": 13661,
"firstName": "Ville",
"lastName": "Husso",
"teamId": 17,
"teamAbbreviation": "STL",
"active": true,
"numberOne": false,
"nhlId": 8478024,
"nhlTeamId": 23,
"teamCity": "St. Louis",
"teamName": "Blues",
"teamTwitter": "#STLBlues"
}
}
- In
server.js
on line 4const fs = require('fs')
- Import
json file
inserver.js
let data = fs.readFileSync('nhlGoalies.json'), items = JSON.parse(data)
Now I can pass items
into the ui with the EJS module
.
- update
home.ejs
<h3>NHL Goalies</h3>
<ul>
<% for (let item in items) { %>
<li><%= items[item].firstName %> <%= items[item].lastName %> - G (<%= items[item].teamAbbreviation %>)</li>
<% } %>
</ul>
I can share this json data to the public by adding a few more lines of code and generate public API that could be fetched by another app. Sounds fun!
npm install cors
- In
server.js
on line 7const cors = require('cors')
//server.js
const express = require('express')
const ejs = require('ejs')
const port = process.env.PORT || 3000
const fs = require('fs')
let data = fs.readFileSync('nhlGoalies.json'),
items = JSON.parse(data)
const cors = require('cors')
app = express()
app.use(express.static('public'))
app.use(cors())
app.get('/nhlgoalies', allItems)
function allItems(request, response) {
response.send(items)
}
app.get('/nhlgoalies/:nhlgoalie/', search);
function search(request, response) {
let term = request.params.nhlgoalie;
let reply = null;
term = term.charAt(0).toUpperCase()+ term.slice(1).toLowerCase();
if(items[term])
reply = items[term]
else
reply = {status:"Not Found"}
response.send(reply);
}
app.get('/', (req, res) => {
ejs.renderFile('views/home.ejs', {items}, {}, (err, template) => {
if (err) throw err
res.end(template)
})
})
app.listen(port, (err) => {
if(err) throw err
console.log('Server running on port '+port)
})
- Go to http://localhost:3000/nhlgoalies to see the API data.
- To search one item http://localhost:3000/nhlgoalies/samsonov
Live API examples: https://ejs-ssr.herokuapp.com/nhlgoalies https://ejs-ssr.herokuapp.com/nhlgoalies/samsonov
This api can be fetched by using a http Get request. Here is an example of how to get the data from this api using angular and the HttpClient Module
.
this.http.get('https://ejs-ssr.herokuapp.com/nhlgoalies')
.subscribe(data => {
console.log(data)
})