Robin
Robin

Reputation: 516

How to save rendered html view files from ExpressJS Routes

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

Answers (2)

xdayaan
xdayaan

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

Robin
Robin

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

Related Questions