Getting started
editInstall the package and Node.js
Add the Meziantou.Framework.NodeJs package to a project:
dotnet package add Meziantou.Framework.NodeJsThe package does not include Node.js. Install Node.js 16.9 or later on the machines that run your application, and check that the node executable is in the PATH:
node --versionWhen node is not in the PATH, set NodeJsHostOptions.NodeExecutablePath, as described in Configuring the Node.js process.
The examples of this documentation omit the using directives: they need using Meziantou.Framework.NodeJs;, and using System.Text.Json; or using System.Text.Json.Nodes; for the JSON types.
Run JavaScript code
Start a Node.js process, evaluate code, and call a function of a built-in module:
await using var node = await NodeJsHost.StartAsync();
// Evaluate code as the body of an async function
var sum = await node.EvaluateAsync("return 1 + 2;");
Assert.Equal(3, sum.GetInt32());
// Call a function exported by a module: a file, a package, or a built-in module
var text = await node.InvokeAsync("node:util", "format", ["%s has %d items", "cart", 3]);
Assert.Equal("cart has 3 items", text.GetString());- NodeJsHost.StartAsync starts the
nodeprocess. The host is disposable: theawait usingdeclaration stops the process. - EvaluateAsync runs the code as the body of an async function and returns the JSON representation of its result, as a
JsonElement. - InvokeAsync imports a module and calls one of its exports with the arguments.
node:utilis a built-in module of Node.js; the next example calls a file of your own.
Call your own JavaScript
Put your JavaScript code in a module, such as scripts/slug.mjs:
// Turns a title into a URL segment: "Hello, World!" becomes "hello-world"
export function slugify(title) {
return title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
}
// An export that is not a function
export const separator = '-';Copy the folder to the output directory of your application, for instance with <None Update="scripts/**" CopyToOutputDirectory="PreserveNewest" /> in the project file. Then use it as the working directory of the process, and call the function:
await using var node = await NodeJsHost.StartAsync(new NodeJsHostOptions
{
// The folder of the JavaScript files, copied to the output directory of the application
WorkingDirectory = Path.Combine(AppContext.BaseDirectory, "scripts"),
});
var slug = await node.InvokeAsync<string>("./slug.mjs", "slugify", ["Hello, World!"]);
Assert.Equal("hello-world", slug);- A relative module path starts with
./and includes the file extension. It is resolved from the working directory. - InvokeAsync<string> deserializes the result to a .NET type. See Arguments and results for the types you can use, and for the overloads that work with trimming and Native AOT.
- Start one host and reuse it for many calls: starting a process is slow, and a module is loaded once per process. NodeJsHost is thread-safe.
Next steps
- Running JavaScript code and Calling modules: the details of the two kinds of calls, and how npm packages are found.
- Handling errors: what happens when the JavaScript code throws.
- Running calls in parallel: run CPU-bound code on several threads or processes.