Reputation: 516
I've built few pages of a static website using ExpressJS
and PUG
to get the advantage of the template engine.
But now I need to export all the raw HTML that is being rendered by all ExpressJS
Routes
.
Is there any package that can help me to do that? Or I've to write custom command and iterate over all the Routes
and save the rendered output?
If a custom command is the only way, how do I iterate over all the routes
and get the rendered output?
Upvotes: 2
Views: 1559
Reputation: 87
Edited version of the same answer.
First of all thank you so much for solving this problem. I have made some changes to your code as per new errors.
Here is the code with async and await function for ejs users
const express = require('express')
const ejs = require('ejs')
const fs = require('fs')
const app = express()
const port = 3000
//set the templating engine as ejs
app.set('view engine', 'ejs');
function createTemplateFile(filename) {
fs.open(filename,'r',function(err, fd){
if (err) {
fs.writeFile(filename, '', function(err) {
if(err) {
console.log(err);
}
});
}
});
}
async function exportTemplateFile(templateLocation, templateName) {
var html = await ejs.renderFile(templateLocation);
createTemplateFile('templates/'+templateName);
var stream = fs.createWriteStream('templates/'+templateName);
stream.once('open', function (fd) {
stream.write(`${html}`);
stream.end();
});
}
app.get('/', (req, res, next) => {
res.render('./pages/home')
exportTemplateFile('views/pages/home.ejs', 'index.html');
console.log('file rendered and saved successfully')
})
app.listen(port, () => {
console.log(`App is listening on port ${port}`)
})
Upvotes: 0
Reputation: 516
I couldn't find any library or resource to achieve what I wanted. But with some of my dirty code, hacks, and packages I was able to export all the routes.
Note: Instead of writing a node command to export the htmls, I've added a route to trigger the operations here is the code for the route:
app.use('/export_templates', router.get('/', async function (req, res, next) {
const endpoints = listEndpoints(app);
const failedEndpoints = [];
for (const i in endpoints) {
const endpoint = endpoints[i];
if (endpoint.path == '/export_templates') {
continue;
}
try {
const res = await axios.get('http://'+req.headers.host+''+endpoint.path+'?export=true');
}
catch(error) {
failedEndpoints.push(endpoint.path);
}
}
res.json({
"status": "succes",
"message": "Please check templates folder for the latest exported html templates",
"failed": failedEndpoints
})
}));
Basically this route iterates and makes a request to all the available routes with a export=true
parameter.
Then inside every route view function a condition checks if the export parameter is available then calls the exportTemplateFile
function with the pug
template location and new file name as the function parameter.
If the request doesn't contain export
parameter the requested route will simply output what template.
An example route:
router.get('/', function(req, res, next) {
if (req.query.export) {
exportTemplateFile('views/index.pug', 'index.html');
}
res.render('index.pug');
});
And here is the code for 2 util function to complete the export process
function createTemplateFile(filename) {
fs.open(filename,'r',function(err, fd){
if (err) {
fs.writeFile(filename, '', function(err) {
if(err) {
console.log(err);
}
});
}
});
}
function exportTemplateFile(templateLocation, templateName) {
const html = pretty(pug.renderFile(templateLocation));
createTemplateFile('templates/'+templateName);
var stream = fs.createWriteStream('templates/'+templateName);
stream.once('open', function (fd) {
stream.write(html);
stream.end();
});
}
The createTemplateFile
function simply creates a new file if it doesn't exist.
The exportTemplateFile
function saves the HTML in the html
variable rendered by pug
and prettifies it with the pretty
package and then overwrites the new template file.
Note: In my case all the pug
templates were static so I didn't have to pass any context to the pug.renderFile
function. But if you need any context to be used inside the pug template you can simply pass that with the template location.
Upvotes: 2