I use several templates in a Chrome content script for elements
I'm adding to matched pages.
Currently I'm storing these templates as string
in the script, but I wonder if there are better ways to do this.
tl;dr answer - Yes, you can store them in a <script type="text/html">
tags or load them dynamically through ajax. Examples here (from KnockoutJS) and here. Store them in a file with the proper extension and use an empty tag with an id X, then $("#X").load("/path/to/template", function() { renderX(); })
Long answer with insightful thoughts, keep reading...
As a front end engineer, I learned to keep layers as separate as possible; this helps your team to understand better your code and make it more maintainable. Separating your layers in modules and then assembling them through an "assembly" mechanism is probably one of the best practices in software engineering. Some of the benefits of this practice include:
By keeping views in separate files, other coders can view them and understand an important layer of the system without needing to understand the entire application; even collaboration gets easier when the developer just need to review those specifics files. Through bashing or scripting, even large architectural systems with thousand of "views" like files can be filtered in order to output just what needs to be reviewed.
(By now I hope I convinced you into removing your string from your code and create a new file and it there, otherwise I really need to improve my writing skills)
So, after we have moved our template to an external file, what do we do next?
Javascript doesn't have a default templating feature (heck, it doesn't even have a modular one, although some smart people are working on it for the ECMAScript Ed. 6, yay!), which means that we need to use a templating library for that. Let's assume you are using Mustache, Underscore template of something alike and thus using its library to render it.
Most of those templating engines use the infamous eval
, which can provide a vulnerability to your code, which Chrome Extensions dislike, a lot. The Chrome Extension Dev Team even enforced a new version of the manifest.json
file in order to forbid eval
, and gave developers the choice to use Sandboxing Pages in order to do so. Luckily for us, they decided to relax the policies a little bit and we can continue use it with a proper CSP definition in our manifest.json
.
This means that we need to tackle two problems instead of only one: the "load the template" one and the "render the template in a way won't freak out the new incoming versions of CSP in case the Chrome Extension Dev team change their mind".
Load the template, luckily, can be done through an XML HTTP Request through AJAX. Just point the url with the name of the file and you can receive the template as a string, which was probably your original set up. Here's an example that I do with KnokcoutJS:
$("#aiesecTemplate").load('js/libs/aiesec/aiesecTemplate.html', function() {
ko.applyBindings(AIESECViewModel);
});
The #aiesecTemplate
is a <script type="text/html">
tag that the browser won't render as part of the DOM. You can use that with other template mechanisms in order to actually assemble your DOM. If you have already a solution for this, this is probably the end of the answer and you can move on with your life. If you are wondering how do we render the code from there, keep reading.
The Chrome Dev team suggest us to Sandbox our rendering process due most templating engine libraries being non-CSP compliant (AngularJS being an exception). Here'an excerpt of the code from the Sandbox page.
iframe.contentWindow.postMessage(message, '*');
Where iframe
is a specific DOM Iframe Element from the sandbox page with a src
attribute of a page that has the templating engine; message
has the string template previously loaded, so after posting the message a window.addEventListener
for message
inside the iframe can render it without a problem. More information about sandboxing eval can be read here
If you made it to here, awesome! My answers might not be that boring. As a last note, you might be thinking "What about AMD or RequireJS?"; to be honest I haven't tried them, but really smart people think that AMD is not the best approach. Loading through a XML HTTP Request might not be better, but in case you think it hits your performance (I have used it in my application and it doesn't) you can always use some Event Pages and Web Workers with that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With