How to save rendered html view files from ExpressJS Routes

Viewed 984

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?

1 Answers

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.

Related