Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockout.js external templates without require.js

I'm wondering if there's another way of using templates in knockout.js without having to use require.js to load them dynamically.

It adds around 20Kb after minification more to the site and it seems we are loading quite a big library to do something that probably wouldn't need as much code behind it.

This is what I'm doing now:

ko.components.register('menu', {
    viewModel: { instance: mm.viewModel },
    template: { require: 'text!views/menu.html' },
});

To do so I had to include require.js in my project and requrie text`:

<script type="text/javascript">
    requirejs.config({
        paths: {
            text: 'bower_components/text/text'
        },

        urlArgs: "v=" + new Date().valueOf()

    });
</script>
like image 354
Alvaro Avatar asked Mar 14 '26 16:03

Alvaro


1 Answers

I ended up getting the file from the server side with my own call.

In node (but this can be done in PHP or any other language as well), I added a route to retrieve the requested file:

router.get('/loadFile/', function(req, res, next){
    var params = req.query;
    var demo = express.static(path.join(res.locals.virtualDirPath, 'public'));

    fs.readFile( __dirname + '/../public/elements/' + params.filename, "utf-8", function read(err, data) {
        if (err) {
            throw err;
        }

        // Invoke the next step here however you like
        return res.send(data);

        processFile(); 
    });
});

Then I created my own custom component loader in the Javascript side as detailed in the docs.

var templateFromUrlLoader = {
    loadTemplate: function(name, templateConfig, callback) {
        var newUrl = url + 'others/loadFile/';
        var params = { 'filename' : templateConfig.filename };

        if (templateConfig.filename) {
            // Uses jQuery's ajax facility to load the markup from a file
            $.get(newUrl, params, function(markupString) {
                // We need an array of DOM nodes, not a string.
                // We can use the default loader to convert to the
                // required format.
                ko.components.defaultLoader.loadTemplate(name, markupString, callback);
            });
        } else {
            // Unrecognized config format. Let another loader handle it.
            callback(null);
        }
    }
};

// Registering it
ko.components.loaders.unshift(templateFromUrlLoader);

This way I saved myself from having to load 84Kb of require.js for this simple task. Plus I'm not limited this way to the use of require.js and I can use a single combined and minified file for production environments.

Also, I'm in total control over the caching of the returned templates, which used to cause me problems when using require.js.

like image 137
Alvaro Avatar answered Mar 16 '26 04:03

Alvaro