Skip to content

Instantly share code, notes, and snippets.

@sinau123
Created February 26, 2021 04:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sinau123/595aacb4ce84a537b19f2a0a4a2d9cdc to your computer and use it in GitHub Desktop.
Save sinau123/595aacb4ce84a537b19f2a0a4a2d9cdc to your computer and use it in GitHub Desktop.
Vue & Node js SSR hack
require('dotenv').config()
const express = require('express');
const app = express();
const path = require('path');
const fetch = require("node-fetch");
const fs = require('fs')
app.use(express.static(path.join(__dirname, '../dist'), { index : false }))
//default meta tag
const metaTagsFb = [
{name: "og:type", content: "website"},
{name: "og:site_name", content: "my-domain.org"},
{name: "og:title", content: "My Web Title"},
{name: "og:image", content: "https://www.my-domain.org/img/landing.png"},
{name: "og:description", content: "this is my web description."},
{name: "og:url", content: "https://www.my-domain.org"},
{name: "og:image:type", content: "image/png"},
{name: "og:image:alt", content: "Image alt"},
]
// default meta for twitter
const metaTagsTw = [
{name: "twitter:card", content: "summary_large_image"},
{name: "twitter:site", content: "@MyTwitterAccount"},
{name: "twitter:title", content: "My Web Title"},
{name: "twitter:description", content: "this is my web description."},
{name: "twitter:image", content: "https://www.my-domain.org/img/landing.png"},
]
//path to vue js dist index.html
const indexPath = path.join('/dist/index.html')
const idxHtml = fs.readFileSync('..' + indexPath).toString();
const normHtml = (_tw, _fb) => {
const twTag = _tw.map(({name, content}) => {
return `<meta name="${name}" content="${content}" />`
}).join('')
const fbTag = _fb.map(({name, content}) => {
return `<meta property="${name}" content="${content}" />`
}).join('')
return idxHtml.replace(/<\/head>/g, fbTag + twTag + '</head>')
}
const serveDetail = async (req, res) => {
try {
// get data from API
const response = await fetch(`${process.env.BASE_API_URL}/post/${req.params.id}`);
const json = await response.json();
if (json.code != 0) {
throw `Cannot get issue with id: ${req.params.id}`
}
const {id, classification_num, name, desc} = json.result
const title = `[${statusToStr(classification_num)}] ${name.trim()}`;
const img = `${process.env.BASE_API_URL}/post/${id}.png`;
const url = process.env.BASE_URL + id;
const _fb = metaTagsFb.filter(x => !['og:title', 'og:image', 'og:url', 'og:description'].includes(x.name));
_fb.push({name: "og:title", content: title});
_fb.push({name: "og:image", content: img});
_fb.push({name: "og:url", content: url});
_fb.push({name: "og:description", content: desc.trim()});
const _tw = metaTagsTw.filter(x => !['twitter:title', 'twitter:image', 'twitter:description'].includes(x.name));
_tw.push({name: "twitter:title", content: title});
_tw.push({name: "twitter:image", content: img});
_tw.push({name: "twitter:description", content: desc.trim()});
res.send(normHtml(_tw, _fb))
} catch (error) {
console.log('Error: ' + error);
res.send(normHtml(metaTagsTw, metaTagsFb))
}
};
// if user share post detail page
app.get('/post/:id', function(req, res) {
serveDetail(req, res);
});
// other route will use default meta
app.get('*', function(req, res) {
res.send(normHtml(metaTagsTw, metaTagsFb))
});
app.listen(parseInt(process.env.PORT), () => console.log(`App is ready\nlistening on port ${process.env.PORT}`));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment