フロントエンドの概要
IC では、JavaScript agent を使うことで dapps のために Web 3.0 のフロントエンドをホストすることができます。また、dfx が提供する asset canister を使って静的ファイルを IC にアップロードすることで、アプリケーション全体を分散型技術で実行することができます。このセクションでは、dfx new で提供されるデフォルトのフロントエンドテンプレート、フロントエンドの設定オプション、プロジェクトのユーザーインターフェイスを構築するための他のフレームワークの使用について詳しく説明します。
ここではフロントエンド Dapps の開発の様々な段階でのサンプルコードを含むチュートリアルへのクイックリンクをご紹介します。
- React dapp 構築のチュートリアル Customize the frontend 
- Candid を、Canister 内の機能を公開してテストするための最低限のインターフェースとして使用する。 
- 生の HTML と JavaScript を使って、シンプルな HTML エントリーページを表示する。 
- React とコンパイルされた JavaScript を使って、HTML の属性や要素を直接ページに埋め込む。 
- React と TypeScript を使って、外部ファイルから CSS プロパティをインポートする。 
デフォルトテンプレートの使用方法
チュートリアルでお気づきのように、プロジェクトにはテンプレートの index.js と webpack.config.js ファイルが含まれています。
デフォルトでは、index.js ファイルは、src/declarations フォルダにあるエージェントをインポートします。このディレクトリは、dfx deploy を実行しローカルまたは Internet Computer にデプロイするときに、dfx によって生成されます。
その生成されたコードは以下のようになります。
import { Actor, HttpAgent } from "@dfinity/agent";
// candid interfaceをimport
import { idlFactory } from './hello.did.js';
// CANISTER_ID は、ノード環境に応じて webpack で置き換え
export const canisterId = process.env.HELLO_CANISTER_ID;
/**
 *
 * @param {string | Principal} canisterId Canister ID of Agent
 * @param {{agentOptions?: import("@dfinity/agent").HttpAgentOptions; actorOptions?: import("@dfinity/agent").ActorConfig}} [options]
 * @return {import("@dfinity/agent").ActorSubclass<import("./hello.did.js")._SERVICE>}
 */
export const createActor = (canisterId, options) => {
  const agent = new HttpAgent({ ...options?.agentOptions });
  // 開発中の証明書検証のためのルートキーをfetch
  if(process.env.NODE_ENV !== "production") agent.fetchRootKey();
  // actor をcandid インターフェースとHttpAgentを利用して生成
  return Actor.createActor(idlFactory, {
    agent,
    canisterId,
    ...options?.actorOptions,
  });
};
/**
 * A ready-to-use agent for the hello canister
 * @type {import("@dfinity/agent").ActorSubclass<import("./hello.did.js")._SERVICE>}
 */
export const hello = createActor(canisterId);
そして、index.js に戻ると、生成されたアクターを受け取り、それを使って hello Canister の greet メソッドを呼び出しているのがわかります。
import { hello } from "../../declarations/hello";
document.getElementById("clickMeBtn").addEventListener("click", async () => {
  const name = document.getElementById("name").value.toString();
  // Interact with hello actor, greet methodをコール
  const greeting = await hello.greet(name);
  document.getElementById("greeting").innerText = greeting;
});
多くのプロジェクトでは、declarations にあるコードをそのまま使うことができ、hello_assets/src に変更を加えることができます。しかし、あなたのプロジェクトに追加の要件がある場合は、以下を読み進めてください。
webpack の設定を変更する
webpack は、JavaScript ベースのアプリケーション用のモジュールバンドラーとして人気があり、高度な設定が可能であるため、新しいプロジェクトでは、デフォルトの webpack.config.js ファイルが作成され、使用したい特定のモジュール(react や markdown など)を簡単に追加できるようになっています。
テンプレートの webpack.config.js ファイルのコードを確認すると、ローカル開発の場合は .dfx/local/canister_ids.json から、その他の環境を設定した場合は ./canister_ids.json から Canister ID を推定しています。どのネットワークを使用するかは、プロセス変数の DFX_NETWORK や、NODE_ENV が "production" に設定されているかどうかに基づいて決定されます。
これらの手順は以下のコードブロックで見ることができます。
let localCanisters, prodCanisters, canisters;
try {
  localCanisters = require(path.resolve(".dfx", "local", "canister_ids.json"));
} catch (error) {
  console.log("No local canister_ids.json found. Continuing production");
}
function initCanisterIds() {
  try {
    prodCanisters = require(path.resolve("canister_ids.json"));
  } catch (error) {
    console.log("No production canister_ids.json found. Continuing with local");
  }
  const network =
    process.env.DFX_NETWORK ||
    (process.env.NODE_ENV === "production" ? "ic" : "local");
  canisters = network === "local" ? localCanisters : prodCanisters;
  for (const canister in canisters) {
    process.env[canister.toUpperCase() + "_CANISTER_ID"] =
      canisters[canister][network];
  }
}
initCanisterIds();
エントリーとアウトプットの設定
多くの場合、デフォルトの webpack.config.js ファイルをそのまま、何も変更せずに使用することもできますし、プラグインやモジュール、その他のカスタム構成を追加して、ニーズに合わせて使用することもできます。 具体的に webpack.config.js の設定をどのように変更するかは、使用したい他のツールやフレームワークに大きく依存します。
例えば、フロントエンドのチュートリアルである フロントエンドのカスタマイズ や スタイルシートの追加 を試したことがある方は、React JavaScript で動作するように以下の部分を変更しているかもしれません。
    module: {
      rules: [
        { test: /\.(ts|tsx|jsx)$/, loader: "ts-loader" },
        { test: /\.css$/, use: ['style-loader','css-loader'] }
      ]
    }
  };
}
ビルドスクリプトの実行に dfx を使用しないアプリケーションの場合は、自分で変数を用意することができます。例えば、以下のようになります。
DFX_NETWORK=staging NODE_ENV=production HELLO_CANISTER_ID=rrkah... npm run build
ノードがプロジェクトで利用可能であることを確認する
プロジェクトは、デフォルトのフロントエンドのフレームワークを提供するために webpack に依存しているので、開発環境に node.js がインストールされ、プロジェクトディレクトリにアクセスできる必要があります。
- デフォルトの webpack 設定と Canister のエイリアスを使用せずにプロジェクトを開発したい場合は、 - dfx.jsonファイルから- assetsCanister を削除するか、特定の Canister 名を使用してプロジェクトをビルドすることができます。例えば、以下のコマンドを実行すると、フロントエンドのアセットを使わずに hello プログラムだけをビルドすることができます。- dfx build hello
- デフォルトの webpack 構成を使用していて、 - dfx buildの実行に失敗する場合は、プロジェクトディレクトリで- npm installを実行してから、- dfx buildを再実行してください。
- プロジェクトディレクトリで - npm installを実行しても問題が解決しない場合は、- webpack.config.jsファイルの設定にシンタックスエラーがないか確認してください。
他のモジュールを React フレームワークで使用する
リポジトリにあるいくつかのチュートリアルやサンプルプロジェクトでは、npm install コマンドを使って React モジュールを追加する方法が説明されています。 これらのモジュールを使って、プロジェクトで使用したいユーザーインターフェースコンポーネントを構築することができます。 例えば、以下のコマンドを実行して、react-router モジュールをインストールすることができます。
npm install --save react react-router-dom
このモジュールを使って、以下のようなナビゲーションコンポーネントを作ることができます。
import React from 'react';
import { NavLink } from 'react-router-dom';
const Navigation = () => {
  return (
    <nav className="main-nav">
      <ul>
        <li><NavLink to="/myphotos">Remember</NavLink></li>
        <li><NavLink to="/myvids">Watch</NavLink></li>
        <li><NavLink to="/audio">Listen</NavLink></li>
        <li><NavLink to="/articles">Read</NavLink></li>
        <li><NavLink to="/contribute">Write</NavLink></li>
      </ul>
    </nav>
  );
}
export default Navigation;
webpack-dev-server を使用した反復処理の高速化
dfx 0.7.7 から、dfx new スターターに webpack dev-server が搭載されました。
webpack 開発サーバ webpack-dev-server は、webpack アセットへのインメモリアクセスを提供し、ライブリロードを使って変更を行い、すぐにブラウザに反映させることができます。
webpack-dev-server を利用するには、次のようにします。
- 新しいプロジェクトを作成し、プロジェクトディレクトリに変更します。 
- 必要に応じて{IC}をローカルで起動し、 - dfx deployコマンドを実行するなど、通常の操作でデプロイします。
- 以下のコマンドを実行して、webpack 開発サーバーを起動します。 - npm start
- Web ブラウザーを開き、8080 ポートを使用して、アプリケーションのアセット Canister にナビゲートします。 - 例: - http://localhost:8080
- 新しいターミナルウィンドウまたはタブを開き、プロジェクトのディレクトリに移動します。 
- プロジェクトの - index.jsファイルをテキストエディターで開き、内容を変更します。- 例えば、JavaScript を使ってページに要素を追加するような場合です。 - document.body.onload = addElement; - document.body.onload = addElement;
 function addElement () {
 // div要素を新規に生成
 const newDiv = document.createElement("div");
 // それに乗せるコンテント
 const newContent = document.createTextNode("Test live page reloading!");
 // 新しく作成された div 要素に テキストノードである newContent を追加
 newDiv.appendChild(newContent);
 // 新しく作成したnewDiv要素とnewContentをDOMに追加
 const currentDiv = document.getElementById("div1");
 document.body.insertBefore(newDiv, currentDiv);
 }
- index.jsファイルへの変更を保存しますが、エディタを開いたままにしておき、変更を続けます。
- ブラウザを更新するか、またはブラウザが自動的に更新されるのを待つと、変更内容が表示されます。 - プロジェクトのフロントエンドの作業が終わったら、Control-C を押して webpack 開発サーバーを停止することができます。 
他のフレームワークを使うと
webpack 以外のバンドラーを使いたい場合もあるでしょう。バンドラーごとの説明はまだ準備できていませんが、お使いのバンドラーに精通していれば、以下の手順で作業を進めることができます。
- package.jsonから- copy:types,- prestart,- prebuildのスクリプトを削除します。
- dfx deployを実行して、Canister 用のローカルバインディングを生成します。
- 生成されたバインディングを保存したいディレクトリにコピーします。 
- declarations/<canister_name>/index.jsを修正し、- process.env.<CANISTER_NAME>_CANISTER_IDをバンドラーの環境変数に相当するパターンに置き換えます。- 望ましいワークフローであれば、CanisterID をハードコードすることもできます。
 
- 宣言をコミットして、コードベースに import します。