-
Notifications
You must be signed in to change notification settings - Fork 6
Hello world (NW.js)
In this example we're going to create a very simple app that outputs "Hello world!" to the console through Zig. It demonstrates the basics of working with node-zigar and the steps for deploying an app on multiple platforms.
We begin by starting a Node project. Open a terminal window and run the following command:
``sh mkdir hello cd hello npm init -y
Next, we install node-zigar:
```sh
npm install node-zigar
Create directories for storing web contents (.js, .html, .etc) and Zig source code:
mkdir src zigIn the zig directory, add hello.zig:
const std = @import("std");
pub fn hello() void {
std.debug.print("Hello world!", .{});
}Then index.js in src:
require('node-zigar/cjs');
const { hello } = require('./zig/hello.zig');
__zigar.on('log', ({ source, message }) => {
process[source].write(message + '\n');
return true;
});
hello();
nw.Window.open('./src/index.html', { width: 800, height: 600 });NW.js doesn't display output sent to Node.js's development console. That's why we need to add a listener for the 'log' event and output the text manually.
Finally, add an index.html:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>In package.json, adjust the path to main script:
"main": "src/index.js",At this point the app is ready to be tested. If you haven't done so already, download the SDK version of NW.js from its homepage and decompress the package into a directory. In the terminal, run the following command:
[directory]/nw .You should see our message among various debug messages:
[40512:40512:0322/200448.763374:ERROR:policy_logger.cc(156)] :components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc(161) Cloud management controller initialization aborted as CBCM is not enabled. Please use the `--enable-chrome-browser-cloud-management` command line flag to enable it if you are not using the official Google Chrome build.
[0322/200448.828318:ERROR:elf_dynamic_array_reader.h(64)] tag not found
[0322/200448.829505:ERROR:elf_dynamic_array_reader.h(64)] tag not found
Hello world!
When you use require on a Zig file, node-zigar will place the resultant library file at a temporary
location. At the root level of the app you will notice a .zigar-cache sub-directory with the
following structure:
📁 .zigar-cache
📁 zig-34cc0bd0
📁 Debug
📁 hello.zigar
📑 linux.x64.so
📁 node-zigar-addon
📑 linux.x64.node
hello.zigar is a node-zigar module. It's a directory containing dynamic-link libraries for
different platforms. node-zigar-addon is the Node.js native addon used to load node-zigar
modules. It too comes in platform-specific versions.
The files in the cache directory aren't ones we want delivered to end-users. They're compiled at the
Debug level and are therefore large and slow. Moreover, they only cover the platform we're using
for development (Linux in this case) and not others (Windows and Mac).
To prepare our app for deployment, we first change the require statement so that it references a
.zigar instead, stored at a more permanent location:
const { hello } = require('./lib/hello.zigar');We then create a configure file for node-zigar with the help of its CLI script:
npx zigar initnode-zigar.config.json will be populated with some default options:
{
"optimize": "ReleaseSmall",
"modules": {},
"targets": [
{
"platform": "linux",
"arch": "x64"
}
]
}modules maps .zigar modules to source files. Paths are relative to the config file.
optimize can be Debug, ReleaseSafe, ReleaseSmall, or ReleaseFast.
targets is a list of cross-compile targets. platform and arch should be a combination of
possible return values from os.platform and
os.arch.
We insert the following into our config file:
{
"optimize": "ReleaseSmall",
"modules": {
"lib/hello.zigar": {
"source": "zig/hello.zig"
}
},
"targets": [
{ "platform": "win32", "arch": "x64" },
{ "platform": "win32", "arch": "arm64" },
{ "platform": "win32", "arch": "ia32" },
{ "platform": "linux", "arch": "x64" },
{ "platform": "linux", "arch": "arm64" },
{ "platform": "darwin", "arch": "x64" },
{ "platform": "darwin", "arch": "arm64" }
]
}Then we ask node-zigar to create the necessary library files:
npx zigar build✓ Built module "hello" (win32/x64)
✓ Built module "hello" (win32/arm64)
✓ Built module "hello" (win32/ia32)
✓ Built module "hello" (linux/arm64)
✓ Built module "hello" (darwin/x64)
✓ Built module "hello" (darwin/arm64)
✓ Built module "hello" (linux/x64)
✓ Built Node.js addon (win32/x64)
✓ Built Node.js addon (win32/arm64)
✓ Built Node.js addon (win32/ia32)
✓ Built Node.js addon (linux/arm64)
✓ Built Node.js addon (darwin/x64)
✓ Built Node.js addon (darwin/arm64)
✓ Built Node.js addon (linux/x64)
When the script finishes, start the app again to confirm that it's correctly configured.
NW.js does not have an official packager. The unofficial ones, meanwhile, are not well maintained. You'll need to create packages manually using these instructions.
It's not a difficult task. Simply download the packages for the platforms you intend to support from the download page, decompress them, then place copies of the app at the appropriate locations. You will need to copy the following:
📁 lib
📁 node_modules
📁 src
📄 package.json
You must omit node-zigar.config.json to prevent node-zigar from attempting recompilation.
You can find the complete source code for this example here.
Congratulation! You have created your first cross-platform app with the help of NW.js and node-zigar. As console output is hidden when the app is launched from the graphical interface, you might not be entirely convinced it's working correctly. In the next example we're going to create an app that performs more visible (and useful) work.