本記事では、静的サイトジェネレーターHugoのテーマを自作する際に、TypeScriptとReactを導入する方法について解説します。Hugo自体の基本的な設定については、markdownで記事を作成して無料ブログをつくる[Github Pages+Hugo] を参照してください。
1. Hugoテーマの初期化
hugo new theme コマンドを使用すると、テーマのひな形を簡単に作成できます。
| |
このコマンドを実行すると、tomatohugo という名前のディレクトリが作成され、その中にテーマ開発に必要な基本的なファイルとディレクトリ構造が生成されます。
| |
LICENSE: テーマのライセンス情報。README.md: テーマの説明や使用方法。archetypes/: コンテンツ作成時のテンプレート。assets/: CSSやJavaScriptなどのフロントエンドリソース。Hugo Pipesで処理されます。content/: サンプルのコンテンツ。data/: テーマで使用するデータファイル。hugo.toml: サイト全体の設定ファイル(Hugo 0.112.0以降)。i18n/: 多言語対応のための翻訳ファイル。layouts/: HTMLテンプレートファイル。static/: 静的ファイル(画像、ファビコンなど)。ビルド時にそのままコピーされます。theme.toml: テーマの設定を定義するファイル。
初期化が完了したら、hugo server コマンドを使用してローカルサーバーを起動し、シンプルなテーマが正しく動作しているか確認できます。
| |
初期化時のコミット例: https://github.com/yuhi-sa/tomatohugo/commit/695eed912b903388faf16a1791b852697811d348
2. TypeScriptの導入
テーマ内でTypeScriptを使用するために、Node.jsの環境をセットアップし、WebpackとTypeScriptコンパイラを設定します。
package.jsonの初期化: テーマディレクトリのルートでnpm initコマンドを実行し、package.jsonファイルを作成します。
npm init -y ```
TypeScriptと
ts-loaderのインストール: TypeScriptコンパイラと、WebpackでTypeScriptファイルを処理するためのローダーをインストールします。
npm install –save-dev typescript ts-loader webpack webpack-cli ```
tsconfig.jsonの作成: TypeScriptの設定ファイルtsconfig.jsonを作成します。
{ “compilerOptions”: { “target”: “es5”, // 出力するJavaScriptのバージョン “module”: “commonjs”, // モジュールシステム “outDir”: “./assets/js/”, // コンパイルされたJSファイルの出力先 “strict”: true // 厳格な型チェックを有効にする }, “include”: [ “./assets/ts/**/*.ts” // コンパイル対象のTypeScriptファイル ], “exclude”: [ “node_modules” // 除外するディレクトリ ] } ```
TypeScriptファイルの作成:
./assets/ts/ディレクトリ内にTypeScriptファイル(例:main.ts)を作成します。
const message: string = “Hello, TypeScript!”; console.log(message); ```
webpack.config.jsの作成: Webpackの設定ファイルを作成します。Webpackは、JavaScriptアプリケーションのためのモジュールバンドラーであり、TypeScriptファイルをバンドルするために使用します。
const path = require(‘path’);
module.exports = { mode: ‘development’, // または ‘production’ entry: ‘./assets/ts/main.ts’, // エントリポイント module: { rules: [ { test: /\.ts$/, // .tsファイルを対象とする use: ’ts-loader’, // ts-loaderを使用 exclude: /node_modules/, }, ], }, resolve: { extensions: [’.ts’, ‘.js’], // インポート時に解決する拡張子 }, output: { filename: ‘bundle.js’, // 出力ファイル名 path: path.resolve(__dirname, ‘assets/js’), // 出力ディレクトリ }, }; ```
ビルドの実行: Webpackを実行してTypeScriptファイルをJavaScriptにコンパイルし、バンドルします。
npx webpack
```
これにより、./assets/js/bundle.js が作成されます。
Hugoテンプレートへの組み込み: 生成されたJavaScriptファイルをHugoのテンプレートに組み込むために、
layouts/partials/head/js.htmlなどの適切な場所に以下のようなコードを追加します。
{{- with resources.Get “js/bundle.js” }}
{{- end }} ``` TypeScript導入時のPR例: https://github.com/yuhi-sa/tomatohugo/pull/1
3. Reactの導入
TypeScript環境にReactを追加します。
React関連ライブラリのインストール: React本体とDOM操作ライブラリ、およびそれらの型定義ファイルをインストールします。
npm install –save react react-dom npm install –save-dev @types/react @types/react-dom ```
Reactコンポーネントの記述: ReactではJSX(JavaScript XML)と呼ばれる構文を使用してコンポーネントを記述するため、TypeScriptファイルの拡張子を
assets/ts/main.tsxに変更します。
import React from ‘react’; import { createRoot } from ‘react-dom/client’; // React 18以降の推奨API
const App = () => { return (
Hello, React!
// HTML内のマウントポイントとなる要素を取得
const appElement = document.getElementById(‘app-root’); // 例: idを’app-root’とする
if (appElement) {
const root = createRoot(appElement); // createRootでルートを作成
root.render(ReactDOM.render の代わりに createRoot を使用することが推奨されています。HTML側のマウントポイントのIDも app-root などに変更してください。
Hugoテンプレートへの組み込み: Reactコンポーネントを呼び出すためのHTML要素を、適切なHugoのテンプレートファイル(例:
layouts/_default/single.htmlやlayouts/_default/home.html)に追加します。
{{- partial “head/js.html” . -}} ```
Webpack設定の更新: Reactコンポーネント(.tsxファイル)をバンドルするために、Webpackの設定を更新します。
const path = require(‘path’);
module.exports = { mode: ‘development’, entry: ‘./assets/ts/main.tsx’, // エントリポイントを.tsxに変更 module: { rules: [ { test: /\.tsx?$/, // .tsまたは.tsxファイルを対象とする use: ’ts-loader’, exclude: /node_modules/, }, ], }, resolve: { extensions: [’.ts’, ‘.tsx’, ‘.js’], // 拡張子に.tsxを追加 }, output: { filename: ‘bundle.js’, path: path.resolve(__dirname, ‘assets/js’), }, }; ```
動作確認: 動作確認を行います。 ローカルサーバーを起動し、「Hello, React!」が表示されることを確認します.
hugo server ``` React導入時のPR例: https://github.com/yuhi-sa/tomatohugo/pull/2