NodeJS Packages and Matrix


(Gavin Boyd) #1

Matrix supports SSJS using V8 - does that enable you to within Matrix use NodeJS packages if they have been installed on the Matrix server? Can they be called using Require? For exmaple:

<script runat="server">
  var gulp = require('gulp');
  var parallel = require('concurrent-transform');
  gulp.task('parallel', function() {...});
</script>

Is that possible?


(Bart Banda) #2

No, it doesn’t have access to those files on the server. However, if the file is web browserable, you can include it as a reference first and then call functions from it.

<script runat="server" src="plugins.js"></script>
<script runat="server">
    runPluginFunction();
</script>

(*) #3

@gboyd Just make sure you’re running the latest Matrix version, if possible.

I’ve found/reported a variety of bugs to do with the order of SSJS execution, context of SSJS, the content of the JS itself affecting if it works and areas where SSJS doesn’t (or didn’t, depending on your version) run at all. For instance, in the case of the latter if you’re on Matrix < 5.4.1.1, you’ll find that SSJS just gets sent to the browser and not processed on 404 pages, password change and Login Designs.

You’ll also need to watch out if your JS package/library ends in a comment or whitespace; versions prior to 5.4.1.0 had a bug which broke execution (https://squizmap.squiz.net/matrix/10525). In general if something’s not looking right, do a search on the SquizMap; I tried to outline workarounds to various situations (such as https://squizmap.squiz.net/matrix/10584 where rendering a bodycopy div causes execution problems).

Also, definitely check out http://browserify.org/ to help get your npm modules into a browser/SSJS compatible form. Good luck.


(Gavin Boyd) #4

We are using v5.4.0.2

Tried including the file - but this breaks all output.

<script runat="server">
  print('tester');
</script>
<script runat="server" src="//cdn.ulster.ac.uk/home/ulster-frontend/maxmind/bundle.js"></script>
<script runat="server">
  print('tester');
</script>

How do you debug SSJS in Matrix?


(Bart Banda) #5

You need to download the file and upload it as a file asset in matrix to reference. Including a JS file only works with Matrix JS file assets (or git bridge js files).

If you have hide errors on the frontend turned off, you should get the JS error show up on the frontend when you try and view the page.


(David Schoen) #6

It might be worth being clear that V8JS as available in PHP (and used by Matrix for SSJS) doesn’t have any of the async (promises, setInterval, setTimeout, etc) or IO (loading files locally from network or local disk) functions that you might be expecting from the V8 engine in Node or any of the XHR available in a browser.

As Bart says you have to have all the code available in Matrix because by the time it hits V8JS Matrix has to have compiled a single JS blob that has everything required to run already in it.


(*) #7

In this case, definitely read through all the bug reports I’ve made (https://squizmap.squiz.net/matrix/_reports/contributed?creatorOR=-1374); you’ll likely encounter all of those bugs because you’re on such an early version of SSJS support. If you’re able to upgrade Matrix, definitely try and do so first.

In terms of debugging, if you can, turn off hiding of front end errors and again, if you can, access the system’s error log. In my case, I have access to do neither because we only have a production environment so I use the ?SQ_DISABLE_SERVER_JS query string (https://matrix.squiz.net/manuals/concepts/chapters/server-side-javascript#disabling-ssjs) which causes all the SSJS to just dumped into the page sent to your browser. You can then use your browser’s debug console to pinpoint problems. It’s fiddly but you can get by if you ensure your keyword use, if present, still makes for valid JavaScript.

With our hosted setup, there’s been ambiguity around exactly what version of JavaScript (eg through V8Js) was being run so I found that writing an SSJS ‘introspector’ (eg using JS’s Object.getOwnPropertyNames(global) where global is the global object) was extremely helpful in determining what objects and functions exist in our environment. Overall, I determined our setup was somewhere between ECMAScript 5.1 and 6 – certain syntax from 6 works but most doesn’t; YMMV.