How to run ClearScript V8 JavaScript engine in Azure

UPDATE JANUARY 25, 2016: ReactJS.NET from version 2.2 onwards supports V8 JavaScript engine in Azure out of the box. You can read the official Azure documentation I’ve written for ReactJS.NET for more details.

I’m developing a ReactJS.NET application that makes heavy use of server side rendering (tutorial here). It’s built on the latest ASP.NET 5 MVC 6 stack and runs as an Azure Web App. It all seemed to be working just fine locally but when deployed to Azure everything blew up.

I was suddenly getting a bunch of weird JavaScript errors from ReactJS.NET trying to do server side rendering:

Error while loading "~/build/server.bundle.js": Object.create: implementation only accepts one parameter.

Error while loading "~/build/server.bundle.js": Expected identifier, string or number

After several hours of figuring out what was happening here’s what I found:

  1. ReactJS.NET uses different JS engines based on what’s available on your machine
  2. Locally I was running MSIE ChakraJsRt (comes with Microsoft Edge browser)
  3. Azure was running another MSIE engine (probably Classic JS)
  4. I had installed react-bootstrap components and Azure’s engine wasn’t able to render them and threw those JavaScript exceptions.

Damn, there had to be a way around. And there was.

ClearScript V8 JavaScript Engine

It turns out that ReactJS.NET supports (and prefers, if it’s available) a ClearScript V8 JavaScript Engine which is much faster and better than the MSIE engine that Azure is using. It comes installed with ReactJS.NET but it seems like it’s not working out of the box for ASP.NET 5 projects.

ReactJS.NET determines the best available engine using a library called JavaScriptEngineSwitcher. All we should now do is make it find the V8 engine both locally and in Azure so let’s get going.

Running V8 locally

First let’s force ReactJS.NET to only run in the V8 engine (by disallowing MSIE engines). In your Startup.cs set the value for AllowMsieEngine to false:

app.UseReact(config =>
{
    config
        .SetReuseJavaScriptEngines(false)
        .SetAllowMsieEngine(false)
        .AddScriptWithoutTransform("~/build/server.bundle.js");

});

If you try to run your application now it will throw an exception if the V8 engine isn’t available instead of just silently falling back to an MSIE engine. The next step is to manually copy the binaries of JavaScriptEngineSwitcher and the V8 engine to a folder where our application can find them.

Unfortunately for ASP.NET 5 people ReactJS.NET is using and older version (1.2.4) of JavaScriptEngineSwitcher.V8 package that isn’t compatible with ASP.NET 5 because it requires a configuration section in a web.config. A later version (1.41.) fixes this issue. Fortunately there’s a way to force ReactJS.NET to use the later version by installing the packages separately in the Package Manager.

Uninstall-Package React.AspNet
Install-Package JavaScriptEngineSwitcher.Core
Install-Package JavaScriptEngineSwitcher.Msie
Install-Package JavaScriptEngineSwitcher.V8
Install-Package React.AspNet -IgnoreDependencies

You should now have the latest versions of JavaScriptEngineSwitcher installed and ReactJS.NET using them. We can now continue and copy the following binaries manually from C:\Users\username.dnx\packages to C:\Users\username.dnx\runtimes\yourruntime\ClearScript.V8:

  • JavaScriptEngineSwitcher.Core\1.2.4\lib\net40\JavaScriptEngineSwitcher.Core.dll
  • JavaScriptEngineSwitcher.V8\1.4.1\lib\net40\JavaScriptEngineSwitcher.V8.dll
  • JavaScriptEngineSwitcher.V8\1.4.1\lib\net40\ClearScript.dll
  • JavaScriptEngineSwitcher.V8\1.4.1\content\ClearScript.V8\ClearScriptV8-32.dll
  • JavaScriptEngineSwitcher.V8\1.4.1\content\ClearScript.V8\ClearScriptV8-64.dll
  • JavaScriptEngineSwitcher.V8\1.4.1\content\ClearScript.V8\v8-ia32.dll
  • JavaScriptEngineSwitcher.V8\1.4.1\content\ClearScript.V8\v8-x64.dll

If you try running your application now it should run just fine using the V8 engine!

Running V8 in Azure

To make V8 run in Azure we simply need to include the same V8 and JavaScriptEngineSwitcher binaries in our deployment as we did locally. I’m using a gulp task to copy the binaries automatically on deployment (sorry, it’s a bit ugly but works):

var exec = require('child_process').exec;

gulp.task("copy-v8-runtime", function () {
    var packages = "C:\\Users\\username\\.dnx\\packages\\";
    var dest = "C:\\Users\\username\\AppData\\Local\\Temp\\PublishTemp\\projectfolder\\approot\\runtimes\\yourruntime\\ClearScript.V8";

    execLog('if not exist "' + dest + '" mkdir "' + dest + '"')
    execLog('copy /Y "' + packages + 'JavaScriptEngineSwitcher.Core\\1.2.4\\lib\\net40" "' + dest + '"')
    execLog('copy /Y "' + packages + 'JavaScriptEngineSwitcher.V8\\1.4.1\\lib\\net40" "' + dest + '"')
    execLog('copy /Y "' + packages + 'JavaScriptEngineSwitcher.V8\\1.4.1\\content\\ClearScript.V8" "' + dest + '"')
});

function execLog(command) {
    exec(command, function (err, stdout, stderr) {
        console.log(stdout);
        console.log(stderr);
    });
}

The last step is to wire this as a post publish script in project.json:

"scripts": {
    "postpublish": [ "gulp copy-v8-runtime" ]
}

If you now publish your project from Visual Studio the binaries should be automatically included in the deployment. Enjoy your application running in Azure using the V8 JavaScript engine!