More client server code sharing

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.

Recap

The key to Sharing code between client and server is this server side code.

paired with this in your client Html template

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 manifests

This 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.
In the client html –

Restrictions

You 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

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.

RequireJs

I 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.
In my index.html, I call them like this
And my manifests look like this

Namespaces

As discussed in Namespaces in libraries and scripts, encapsulating logically separate pieces of code is a pretty good thing to do. It also helps to enable avoiding some of the pitfalls of embedding executable JS code in the GS IDE.

To recap, you can create a namespace like this – shown here with some  variables function that you might otherwise have declared globally

However, using this pattern (function() {...})(); executes the enclosed code, so the content of you namespace (just like the global content) should not be executable if you are combining this with the technique for Sharing code between client and server.

so this is fine,

but this is not, since Apps Script would try to execute something using the document object which only exists client side.

Initialize

You can get round this by equipping namespaces like this with an initialization function in which you embed any code that would otherwise execute

and then when you are ready to go,

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

and this is my main.js – the only Apps Script HTML.js file.

For more like this, see Google Apps Scripts Snippets

Why not join our forum, follow the blog or and follow me on Twitter for more information and updates.