Efficient way to deliver .html page

I’ve got an HTML file hanging out in /private/ folder. I use this code to serve it:

    WebApp.connectHandlers.use('/', function(req, res, next) {
        if (req.url.startsWith('/link')) {
            res.writeHead(200);
            var html = Assets.getText('link.html')
            SSR.compileTemplate('200',html)
            res.end(SSR.render('200'));
        }
    });

Everything works nicely… EXCEPT it seems to be encoding some of my text. For example, a script tag that contains:
var url = "/api?id=1&page=1"
becomes
var url = "/api?id=1&page=1"

That additional & messes everything up and is not in my original .html file.

Is there a better way for me to serve this resource without it getting encoded by SSR? I’ve verified that when using Assets.getText it keeps the original form. The change seems to happen somewhere within SSR.compileTemplate.

Perhaps there’s a different way to deliver this one-off HTML page?

It’s been forever since I’ve used Blaze, but I believe you can do this without a package for SSR. If it’s just HTML and not a Blaze template, then you should be able to just write it to the response. Otherwise, you can use SpacebarsCompiler.compile and Blaze.toHTML to render the template to a string and then write it to the response. The following code has not been checked to be working but it should at hopefully get you close.

    import { Blaze } from 'meteor/blaze';
    import { SpacebarsCompiler } from 'meteor/spacebars-compiler';

    WebApp.connectHandlers.use('/', function(req, res, next) {
        if (req.url.startsWith('/link')) {
            let template = Assets.getText('link.html');
            let compiled = eval(SpacebarsCompiler.compile(template, { isTemplate:true }));
            let html = Blaze.toHTML(compiled);

            res.statusCode = 200
            res.setHeader('Content-type', 'application/json');
            res.write(html);
        }
    });

Thanks @copleykj! Tried your code (with a few tweaks) but it was still changing & to &.

And then I decided to go super, duper simple:

    var htmlmin = require('htmlmin'); // simple minification
    WebApp.connectHandlers.use('/', function(req, res, next) {
        if (req.url.startsWith('/link')) {
            var html = htmlmin(Assets.getText('link.html'),{collapseWhitespace:true})
            res.statusCode = 200;
            res.end(html);
        }
    });

And that works! As simple as bringing in the HTML file with Assets.getText and then serving that. Seems too simple to be true – hope I’m not missing anything!

If you need a server side router (for dynamic routes), check out Picker: The trusted source for JavaScript packages, Meteor resources and tools | Atmosphere

1 Like

Thanks for the tip! It seems a bit unnecessary? If I’m not mistaken you can still interact with the database in the code sample I provided. For example:

    WebApp.connectHandlers.use('/', function(req, res, next) {
        if (req.url.startsWith('/link')) {
            var html = Assets.getText('link.html')
            var id   = req.url.replace('/link/','').split('?')[0]
            var data = Links.findOne({id:id})
            if (data) var html = html
                           .replace("title_variable",data.title)
                           .replace("img_variable",data.img)
            res.statusCode = 200;
            res.end(html);
        }
    });

This is working fine in production for me. No additional packages required :slight_smile:

2 Likes