-
Notifications
You must be signed in to change notification settings - Fork 3
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 zig
In 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');
console.log = (s) => process.stderr.write(`${s}\n`);
hello();
nw.Window.open('./src/index.html', { width: 800, height: 600 });
And 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 node-zigar init
node-zigar.config.json
will be populated with some default options:
{
"optimize": "ReleaseSmall",
"sourceFiles": {},
"targets": [
{
"platform": "linux",
"arch": "x64"
}
]
}
sourceFiles
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
can be one of the possible values
returned by os.platform
and
os.arch
.
We insert the following into our config file:
{
"optimize": "ReleaseSmall",
"sourceFiles": {
"lib/hello.zigar": "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 node-zigar build
✓ Built module "hello" (win32/x64)
✓ Built module "hello" (win32/arm64)
✓ Built module "hello" (win32/ia32)
✓ Built module "hello" (linux/x64)
✓ Built module "hello" (linux/arm64)
✓ Built module "hello" (darwin/x64)
✓ Built module "hello" (darwin/arm64)
✓ Built Node.js addon (win32/x64)
✓ Built Node.js addon (win32/arm64)
✓ Built Node.js addon (win32/ia32)
✓ Built Node.js addon (linux/x64)
✓ Built Node.js addon (linux/arm64)
✓ Built Node.js addon (darwin/x64)
✓ Built Node.js addon (darwin/arm64)
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.