はじめに
Electronでデスクトップアプリを作ったことがある方なら、「レンダラープロセスから直接Node.jsのAPIを叩けたら楽なのに」と思った経験があるのではないでしょうか。Electronではセキュリティ上の理由から、レンダラーとメインプロセスの間にpreloadスクリプトやcontextBridgeを挟む必要があり、ちょっとしたファイル操作をしたいだけでもIPC(プロセス間通信)の実装が求められます。
実は、その面倒さを最初から抱えていないデスクトップアプリフレームワークがあります。それが今回紹介するNW.jsです。ElectronよりもGitHub登場が早く、DOMとNode.jsが同じコンテキストで動くというシンプルな設計思想を持ち続けています。
NW.jsとは
NW.js(旧称: node-webkit)は、HTML・CSS・JavaScriptといったWeb技術だけでデスクトップアプリケーションを構築できるフレームワークです。ChromiumとNode.jsを組み合わせて動作し、Webページのスクリプトからrequire()でNode.jsのモジュールをそのまま呼び出せる点が最大の特徴です。
Intel主導で開発が始まり、現在もオープンソースコミュニティによってメンテナンスが続けられています。2026年時点でもv0.113系がリリースされており、最新のChromiumとNode.jsに追従し続けています。
主な特徴
- DOM/WebWorkerから直接Node.jsを呼び出せる - preloadスクリプトやcontextBridgeのような橋渡しが不要で、HTML内のスクリプトから
fsやchild_processなどをそのまま利用できます - package.jsonの
mainにHTMLを直接指定できる - エントリーポイントがそのままウィンドウの中身になるため、最小構成のアプリを数行で書けます - Node.jsとChromiumが同一プロセスで動作 - Electronのようにメイン/レンダラーでプロセスを分ける必要がなく、構成がシンプルです
- Chrome Appsに近いAPI群を提供 - システムトレイやクリップボード、メニューバーなど、デスクトップアプリに必要なネイティブ機能をカバーしています
インストール
npmからnwパッケージとしてインストールできます。開発時のランタイムとしてdevDependenciesに追加するのが一般的です。
# npmの場合
npm install --save-dev nw
# yarnの場合
yarn add -D nw
# pnpmの場合
pnpm add -D nw
インストール後は、プロジェクトルートで以下のように実行するだけでアプリを起動できます。
npx nw .
基本的な使い方
まずはプロジェクトの起点となるpackage.jsonを用意します。Electronと異なり、mainフィールドにJavaScriptではなくHTMLファイルを指定できるのがポイントです。
{
"name": "nwjs-sample",
"main": "index.html",
"version": "1.0.0",
"window": {
"title": "NW.js Sample",
"width": 800,
"height": 600
}
}
次に、index.htmlを作成します。<script>内からrequire()を呼べる点に注目してください。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>NW.js Sample</title>
</head>
<body>
<h1>Hello, NW.js!</h1>
<p id="path-info"></p>
<script>
// ブラウザのスクリプトから直接Node.jsのモジュールを呼び出せる
const os = require('os');
const path = require('path');
document.getElementById('path-info').textContent =
`作業ディレクトリ: ${process.cwd()} / OS: ${os.platform()}`;
</script>
</body>
</html>
これだけで、Node.jsのAPIにアクセスできるウィンドウアプリが完成します。IPC通信の設計やプリロードスクリプトの用意は不要です。
npx nw .
実践的なユースケース
ローカルファイルを扱うツール
NW.jsが力を発揮するのは、ローカルファイルシステムに頻繁にアクセスするツールです。例えば、フォルダ内のファイル一覧を読み込んで画面に表示するシンプルなビューアーは、以下のように書けます。
<script>
const fs = require('fs');
const path = require('path');
function renderFileList(targetDir) {
const listEl = document.getElementById('file-list');
listEl.innerHTML = '';
const entries = fs.readdirSync(targetDir);
entries.forEach((entry) => {
const li = document.createElement('li');
li.textContent = entry;
listEl.appendChild(li);
});
}
renderFileList(path.join(process.cwd(), 'sample-data'));
</script>
Electronであれば、このfs.readdirSyncの呼び出しはメインプロセス側に置き、ipcRenderer.invoke経由で結果を受け取る設計が必要になります。NW.jsではその手間がなく、フロントエンドのロジックとファイル操作を同じファイル内に自然に書けます。
既存のNode.js製CLIツールをGUI化する
すでにNode.jsで書かれたCLIツールがある場合、そのモジュールをほぼそのままrequire()して、結果をHTML上に描画するだけでGUI版を作れます。ロジック側の再実装が最小限で済むのは、社内ツールをGUI化したいときに大きな利点です。
<script>
const { execSync } = require('child_process');
document.getElementById('run-btn').addEventListener('click', () => {
try {
const result = execSync('node ./scripts/build-report.js').toString();
document.getElementById('output').textContent = result;
} catch (err) {
document.getElementById('output').textContent = `エラー: ${err.message}`;
}
});
</script>
まとめ
NW.jsは、Webの技術資産をそのままデスクトップアプリに持ち込みたいときに、Electronとは違うアプローチを提供してくれるフレームワークです。DOMからNode.jsを直接呼び出せる設計により、IPCやプリロードスクリプトを意識せずにシンプルな構成でアプリを組み立てられます。特に、既存のNode.jsロジックをそのまま活かしたい場合や、ファイルシステム操作が中心の社内ツールを素早くGUI化したい場合に向いています。
一方で、レンダラーとNode.jsの境界がないぶん、Webページとして外部コンテンツを表示するような用途ではセキュリティ設計により注意が必要です。まずはnwパッケージをインストールして、小さなツールから試してみてはいかがでしょうか。