おそらく注目されるのは、ソフトウェアの配布部分でしょう。
🌟マークのところですよ。

個人サイト制作:サイトマップへ戻る

Web制作の技術でソフトウェアを作る

Web制作の技術は幅広く使えるんですよね。
このページの主旨は「HTML・CSS・JavaScriptでパソコンソフトを作ろう」というものです。
その気になればいくらでも機能拡張できますし、ちょっとした便利ソフトくらいなら、わりと簡単に作れるもんですよ?

それでは、まず私が作った「フローティング・ランチャー」をご紹介した後、実際の手順とソースコードへ話題を移します。

マルチプラットフォーム対応のフローティング・ランチャー

私は整理されたデスクトップが好きです。
ある日、壁紙を邪魔しないランチャーソフトが欲しくなったのですが、フリーソフトで「これだ!」と思うソフトを見つけられませんでした😵‍💫
ずっとLinuxを使っていて、Windowsが久しぶりだったこともあってね…
そこで、自分でこういうソフトを作っちゃったのですよ。

feinlauncher

これはWindows11のデスクトップです。
壁紙はアナザーエデンというゲームのものですよ。
綺麗でしょう?
ちょっとランチャーソフトだけを拡大しましょうか。

feinlauncher

こういう感じの、テキストベースのフローティング・ランチャーです。
でも最前面には表示させず、あくまでも自分が使っているソフトが主体となるようにしてます。

また、Windows・Mac・Linuxを問わず動作します。
元がWeb技術だからさ。
新しくLinuxをインストールしても、このソフトは活躍してくれるでしょう。

自作ソフトをスタートアップに登録する

何も自作ソフトに限ったことではありませんが、Windows11の起動時にソフトを起動するには、次のようにします。

フェードアウト効果の草花写真
1. ショートカットの作成
fein_launcher.exe ファイルを右クリックし、「ショートカットの作成」を選択します。
2. スタートアップフォルダを開く
スタートメニューの検索バーに「shell:startup」と入力し、Enterキーを押します。
3. ショートカットをスタートアップフォルダに移動
作成したショートカットを、開いたスタートアップフォルダにドラッグ&ドロップします。

これで次回Windowsを起動すると、fein_launcher.exe によってフローティング・ランチャーが自動的に起動するようになります。
では、そろそろ実際の作り方へ話題を移しましょう。

Web技術でソフトウェアを作る手順

いろんな方法があるのですが、私は次のようなやり方をしています。

Node.js
JavaScriptを使ってサーバーサイドのプログラムを書けるツール。
npm
Node.jsのためのパッケージ管理ツール。ライブラリやツールを簡単にインストール・管理できる。
Electron
Web技術(HTML、CSS、JavaScript)でデスクトップアプリを作るためのフレームワーク。

上記3つを使ってソフトを作る手順は、次の通りです。

フェードアウト効果の草花写真
  1. Node.jsとnpmをインストール
  2. プロジェクトディレクトリの作成
  3. Electronのインストール
  4. リソースとなるファイルの作成
  5. ソフトウェアの起動テスト
  6. ソフトウェアのビルドとパッケージング

初めてやる時にありがちなつまづきポイントは「環境構築」です。
勉強すれば、ある程度のコードを書くくらいなら難しくないんですよね。
だからレンタルサーバーにちょっとしたホームページを作るくらいなら、わりと手軽にできちゃいます。
でも環境構築まで必要な開発になってくると、なかなか厳しい状況もあるでしょう。
このページではそういう部分にも解説を添えつつ、簡単なフローティング・ランチャーを作っていきます。

ではいよいよソースコードを書いていきますが、その前に一言形式的なご挨拶をしておきますね。

このページに関する注意事項

当Webサイト作成者は、例示を目的としてマークアップ及びプログラミング例を提供しており、明示または黙示にかかわらず、いかなる責任も負わないものとします。
このページは、説明されているマークアップ及びプログラミング言語、手順を作成およびデバッグするために使用される各種ツールに読者が精通していることを前提にしています。
このページは、特定の機能を説明するのに役立つ可能性がありますが、当Webサイト作成者がこれらの例を変更した上で、特定の要件を満たすために追加の機能を提供したり、システムを構築したりすることはできません。
加えて、この例の手順に従う場合は、読者の各種ファイルを事前にバックアップすることを推奨いたします。

Node.jsとnpmをインストール

まずはNode.jsをインストールします。

フェードアウト効果の草花写真
  1. Node.jsの公式サイトにアクセスします。
  2. WindowsやMac、Linuxのインストーラがあるので、自分のOSに合ったものを選んでダウンロードします。
  3. ダウンロードしたインストーラを実行し、画面の指示に従ってインストールを完了します。

次はnpmの確認です。

  1. Node.jsをインストールすると、自動的にnpmもインストールされます。
  2. インストールが完了したら、コマンドプロンプトやターミナルを開いて以下のコマンドを入力し、バージョン情報が表示されることを確認します。

node -v
npm -v

これでNode.jsとnpmが正しくインストールされたことを確認できます。

npm (Node Package Manager)

このページでは、Node.jsとElectronを使ってデスクトップアプリを作ろうとしています。
Node.jsとnpmの関係性、そしてそれがなぜパソコンソフトを作れることに繋がるのか、ちょっと説明しましょう。

Node.js
JavaScriptをサーバーサイドで実行するための環境です。
通常、JavaScriptはWebブラウザ上で動作しますが、Node.jsを使うことで、サーバー側でもJavaScriptを動かすことができるようになります。
npm
Node.jsのパッケージマネージャーです。
パッケージとは、Node.jsで利用できる様々な機能を持ったプログラムのことで、npmを使って簡単にインストールしたり、管理したりすることができます。
フェードアウト効果の草花写真

Node.jsとnpmを使うことで、JavaScriptを使って様々な種類のソフトウェアを作ることができます。
Webアプリケーションはもちろんのこと、デスクトップアプリケーションや、サーバー上で動作するプログラムも作成可能です。
ちょっと紛らわしいように思えるけど、なにもパソコンがサーバーになるわけではありません。
Node.jsで作成したプログラムは、様々な場所で実行することができるのです。

Webサーバー
Node.jsで作ったプログラムをWebサーバー上で動かせば、Webアプリケーションとして公開することができます。
デスクトップアプリケーション
Electronというフレームワークを使えば、Node.jsとWeb技術を使ってWindowsやMacで動作するデスクトップアプリケーションを作成できます。

このページでは、上記で言うところのデスクトップアプリケーションを作ろうとしているんですよね。

プロジェクトディレクトリの作成

プロジェクトなんて言うと大袈裟に聞こえますが、実際にこう呼ばれます。
ここでやるのは、要するにソフトを作る場所を用意しましょうという、それだけですよ。
きちんと言うなら、ここでやるのは新しいNode.jsプロジェクトを始めるための初期設定を行う手順です。

引き続き、コマンドプロンプトでの作業です。


mkdir fein_launcher
cd fein_launcher

mkdir fein_launcher
新しいディレクトリ(フォルダ)を作成しています。
このディレクトリは、プロジェクトのファイルを整理するための専用の場所です。
cd fein_launcher
上記で作成したディレクトリに移動するコマンドです。
次の作業をこの新しいディレクトリ内で行うことができます。

npmプロジェクトの初期化


npm init -y

npm init -yは、Node.jsのプロジェクトを初期化するためのコマンドです。
このコマンドを実行すると、新しいプロジェクト用の package.json ファイルが自動的に作成されます。
このファイルはプロジェクトの設定情報や依存関係を管理するために使用されます。

ひとまず、これでプロジェクトを始めるための基盤が整いました。
次は、このプロジェクトに必要なライブラリやフレームワークをインストールして、実際の開発を進めることができます。

npmプロジェクトの初期化

npmプロジェクトの初期化Node.jsプロジェクトを整理し、管理するための重要なステップです。

フェードアウト効果の草花写真
プロジェクトの構成
npm init コマンドを実行すると、プロジェクトの設定情報を含む package.json ファイルが作成されます。
このファイルには、プロジェクトの名前、バージョン、依存関係、スクリプトなどの情報が記載されます。
依存関係の管理
package.json ファイルは、プロジェクトが依存する外部パッケージやライブラリを管理するために使用されます。
他の開発者がプロジェクトをクローンしても、必要なパッケージを簡単にインストールできます。
バージョン管理
package.json ファイルには、使用しているパッケージのバージョン情報が含まれます。
プロジェクトの互換性を保ちながら開発を進めることができます。

初期化(init)という言葉は、これらの設定を最初に行うことを意味しています。
このステップをスキップすると、依存関係やプロジェクトの設定を正しく管理することが難しくなってしまうんです。

Electronのインストール

久しぶりにやったんだけど、やけに時間がかかりましたねー。
実際にチャレンジされる方は、このコマンドを入れてからお風呂に入ると良いかも?


npm install electron --save-dev

このElectronがあることで、HTML、CSS、JavaScriptでデスクトップアプリを作れるのです。
個人サイトをそのまんまアプリにする方法というページでは、普通のホームページをプログレッシブウェブアプリとして構築し、いろんなパソコンやスマホにインストールできるようにしました。
似たような雰囲気で、─ だいぶ違うけど。雰囲気を掴んでもらえれば… ─ 普通のパソコンの普通のソフトウェアだって作れてしまいます。
こうしてみると、HTML、CSS、JavaScriptはとっても汎用性が高いと感じますね。

Node.jsとElectron

Electron は GitHub(Electron GitHub リポジトリ)が開発したオープンソースのフレームワークです。
Electron を使うことで、Web 技術 (HTML, CSS, JavaScript) を使って Windows, macOS, Linux 向けのデスクトップアプリケーションを開発することができます。
Electron 製のアプリケーションとして有名なのは、このあたりでしょうかね。

フェードアウト効果の草花写真

ElectronはWeb開発の知識があればデスクトップアプリケーション開発を始められるという点で、多くの開発者に利用されています。
私も学生時代にサイト制作とエレクトロンを行き来したもんですわ。

Microsoft Edge

現在のWindowsでプリインストールされているのはMicrosoft Edgeなので、このブラウザについても多少は理解を深める必要があります。
Microsoft Edgeは、Chromiumベースのバージョン(Chromium Edge)と、独自のEdgeHTMLエンジンを使ったバージョンがあります。最新のEdgeはChromiumベースであり、基本的にはChromiumと同じ技術を使用しています。
Electron自体は、特定のChromiumバージョンを使って最適化されているため、Node.jsとEdge(特にChromiumベースのEdge)を使うというよりは、Electronが内部で適切にChromiumを扱う形で使用するのです。

リソースとなるファイルの作成

fein_launcherというフォルダの下に、次のようにファイルとフォルダを作ります。

launcherfile

それぞれのファイルに、次のような役割を持たせていきます。

index.html
アプリのユーザーインターフェースを定義するためのHTMLファイル。
ウェブページ、つまりソフトウェアの構造を表します。
要するにフロントエンドですよね。
renderer.js
index.htmlと連携して動作するJavaScriptコードを記述するファイル。
ユーザーの操作や表示を制御します。
style.css
アプリの見た目(デザインやスタイル)を設定するためのCSSファイル。
レイアウトや色などを定義します。
main.js
エレクトロンアプリ全体の動作を制御するメインプロセスのコードを記述するファイル。
ウィンドウの生成やアプリのライフサイクルを管理します。
package.json
プロジェクトの設定情報や依存関係を管理するファイル。
アプリの名前やバージョン、使用するライブラリなどを記述します。
preload.js
レンダラープロセスとメインプロセス間で安全に通信するためのスクリプトを記述するファイル。
必要なAPIをレンダラープロセスに公開します。

ちなみに、ここで紹介しているフローティング・ランチャーくらいであればpreload.jsの記述までは必要ありません。
ローカルで使用する単純なランチャーアプリですからね。
ただし、後々、アプリに追加機能を追加したくなった場合や、他のプロジェクトに拡張したい場合には、preload.js を使ってセキュリティや機能性を向上させることができますよ?
では、実際のコードを書いていきます。

index.html

このサイトではhtmlの意味までは掲載していません。
次のコードをご覧いただければ分かるように、さほど難しいコードではないです。
少し余計な記述もあるんだけど、これは私が後日ランチャーを拡張したくなったときのために書いてあるだけです。

ユーザーインターフェースを定義するindex.html


<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Start Menu</title>
  <link rel="stylesheet" href="style.css">
  <meta http-equiv="Content-Security-Policy"
    content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self'">
</head>
<body>
  <div id="start-menu">
    <button id="start-button">fein menu</button>
    <div id="menu-content" class="hidden">
      <ul>
        <li>Visual Atelier Code
          <ul>
            <li><a href="#" onclick="openVSCode()">VS code</a></li>
            <li><a href="#" onclick="openFeinsApp()">fein's app</a></li>
            <li><a href="#" onclick="openFeinsPortal()">fein's portal</a></li>
          </ul>
        </li>
        <li><a href="#" onclick="openEdge()">Microsoft Edge</a></li>
        <li>Another Eden
          <ul>
            <li><a href="#"
                onclick="openFile('C:\\Users\\ユーザー名\\OneDrive\\_fein\\google cloud\\web tools\\visual_studio_code\\anothereden.txt')">anothereden.txt</a>
            </li>
            <li><a href="#"
                onclick="openFile('C:\\Users\\ユーザー名\\OneDrive\\_fein\\google cloud\\web tools\\visual_studio_code\\document.txt')">document.txt</a>
            </li>
            <li><a href="#"
                onclick="openFile('C:\\Users\\ユーザー名\\OneDrive\\_fein\\google cloud\\web tools\\visual_studio_code\\sourcecode.txt')">sourcecode.txt</a>
            </li>
          </ul>
        </li>
      </ul>
    </div>
  </div>
  <script src="renderer.js"></script>
</body>
</html>

ただ、onclick="openFeinsApp()"とか、JavaScriptと繋がっている部分についてはけっこう大切な部分なので、見ておいていただけると。

renderer.js

上述していますが、ここでご紹介しているソフトウェアの基礎構造は、ファイルの整理とプロジェクトの構造を明確に保つためによく行われる方法です。

フェードアウト効果の草花写真

renderer.js、index.html、style.css などのファイルはアプリのUI(レンダラー)に関連するものであり、これらを src フォルダにまとめることで、プロジェクトの構造が整理され、理解しやすくなります。

main.js はElectronアプリのメインプロセスを担当するファイルです。アプリ起動時に最初に実行されるため、ルートディレクトリに置かれます。
package.json はプロジェクトの設定ファイルであり、依存関係やスクリプト、メタデータを含んでいます。
npmや他のツールによる管理が容易になるため、ルートディレクトリに配置されます。
preload.js はレンダラープロセスとメインプロセスの間でデータをやり取りするためのスクリプトです。
セキュリティの理由からも、ルートディレクトリに置かれることが多いです。

ユーザーの操作や表示を制御するrenderer.js


const { exec } = require('child_process');

function openVSCode() {
 exec('"C:\\Users\\ユーザー名\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe"', (error, stdout, stderr) => {
  if (error) {
   console.error(`Error opening VS Code: ${error.message}`);
   return;
  }
  console.log(`VS Code output: ${stdout}`);
 });
}

function openEdge() {
 exec('"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"', (error, stdout, stderr) => {
  if (error) {
   console.error(`Error opening Microsoft Edge: ${error.message}`);
   return;
  }
  console.log(`Microsoft Edge output: ${stdout}`);
 });
}

function openFile(filePath) {
 const command = `start "" "${filePath}"`;
 exec(command, (error, stdout, stderr) => {
  if (error) {
   console.error(`Error opening file ${filePath}: ${error.message}`);
   return;
  }
  console.log(`File output: ${stdout}`);
 });
}

function openFeinsApp() {
 window.open('https://feinatelier.org/', '_blank');
}

function openFeinsPortal() {
 const command = '"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe" https://portal.feinatelier.org/';
 exec(command, (error, stdout, stderr) => {
  if (error) {
   console.error(`Error opening Fein's Portal: ${error.message}`);
   return;
  }
  console.log(`Fein's Portal output: ${stdout}`);
 });
}

console.log('Script loaded');

const startButton = document.getElementById('start-button');
const menuContent = document.getElementById('menu-content');
console.log(startButton);

startButton.style.position = 'fixed';
startButton.style.right = '10px';
startButton.style.top = '10px';

startButton.addEventListener('click', () => {
 console.log('Start button clicked');
 if (menuContent.classList.contains('hidden')) {
  menuContent.classList.remove('hidden');
  menuContent.style.display = 'block';
 } else {
  menuContent.classList.add('hidden');
  menuContent.style.display = 'none';
 }
});

document.querySelectorAll('#menu-content > ul > li').forEach((item) => {
 const subMenu = item.querySelector('ul');
 if (subMenu) {
  item.addEventListener('click', (event) => {
   event.stopPropagation();
   if (subMenu.style.display === 'none' || !subMenu.style.display) {
    subMenu.style.display = 'block';
   } else {
    subMenu.style.display = 'none';
   }
  });
 }
});

このコードは、いくつかのアプリケーションを開いたり、ボタンの動作を制御するためのJavaScriptです。

1. モジュールのインポート


const { exec } = require('child_process');

ここでは、child_processモジュールのexec関数をインポートしています。

child_processモジュールは、Node.jsの標準モジュールの一つで、外部プログラムを実行するためのものです。
このモジュールを使うことで、Node.jsからシェルコマンドや他のスクリプト、実行可能ファイルを呼び出すことができます。

その中でも、exec関数は指定されたコマンドを実行し、その結果をコールバック関数に渡すために使われます。
例えば、他のプログラムやスクリプトを実行したり、OSのコマンドを実行する際に利用されます。

ここでは、次のような役割を持っています。

ランチャーらしいでしょ?
child_processモジュールを使うことで、Node.jsアプリケーションからさまざまなシステム操作を簡単に行うことができるのです。

2. VS Codeを開く関数

この関数はVisual Studio Codeを開きます。
エラーが発生した場合はエラーメッセージを表示します。

Ⅰ. 関数の定義


function openVSCode() {

openVSCodeという名前の関数を定義しています。
この関数はVisual Studio Codeを開くために使います。

Ⅱ. exec関数の呼び出し


exec('"C:\\Users\\ユーザー名\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe"', (error, stdout, stderr) => {

exec関数を使って、指定されたパスにあるVisual Studio Codeの実行ファイル(Code.exe)を起動します。
exec関数は、Node.jsのchild_processモジュールからインポートされています。

Ⅲ. コールバック関数

exec関数の第2引数としてコールバック関数を渡しています。
このコールバック関数は、コマンドの実行が終了したときに呼び出されます。コールバック関数は3つの引数を受け取ります。

error
エラーが発生した場合、その情報が渡されます。
stdout
コマンドの標準出力が渡されます。
stderr
コマンドの標準エラー出力が渡されます。

Ⅳ. エラーチェック


if (error) {
  console.error(`Error opening VS Code: ${error.message}`);
  return;
}

エラーが発生した場合、そのエラーメッセージをコンソールに出力し、関数の実行を終了します(return)。

Ⅴ. 標準出力のログ出力


console.log(`VS Code output: ${stdout}`);

エラーが発生しなかった場合、Visual Studio Codeの実行結果(標準出力)をコンソールに出力します。
この関数を実行すると、指定されたパスにあるVisual Studio Codeが起動されます。
エラーが発生した場合はエラーメッセージが表示され、エラーが発生しなかった場合はVS Codeの標準出力がコンソールに表示されます。

3. Edgeを開く関数


function openEdge() {
  exec('"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"', (error, stdout, stderr) => {
    if (error) {
      console.error(`Error opening Microsoft Edge: ${error.message}`);
      return;
    }
    console.log(`Microsoft Edge output: ${stdout}`);
  });
}

この関数はMicrosoft Edgeを開きます。
動作は上記のVS Codeの関数と同様です。

4. ファイルを開く関数


function openFile(filePath) {
  const command = `start "" "${filePath}"`;
  exec(command, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error opening file ${filePath}: ${error.message}`);
      return;
    }
    console.log(`File output: ${stdout}`);
  });
}

この関数は指定されたファイルを開きます。
filePathには開きたいファイルのパスを入力します。

5. fein's appを新しいタブで開く関数


function openFeinsApp() {
  window.open('https://feinatelier.org/', '_blank');
}

この関数は、指定されたURLを新しいタブで開きます。

6. fein's PortalをEdgeで開く関数


function openFeinsPortal() {
  const command = '"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe" https://portal.feinatelier.org/';
  exec(command, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error opening Fein's Portal: ${error.message}`);
      return;
    }
    console.log(`Fein's Portal output: ${stdout}`);
  });
}

この関数はfein's PortalをMicrosoft Edgeで開きます。

7. ボタンとメニューの動作

ここがちょっと長いですね。
主にいくつかのアプリケーションを開いたり、Webサイトを表示したりするための関数と、ボタンをクリックしたときの動作を設定するものです。
概要としては、次の通りです。

Ⅰ. HTML要素の取得


const startButton = document.getElementById('start-button');
const menuContent = document.getElementById('menu-content');

ここでは、HTMLドキュメントからstart-buttonmenu-contentというIDを持つ要素を取得しています。

Ⅱ. ボタンの位置の設定


startButton.style.position = 'fixed';
startButton.style.right = '10px';
startButton.style.top = '10px';

取得したボタン(startButton)の位置を画面の右上に固定しています。

Ⅲ. ボタンのクリックイベントの設定


startButton.addEventListener('click', () => {
  if (menuContent.classList.contains('hidden')) {
    menuContent.classList.remove('hidden');
    menuContent.style.display = 'block';
  } else {
    menuContent.classList.add('hidden');
    menuContent.style.display = 'none';
  }
});

ボタンがクリックされたときの処理を設定しています。

Ⅳ. サブメニューのクリックイベントの設定


document.querySelectorAll('#menu-content > ul > li').forEach((item) => {
  const subMenu = item.querySelector('ul');
  if (subMenu) {
    item.addEventListener('click', (event) => {
      event.stopPropagation();
      if (subMenu.style.display === 'none' || !subMenu.style.display) {
        subMenu.style.display = 'block';
      } else {
        subMenu.style.display = 'none';
      }
    });
  }
});

このようにして、ボタンのクリックに応じてメニューの表示/非表示を制御し、さらにリスト項目をクリックするとそのサブメニューの表示/非表示も切り替えることができるようになります。

こんな感じかなー
あんまり長々と説明しててもね。
このフローティング・ランチャーもバージョンアップを重ねていくでしょうから、その折にまた再度書きましょうか。

style.css

あるいはこのWebサイトのように、軽いアニメーションでも付けようかと思っています。
でもWindows11のスタートボタンもアニメーションはほとんど付いていないし、悩ましいところです。

ランチャーソフトの見た目を設定するstyle.css


/* 全体の幅と高さを100%に設定し、余白とオーバーフローをリセット */
body,
html {
 width: 100%; /* 要素の幅を100%に設定 */
 height: 100%; /* 要素の高さを100%に設定 */
 margin: 0; /* 余白を0に設定 */
 overflow: hidden; /* 要素のコンテンツがはみ出さないようにする */
 background: transparent; /* 背景を透明に設定 */
 font-size: 12px; /* フォントサイズを12pxに設定 */
 font-family: 'Lucida Handwriting', cursive; /* フォントファミリーを設定 */
 color: #0078D4; /* 文字色を設定 */
}

/* body要素のスタイル設定 */
body {
 border-radius: 15px; /* 角を15pxの半径で丸くする */
 overflow: hidden; /* コンテンツがはみ出さないようにする */
 border: 1px solid rgba(0, 120, 215, 0.5); /* 半透明の1pxの境界線を設定 */
 box-sizing: border-box; /* ボーダーとパディングを含めたボックスサイズを設定 */
}

/* #start-button要素のスタイル設定 */
#start-button {
 width: 120px; /* ボタンの幅を120pxに設定 */
 height: 30px; /* ボタンの高さを30pxに設定 */
 background-color: rgba(144, 238, 144, 0.4); /* 半透明の背景色を設定 */
 border-radius: 30px / 15px; /* 楕円形の角を設定 */
 border: none; /* 境界線をなしに設定 */
 color: white; /* 文字色を白に設定 */
 font-size: 12px; /* フォントサイズを12pxに設定 */
 font-family: 'Lucida Handwriting', cursive; /* フォントファミリーを設定 */
 cursor: pointer; /* マウスオーバー時のカーソルを指ポインターに設定 */
 display: flex; /* フレックスボックスで配置 */
 align-items: center; /* 垂直方向に中央揃え */
 justify-content: center; /* 水平方向に中央揃え */
 box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); /* 半透明の影を設定 */
 position: fixed; /* スクロールしても固定位置 */
 right: 10px; /* 右から10pxの位置に設定 */
 top: 10px; /* 上から10pxの位置に設定 */
}

/* #start-buttonのホバー時のスタイル設定 */
#start-button:hover {
 background-color: rgba(102, 205, 170, 0.4); /* ホバー時の背景色を設定 */
}

/* #menu-content要素のスタイル設定 */
#menu-content {
 width: calc(100% - 40px); /* 幅を計算して設定 */
 background-color: rgba(173, 216, 230, 0.2); /* 半透明の背景色を設定 */
 box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1); /* 半透明の影を設定 */
 padding: 10px; /* 内側の余白を10pxに設定 */
 position: absolute; /* 絶対位置に設定 */
 top: 60px; /* 上から60pxの位置に設定 */
 right: 10px; /* 右から10pxの位置に設定 */
 display: none; /* 非表示に設定 */
 border-radius: 15px; /* 角を15pxの半径で丸くする */
 border: none; /* 境界線をなしに設定 */
 font-family: 'Lucida Handwriting', cursive; /* フォントファミリーを設定 */
}

/* 非表示要素の設定 */
.hidden {
 display: none; /* 非表示に設定 */
}

/* #menu-content内のul要素のスタイル設定 */
#menu-content ul {
 list-style: none; /* リストスタイルをなしに設定 */
 padding: 0; /* 内側の余白を0に設定 */
 margin: 0; /* 外側の余白を0に設定 */
 font-family: 'Lucida Handwriting', cursive; /* フォントファミリーを設定 */
}

/* #menu-content内のli要素のスタイル設定 */
#menu-content li {
 padding: 5px; /* 内側の余白を5pxに設定 */
 cursor: pointer; /* マウスオーバー時のカーソルを指ポインターに設定 */
}

/* 入れ子になったul要素のスタイル設定 */
#menu-content ul ul {
 padding-left: 20px; /* 左側の余白を20pxに設定 */
 display: none; /* 非表示に設定 */
}

/* a要素のスタイル設定 */
a {
 color: #4285F4; /* リンクの文字色を設定 */
 text-decoration: none; /* 下線をなしに設定 */
 font-family: 'Lucida Handwriting', cursive; /* フォントファミリーを設定 */
}

/* a要素のホバー時のスタイル設定 */
a:hover {
 color: #0078D4; /* ホバー時の文字色を設定 */
 text-decoration: underline; /* 下線を表示 */
 font-family: 'Lucida Handwriting', cursive; /* フォントファミリーを設定 */
}

特別なことはやっていないです。
フォントはちょっと気分で筆記体のものを入れてみたんだけど、あるいはまた変えようかしら?
まだバージョン1ですから、これからいろいろ追記できる余地も欲しかったんですよね。

main.js

このコードはElectronを使用してシンプルなデスクトップアプリケーションを作成し、そのウィンドウの動作を制御します。

エレクトロンアプリ全体の動作を制御するmain.js


const { app, BrowserWindow } = require('electron');
const path = require('path');

function createWindow() {
 const { screen } = require('electron');
 const display = screen.getPrimaryDisplay();
 const { width, height } = display.workAreaSize;

 let win = new BrowserWindow({
  width: width * 0.2,
  height: height * 0.5,
  x: width - width * 0.2,
  y: 0,
  frame: false,
  transparent: true,
  hasShadow: false,
  alwaysOnTop: false,
  webPreferences: {
   preload: path.join(__dirname, 'preload.js'),
   nodeIntegration: true,
   contextIsolation: false,
  }
 });

 win.loadFile('src/index.html');

 win.setBackgroundColor('#00000000');
 win.on('closed', () => {
  win = null;
  app.quit();
 });
}

app.on('window-all-closed', () => {
 app.quit();
});

app.whenReady().then(() => {
 createWindow();

 app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
   createWindow();
  }
 });
});

Ⅰ. モジュールのインポート


const { app, BrowserWindow } = require('electron');
const path = require('path');

pathモジュールはファイルやディレクトリのパスを操作するためのものです。

Ⅱ. ウィンドウを作成する関数の定義


function createWindow() {
    const { screen } = require('electron');
    const display = screen.getPrimaryDisplay();
    const { width, height } = display.workAreaSize;

    let win = new BrowserWindow({
        width: width * 0.2,
        height: height * 0.5,
        x: width - width * 0.2,
        y: 0,
        frame: false,
        transparent: true,
        hasShadow: false,
        alwaysOnTop: false,
        webPreferences: {
            preload: path.join(__dirname, 'preload.js'),
            nodeIntegration: true,
            contextIsolation: false,
        }
    });

    win.loadFile('src/index.html');

    win.setBackgroundColor('#00000000');
    win.on('closed', () => {
        win = null;
        app.quit();
    });
}

Ⅲ. 全てのウィンドウが閉じられたときの処理


app.on('window-all-closed', () => {
    app.quit();
});

全てのウィンドウが閉じられたら、アプリケーションを終了します。

Ⅳ. アプリケーションの準備ができたときの処理


app.whenReady().then(() => {
    createWindow();

    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) {
            createWindow();
        }
    });
});

メインプロセス main.js・レンダラープロセス renderer.js

フェードアウト効果の草花写真

main.js はElectronアプリケーションのメインプロセス (main process) を制御するファイルです。
Electronアプリでは、アプリケーションの全体的なライフサイクル管理やウィンドウの作成などの重要な部分がメインプロセスで行われます。
一方、renderer.js はレンダラープロセス (renderer process) のスクリプトであり、各ウィンドウ(またはウェブページ)の動作を制御します。
レンダラープロセスは基本的にブラウザ環境で動作し、ユーザーインターフェイスやDOM操作などを担当します。

ここで、それぞれの役割と違いについて詳しく説明しておきますね。
コード本体より、この考え方のほうが重要と思うから。

1. メインプロセス(main.js)
アプリケーションの起動、ウィンドウの作成、アプリケーション全体のイベント処理などを担当します。
Node.js のフル機能を利用でき、ファイルシステムアクセスやネイティブモジュールの使用が可能です。
複数のレンダラープロセスを管理します。
2. レンダラープロセス(renderer.js)
各ウィンドウ内で動作し、ユーザーインターフェイスのロジックや操作を担当します。
一般的にはブラウザ環境と似ており、HTML、CSS、JavaScriptを使用してDOM操作やユーザーインタラクションを実現します。
メインプロセスと通信するためには、ElectronのIPC(Inter-Process Communication)を使用します。

main.jsが必要な理由があるんですよね。
これは普通の、巷で言うところの「ホームページ」にあるJavaScriptと違う側面でしょう。
この役割分担により、Electronアプリは効率的かつ安全に動作します。
renderer.jsだけではアプリケーションの全体的な管理ができないため、main.jsが必要になります。

ウィンドウ管理
新しいウィンドウの作成や既存ウィンドウの管理はメインプロセスで行われます。renderer.jsだけではこれができません。
アプリケーションライフサイクルの管理
アプリケーションの起動、終了、再起動などの全体的な管理を担当します。
セキュリティ
ノード統合が有効になっている場合、メインプロセスがより信頼できる操作を行い、レンダラープロセスの潜在的なリスクを低減します。
フェードアウト効果の草花写真

ノード統合(Node Integration)とは、ElectronアプリケーションのレンダラープロセスでNode.jsの機能を使用できるようにする設定です。
通常、ブラウザ環境ではNode.jsの機能を直接使用することはできませんが、Electronではノード統合を有効にすることで、HTMLやJavaScriptを使っているレンダラープロセス内でもNode.jsのAPIやモジュールを利用できるようになります。

ノード統合を有効にすることで、次のようなことが可能になるのです。

ファイルシステムへのアクセス:
Node.jsのfsモジュールを使用して、ファイルの読み書きやファイル操作が可能です。
ネイティブモジュールの使用:
Node.jsのネイティブモジュールを利用して、システムレベルの操作や外部パッケージの利用ができます。
サーバーとの通信:
httphttpsモジュールを使用して、外部サーバーとの通信を行うことができます。

しかし、ノード統合を有効にすることにはリスクも伴います。
特に、レンダラープロセス内のWebコンテンツが外部の悪意あるスクリプトによって操作されると、Node.jsのAPIが悪用される可能性があります。
そのため、セキュリティ対策としては、信頼できるコンテンツのみを読み込む、またはコンテキスト分離(Context Isolation)を有効にするなどの方法があります。

上述のmain.jsではノード統合が有効になっています。
次のコードをご覧ください。


webPreferences: {
 preload: path.join(__dirname, 'preload.js'),
 nodeIntegration: true, // ここでノード統合を有効にしている
 contextIsolation: false,
}

webPreferencesオブジェクト内のnodeIntegration: trueという設定がノード統合を有効にしています。
これはレンダラープロセス内でNode.jsの機能を使用することができる状態です。
同時に、contextIsolation: falseが設定されているため、レンダラープロセス内でのコンテキストの分離も無効になっています。
これはセキュリティの観点から注意が必要な設定です。

ここまで見てきたように、ノード統合はElectronアプリケーションの柔軟性を高めるための機能ですが、使用する際にはセキュリティに十分注意する必要があります。
renderer.jsを見ると、特定のアプリケーションやファイルを開くためにNode.jsのchild_processモジュールを使用していることが分かります。
セキュリティを強化する設定に変更すると動作に影響を与える可能性が高いです。
ノード統合を無効にすると、レンダラープロセス内でNode.jsの機能(requireやexecなど)にアクセスできなくなります。
このため、現状のスクリプトでは以下の部分が動作しなくなるでしょう。
コンテキスト分離を有効にすると、メインプロセスとレンダラープロセスが異なるJavaScriptコンテキストで動作するため、セキュリティが強化されますが、同様にNode.jsの機能に直接アクセスできなくなります。
ノード統合を無効にしたり、コンテキスト分離を有効にする場合、次のようにプリロードスクリプトを使用して、メインプロセスとレンダラープロセス間で安全にデータをやり取りする方法があります。

プリロードスクリプト preload.js

上述したように、preload.jsはレンダラープロセスとメインプロセス間で安全に通信するためのスクリプトを記述するファイルであり、必要なAPIをレンダラープロセスに公開します。
このプリロードスクリプト(preload.js)で、contextBridgeipcRendererを使用して、メインプロセスの機能をレンダラープロセスから利用できるようにします。
そうすればセキュリティを利かせつつ、このページで掲載している renderer.js も動作します。


const { contextBridge, ipcRenderer } = require('electron');
const { exec } = require('child_process');

contextBridge.exposeInMainWorld('api', {
 openVSCode: () => ipcRenderer.invoke('open-vscode'),
 openEdge: () => ipcRenderer.invoke('open-edge'),
 openFile: (filePath) => ipcRenderer.invoke('open-file', filePath),
 openFeinsPortal: () => ipcRenderer.invoke('open-feins-portal')
});

フェードアウト効果の草花写真

上記のpreload.jsを書いてから、メインプロセスの main.js でIPC通信を設定しますよね。
次に、レンダラープロセスの renderer.js を用いてプリロードスクリプトで公開されたAPIを使用します。
こうやってやれば、セキュリティを強化しつつ、現在のスクリプトの機能を維持することができます。

まぁでも…すでにお話しましたが、ここで作っているのはローカルで稼働するシンプルなフローティング・ランチャーです。
デザイン面や機能などをさらに拡張したくなった時に改めて考えれば良いわけで。
現段階ではここまでやらずとも良いと判断しているってことですね。

package.json

ここまで、あまりにも長くなり過ぎました。
このpackage.jsonも重要なコードであり、ちゃんと書かないとソフトウェアとしてまともに機能しません。

プロジェクトの設定情報を管理するpackage.json


{
 "name": "fein_launcher",
 "version": "1.0.0",
 "main": "main.js",
 "scripts": {
  "start": "electron .",
  "package-win": "electron-packager . fein_launcher --platform=win32 --arch=x64 --out=dist --overwrite",
  "package-linux": "electron-packager . fein_launcher --platform=linux --arch=x64 --out=dist --overwrite",
  "package-mac": "electron-packager . fein_launcher --platform=darwin --arch=x64 --out=dist --overwrite"
 },
 "devDependencies": {
  "electron": "^xx.x.x",
  "electron-packager": "^xx.x.x"
 }
}

package.jsonは、Node.jsプロジェクトの「設定ファイル」として機能し、プロジェクトの基本情報、依存パッケージ、実行可能なスクリプトなどを管理します。
また、プロジェクトのセットアップやビルド、実行が簡単になります。
このフローティング・ランチャーで使われているコードの説明を致しましょう。

フェードアウト効果の草花写真
プロジェクト情報
name: プロジェクト名です。この場合、プロジェクトの名前は fein_launcher です。
version: プロジェクトのバージョンです。バージョン番号は 1.0.0 です。
main: プロジェクトのエントリーポイントとなるファイルを指定します。この場合は main.js です。
スクリプト
scripts: コマンドラインで実行できるスクリプトを定義します。この部分では以下のスクリプトが定義されています:
start: electron . を実行すると、Electronアプリケーションが起動します。
package-win: electron-packager . fein_launcher --platform=win32 --arch=x64 --out=dist --overwrite を実行すると、Windows用のパッケージが作成されます。
package-linux: electron-packager . fein_launcher --platform=linux --arch=x64 --out=dist --overwrite を実行すると、Linux用のパッケージが作成されます。
package-mac: electron-packager . fein_launcher --platform=darwin --arch=x64 --out=dist --overwrite を実行すると、Mac用のパッケージが作成されます。
開発依存関係
devDependencies: 開発中に必要な依存関係を定義します。この部分では次のような依存関係が定義されています。
electron: ^xx.x.x Electronのバージョンを指定します。xx.x.xの部分には実際のバージョン番号が入ります。
electron-packager: ^xx.x.x Electronアプリケーションをパッケージ化するためのツールである electron-packager のバージョンを指定します。

electronとelectron-packagerのバージョン記述はサボっちゃいました😆ww
いや…だって、この手の設定ファイルって凝り出すとキリないんだもん…
バージョンアップしていくにつれて、少しずつ完璧な形へ近付けていきましょう。

package-lock.json

これも戸惑いを感じるファイルじゃないかな?
プロジェクトのルートディレクトリに作られるもので、何かがおかしいわけじゃないです。
ルートディレクトリに生成されるpackage-lock.jsonは、Node.jsのプロジェクトにおける依存関係を厳密に管理するためのファイルです。
このファイルには、次のようにプロジェクトで使用される正確なパッケージバージョンと依存関係のツリーが記録されています。

依存関係の固定
package-lock.jsonに記録されているバージョン番号により、プロジェクトの依存関係が一貫して再現されるため、異なる環境で同じ動作を保証します。
パフォーマンス向上
npmはpackage-lock.jsonを利用してパッケージのインストールを効率化し、インストール時間を短縮します。
セキュリティ
依存関係のツリーが明示されているため、潜在的な脆弱性のあるパッケージを特定しやすくなります。

package.jsonpackage-lock.jsonは、Node.jsプロジェクトの依存関係管理において大切な役割を持っているんですよね。
加えて、package-lock.jsonは手動で作成するのではなく、次のような状況で自動的に生成されます。

最初の依存関係のインストール時
npm install を実行したときに、package-lock.json がまだ存在しない場合、自動的に生成されます。
依存関係の追加または更新時
npm install <パッケージ名>npm update を実行すると、依存関係が変更され、それに応じて package-lock.json も更新されます。
プロジェクトの初期化時
プロジェクトを初期化する際に依存関係が指定された場合(例:npm init 時に依存関係を追加)、package-lock.json が生成されます。

package-lock.json は、プロジェクト内の依存関係を厳密に管理し、他の開発者が同じ依存関係でプロジェクトを再現できるようにするための重要なファイルです。
なので、自分で手動で作成する必要はなく、npmが自動的に管理してくれます。

ソフトウェアの起動テスト

次のコマンドでElectronアプリが起動します。
開発を進めるには、上記のファイルにソースコードを記載しつつ、機能を追加していきます。


npm start

ソフトウェアを終了するには、コマンドプロンプト内部でctrl+cを押してからyesで終了できます。

ここで、ほっとんどの場合バグが出ます。
想定通りにソフトウェアが動いてくれないので、デバッグする必要がある。
デバッグとは、プログラミングにおいて、プログラムの欠陥や誤り(バグ)を見つけ出し、取り除く作業のことです。
いろんなやり方があるのですが、ここでは基本的なものを紹介します。
次の画像をご覧ください。

feinlauncher

まず、自分が作っているソフト上で Shift+Ctrl+I を押します。
大きいソフトだったらいいけど、そうでない場合は上の画像のように大変操作しにくい開発者ツールが開いてしまうのです。
そしたらソフトのサイズそのものを広げても良いし、右上にある縦に並んだ・を押していただきます。

feinlauncher

またいろんな選択肢が出てきますが、ここでは「Undock into separate window」を押してみましょう。

feinlauncher

これで、広々とした画面で開発者ツールを閲覧できるようになりました。

こうしたデバッグのツールはいろんな種類があり、非常に多機能です。
とてもとても、全ての機能を網羅するのは難しいでしょう。
でもとりあえず、ここのConsoleタブだけは見ておくと良いですよ?
プログラムにバグがあれば、ここにエラーメッセージが出ます。
そのメッセージについて調べながら、ソースコードを修正していくわけです。

node_modules

node.jsのエレクトロンでソフトウェアを作っていると、下の画像のように「node_modules」というフォルダができていることに気付くでしょう。
バグではありませんよ?
「node_modules」フォルダは、node.jsのプロジェクトにおいて、外部のライブラリやパッケージをインストールした際に生成されるフォルダです。

feinlauncher

node.jsのプロジェクトでは、様々な外部のライブラリやパッケージを利用することができます。
これらのライブラリやパッケージは、上述したnpm(Node Package Manager)などのパッケージマネージャーを使ってインストールします。
npmを使ってライブラリやパッケージをインストールすると、それらのファイルは「node_modules」フォルダ内に保存されます。
つまり、「node_modules」フォルダは、プロジェクトが依存する外部のライブラリやパッケージをまとめて管理する場所なのです。

「node_modules」フォルダは、サイズが大きくなりやすいという特徴があります。
このページでやってるランチャーソフトくらいならいいけど、多くのライブラリやパッケージをインストールしているプロジェクトでは、「node_modules」フォルダが数GBになることもあります。
そのため、Gitなどで「node_modules」フォルダを管理することは推奨されていません。
代わりに、package.jsonファイルを使って、プロジェクトの依存関係を管理します。

ソフトウェアのビルドとパッケージング

「ビルド」は、ソースコードから実行可能な形式に変換する全体的なプロセスを指し、「パッケージング」はそのビルドされたファイルをインストーラなどの形で配布可能な形式にまとめるプロセスを指すことが一般的です。

ソフトを作ったら、それを手軽に実行できるようにしなければ意味がありません。これがビルドです。
そして、ビルドされたものを一般ユーザーが使えるようにすると良いですね。これがパッケージングです。
では、実際のやり方を見ていきましょう。

electron-packager のインストール

package.jsonのコード紹介にて、ビルドコマンドを記述していましたね?
しかし、package.jsonにビルドコマンドを記述しても、electron-packager自体がインストールされていなければ実行できません。
まずは、electron-packagerをプロジェクトにインストールしましょう。
ターミナルで、プロジェクトのルートディレクトリに移動し、次のコマンドを実行します。


npm install electron-packager --save-dev

これでelectron-packagerがプロジェクトの devDependencies としてインストールされます。

ビルドコマンドの実行でソフトウェアが完成する

electron-packagerのインストールが完了したら、いよいよビルドコマンドを実行します。
package.jsonに記述したコマンドは npm scripts として登録されているので、次のように簡単に実行できます。


npm run <script名>

例えば、Windows版をビルドする場合は、次のコマンドです。


npm run package-win

このコマンドを実行すると、ソフトウェアを作っているフォルダに「dist」というフォルダが生成されるはずです。

feinlauncher

このフォルダの中に、exeファイルが入っているんだよね。
このランチャーソフトの場合は、次の画像のようになります。

feinlauncher

distフォルダの下にfein_launcher-win32-x64フォルダがあります。
その中に「fein_launcher.exe」があるんだよね。
これで、ソフトウェアの完成となります!

feinlauncher

さらにresurcesというフォルダを見てみましょう。
中にはappフォルダがあり、その中に私が作ったJavaScriptなどが収まっている。

feinlauncher

加えて、srcフォルダの中を見れば、ちゃんとhtmlやcssも入っている。
これが、私が作ったフローティング・ランチャーの仕組みです。

同様に、Linux版、Mac版をビルドする場合は、それぞれ次のコマンドを実行します。


npm run package-linux
npm run package-mac

ちなみにpackage.jsonへ次のように記述しておくと、npm run buildコマンドを実行するだけで、全てのプラットフォーム向けの実行ファイルを一度に生成することができます。
私はやらないんだけどねー。


"build": "npm run package-win && npm run package-linux && npm run package-mac"

さて、こうしてビルドが完了すると、package.jsonで指定した出力先--out=distに、プラットフォームごとの実行ファイルが生成されます。

distディレクトリの中身を確認し、目的の実行ファイルが存在することを確認しましょう。

electron-packager

electron-packagerは、Electronフレームワークを使って開発したアプリケーションを、Windows、macOS、Linuxといった各プラットフォームで配布可能な実行ファイルにパッケージングするためのツールです。
Electronアプリを開発したら、それをエンドユーザーに配布する必要があります。
しかし、ElectronアプリはWeb技術(HTML, CSS, JavaScript)をベースにしているため、そのままでは各OSで実行することができません。
そこで、electron-packagerのようなツールを使って、Electronアプリを各OSに対応した実行ファイルに変換(パッケージング)する必要があるのです。

electron-packagerは、次のようなことをしてくれるのです。

クロスプラットフォーム対応
Windows、macOS、Linuxといった主要なデスクトップOS向けの実行ファイルを生成できます。
実行ファイルの生成
アプリケーションのコードやリソースをまとめて、各OSで実行可能な形式の実行ファイル(.exe, .app, etc.)を生成します。
パッケージング
アプリケーションに必要なファイルや依存関係をまとめて、配布可能なパッケージ(インストーラーなど)を作成します。

electron-packagerは、コマンドラインツールとして提供されています。
通常は、Node.jsのnpmパッケージとしてインストールし、package.jsonにビルドコマンドを定義して使用します。
上述したビルドとパッケージングの作業が、まさにそれです。
基本的な使い方をおさらいしておきましょう。

npm install electron-packager --save-devでインストールするのは同じです。
ビルドコマンドの意味を押さえておくと良いかもね?

例えば、Windows向け実行ファイルの生成は次のようにコマンドします。


electron-packager . myapp --platform=win32 --arch=x64 --out=dist

このコマンドを実行すると、現在のディレクトリ(.)にあるmyappというアプリを、Windows 64bit向けにパッケージングし、distディレクトリに出力します。

electron-packagerは、Electronアプリを各プラットフォーム向けに配布するために必要不可欠なツールですよね。
これを使うことで、開発したアプリをより多くの人に利用してもらうことができるってこと。

dependenciesとdevDependencies

一応、devDependencies という言葉についても書いておこうかな。

Node.jsプロジェクトにおいて、外部のライブラリやツールを利用する場合、それらをプロジェクトにインストールする必要があります。
これらの外部ライブラリやツールは、プロジェクトの「依存関係」と呼ばれることが多いです。
この依存関係には、大きく分けてdependencies(依存)とdevDependencies(開発依存)の2種類があります。

dependencies
アプリケーションの実行時に必要な依存関係
devDependencies
アプリケーションの開発時にのみ必要な依存関係

electron-packagerはdevDependenciesなんですよ?
electron-packagerは、Electronアプリをパッケージングするためのツールであり、アプリケーションの実行時には必要ありません。
electron-packagerは、あくまで開発者がアプリをビルド・パッケージングする際に使用するツールです。
そのため、electron-packagerはdevDependenciesとしてインストールされます。
devDependenciesとしてインストールされたパッケージは、本番環境にデプロイされる際には含まれないということです。

🌟完成したソフトウェアの配布

Electron で作成したアプリを配布する方法はいくつかありますが、dist フォルダを zip 形式で圧縮することもその一つです。
electron-packager や electron-builder などのツールを使ってアプリをビルドすると、通常、dist フォルダに実行ファイルや関連ファイルが生成されます。
この dist フォルダを zip 形式で圧縮することで、配布しやすい形にまとめることができます。
ただ、zip形式には次のようなメリットとデメリットがあることを押さえておきましょう。

手軽さ
圧縮・解凍ソフトを使って簡単に圧縮・解凍できるため、受け取る側も手間がかかりません。
ファイルサイズ
圧縮することでファイルサイズを小さくできるため、配布やダウンロードにかかる時間を短縮できます。
インストール
zip 形式で配布する場合、受け取った側は自分で解凍し、実行ファイルを適切な場所に配置する必要があります。
自動更新
zip 形式では、アプリの自動更新機能を実現するのが難しい場合があります。

このように、Electron アプリの配布方法として dist フォルダを zip 形式で圧縮することは一つの選択肢です。
しかしよりユーザーフレンドリーな方法としては、インストーラー形式での配布が推奨されます。
インストーラー形式では、受け取った側はインストーラーを実行するだけでアプリが適切な場所にインストールされ、必要な設定も自動的に行われます。
また、自動更新機能も実装しやすくなります。
Electron アプリならelectron-builderを使うのがやりやすいでしょうね。
パッケージングするためのツールですが、インストーラーの作成機能も備わっています。

個人のネット活動に流されないようにね!

個人発のソフトウェアをむやみにインストールしてはならない理由…
無数にあるけど、次のようなことはどこの教科書にも書いてあるのでは?
私も子供の頃からもう…イヤってほど叩きこまれています。

1. マルウェアのリスク

個人サイトに公開されているexeファイルには、マルウェアやウイルスが含まれている可能性があります。
これらの有害なプログラムは、コンピュータやネットワークに損害を与えたり、個人情報を盗み取ったりすることがあります。

2. 信頼性の欠如

公式のソースや信頼できるダウンロードサイトで提供されていないexeファイルは、その動作や品質が保証されていません。
予期しない動作やシステムのクラッシュなどの問題が発生する可能性があります。

3. プライバシーの侵害

不正なexeファイルは、個人情報や機密情報を不正に収集する可能性があります。
プライバシーが侵害されるリスクがあります。

4. ライセンス違反

正規のライセンスを持たないソフトウェアをダウンロードして使用することは、法的な問題を引き起こす可能性があります。
違法なソフトウェアの使用は、ソフトウェアの開発者や著作権者に損害を与えるだけでなく、自身も法的なトラブルに巻き込まれるリスクがあります。

5. セキュリティ更新の欠如

公式のソースから提供されているソフトウェアは、セキュリティ更新やパッチが定期的に提供されますが、個人サイトで公開されているexeファイルはそのような更新が行われないことが多いため、セキュリティホールが放置されるリスクがあります。

exeなどソフトウェアの実行ファイルをインストールする際には、必ず公式サイトや信頼できるダウンロードサイトから入手することを強くお勧めします。

でも試してみたくなっちゃったら?

人間には好奇心があり、それは大いに尊重されるべきものです。
お勉強の原動力になるからね。
GitHubなどを見ると、おもしろそうなソフトもいっぱいありますよ!
とは言え、上述している背景から、私のフローティング・ランチャーのexeファイルは提供しません。
でもソースコードはこうして全文公開して解説まで付けています。

言い変えると、このページに習って頂ければ、御自身で「マルチプラットフォーム対応のフローティング・ランチャー」を作れてしまいます😆ww
それなら安全であることはもちろん、次のようなメリットが期待できるでしょう。

今回は私の思い付きでフローティング・ランチャーでしたが、数か月後にはまた何かネタを思い付くかもしれません。
そしたらこのランチャーに機能追加してバージョン2として、改めて公開しましょう。

最後に、要は「調子こいちゃう」から、トラブルになるのですよ。
人からパクったソフトウェアを再配布してしまったりね。
意外にも、技術的なことより人間の原始的な欲求がトラブルの原因であることが多いものです。
節度を守りつつ、インターネットで遊べると良いですね🎵


サイトマップ

全ページをリスト化したサイトマップも用意していますが、けっこうなページ数があります。
下記の「カテゴリー分けサイトマップ」のほうが使いやすいでしょう。

アナザーエデン関連ページ・サイトマップ

アナザーエデンの強敵戦やストーリーコンテンツのリスト、お勧めバッジなどを掲載したコーナーです。
期間限定のない普通のRPGですので、初心者でも安心して続けていけるゲームとなっています。
もっとも重要なグラスタについては、場所別に網羅した表があります。

個人サイトのホスティングとコンテンツ作成

個人でウェブサイトを作るにはどうすればいいか。
HTML・CSS・JavaScriptの書き方はもちろん、無料かつ広告なしでホームページを作る方法を掲載したコーナーです。
Webデザインやレイアウトについても書いてあります。

魚釣りなどアウトドアのエリア

ゲームとパソコンだけじゃなく、アウトドアも趣味なんです。
このコーナーでは魚釣りの記録とか、魚料理のレシピ、はたまたサイクリングなどなど。
アウトドアに関連するコンテンツが詰め込まれています。