In Sharing code between client and server I wrote about how you could write code that could be used by both your client JavaScript and your server Apps Script, so you could pool utility functions when writing Add-ons and HTMLService and also manage all your code in the Apps Script IDE GS editor. Then in Namespaces in libraries and scripts, I showed how you could encapsulate code in its own namespace. Together, these two techniques make a powerful combination to help you avoid rewriting stuff and making global namespace errors. But you have to watch out for a few things. RecapThe key to Sharing code between client and server is this server side code. /** * given an array of .gs file names, it will get the source and return them concatenated for insertion into htmlservice * like this you can share the same code between client and server side, and use the Apps Script IDE to manage your js code * @param {string[]} scripts the names of all the scripts needed * @return {string} the code inside script tags */ function requireGs (scripts) { return '<script>\n' + scripts.map (function (d) { return ScriptApp.getResource(d).getDataAsString(); }) .join('\n\n') + '</script>\n'; } paired with this in your client Html template <?!= requireGs (['usefulThings' , 'clientJs']); ?> This will bring in any code in usefulThings.gs and clientJs.gs - normal Apps Script files that you can use server side if you want - into your client side script which will then be available for client side use by HTML service. Using script manifestsThis version of requireGs allows the client to request any Apps Script file. It may be that you want to lock that down (for example if this project is also being used as a library you may not want to expose a function that can pick up any script file), or maybe you simply prefer to manage access to script source on the server side. Here is an alternative version where you can manage the scripts authorized for client side execution from the server. The client requests a set of scripts by referencing a manifest name. requireGsManifest() on the server knows which scripts make up that manifest. /** * given a manifest name it will get the source and return them concatenated for insertion into htmlservice * like this you can share the same code between client and server side, and use the Apps Script IDE to manage your js code * @param {string} manifest the manifest name * @return {string} the code inside script tags */ function requireGsManifest (manifest) { var manifests = [ { name: 'sankeysnip', scripts: ['Utils', 'Sankey' , 'Shared' , 'View' ,'Home' ,'App', 'Client'] } ]; // find requested manifest var target = manifests.filter (function (d) { return d.name === manifest }); // should be exactly 1 if(target.length !== 1) { throw 'manifest ambiguous ' +manifest; } // get all the script contents return '<script>\n' + target[0].scripts.map (function (d) { return ScriptApp.getResource(d).getDataAsString(); }) .join('\n\n') + '</script>\n'; } <?!= requireGsManifest('sankeysnip'); ?> RestrictionsYou can have any kind of JavaScript in your feeder Apps Script files - even ones that access the DOM, or other objects that don't exist in Apps Script - just so long as Apps Script does not attempt to execute them. So this can live perfectly happily within the App Script IDE as a .gs file function foo () { console.log('im not executed'); var d = document.getElementById('bar'); } but this outside a function will cause an error - which is not a bad thing actually, since execution of things in global space often leads to unexpected behavior. var d = document.getElementById('bar'); RequireJsI also use a similar method to pick up pure js that I've decided to maintain in HTML files (as opposed to GS) files. Like requireGs, there's both a manifest and list version. /** * given an array of .html file names, it will get the source and return them concatenated for insertion into htmlservice * @param {string[]} scripts the names of all the scripts needed * @return {string} the code inside script tags */ function requireJs (scripts) { return '<script>\n' + scripts.map (function (d) { return HtmlService.createHtmlOutputFromFile(d+".js").getContent(); }) .join('\n\n') + '</script>\n'; } /** * given a manifest name it will get the source and return them concatenated for insertion into htmlservice * @param {string} manifest the manifest name * @return {string} the code inside script tags */ function requireJsManifest (manifest) { // find requested manifest var target = manifests.filter (function (d) { return d.name === manifest }); // should be exactly 1 if(target.length !== 1) { throw 'manifest ambigous ' +manifest; } // get all the script contents return '<script>\n' + target[0].scripts.map (function (d) { return HtmlService.createHtmlOutputFromFile(d + ".js").getContent(); }) .join('\n\n') + '</script>\n'; }
|
Example
The benefits of this approach is that you can have code that can execute perfectly happily on both client and server containing Vanilla JavaScript living alongside in the Apps Script IDE, but separated from, code that is specific for either the Server or the Client.
Here's an example from one of my add-ins
My html content
I'm picking up all these script files from the Apps Script IDE, some of which I use both server and client side
<?!= requireGs (['Utils' , 'Sankey' , 'Shared' , 'View' ,'Home' ,'App', 'Client']); ?>
<?!= requireJs (['main']); ?>
and this is my main.js - the only Apps Script HTML.js file.
window.onload = function () {
// set up client app structure
App.initialize();
// initialize this page
Home.initialize();
// get some data to the client and start
Client.getData();
};
You want to learn Google Apps Script?
Learning Apps Script, (and transitioning from VBA) are covered comprehensively in my my book, Going Gas - from VBA to Apps script, available All formats are available now from O'Reilly,Amazon and all good bookshops. You can also read a preview on O'Reilly.
If you prefer Video style learning I also have two courses available. also published by O'Reilly.
Google Apps Script for Developers and Google Apps Script for Beginners.
Learning Apps Script, (and transitioning from VBA) are covered comprehensively in my my book, Going Gas - from VBA to Apps script, available All formats are available now from O'Reilly,Amazon and all good bookshops. You can also read a preview on O'Reilly.
If you prefer Video style learning I also have two courses available. also published by O'Reilly.
Google Apps Script for Developers and Google Apps Script for Beginners.