HUGO v0.74で追加されたJS Bundlerを試す
HUGOのv0.74.0にて、ESBuildが組み込まれ、 HUGO上でJavaScript/JSXやTypeScript/TSXのバンドルが行えるようになりました。
Native JS Bundler, Open API Support, Inline Partials
HUGOの公式ドキュメントにはまだ記載されてませんが、Document JS.Build #1171を参考にこの記事では、JS Budlerを利用する方法を説明します。
2020/07/21 追記 この機能についてのドキュメントが公開されました。 JavaScript Building
動作を確認した環境
- HUGO v0.74.2
- Node.js v12.18.1
基本
バンドル対象のリソースは、テーマディレクトリ、またはサイトディレクトリのassets
の下に置きます。
サイトディレクトリ内のテンプレート内で利用する場合
site/ ├── ... ├── assets/ │ └── js/ │ └── index.ts ├── ...
テーマディレクトリ内のテンプレート内で利用する場合
site ├── ... ├── themes │ └── THEME/ │ ├── ... │ ├── assets │ │ └── js │ │ └── index.ts │ ├── ... ├── ...
TypeScriptのビルド&バンドル
TypeScriptをビルド&バンドルしたいテンプレートファイルに、次のように記述します。
{{ with resources.Get "js/index.ts" }}
{{ $js := resources.Get . | js.Build }}
<script src="{{ $js.Permalink }}"></script>
{{ end }}
resources.Get
のあとに、対象のファイルをassets
以下からパスを指定します。- ビルドしたファイルのパス(ここでは、
$js.Permalink
)を<script>
タグで指定します。
HUGOでビルドすると、jsファイルと次のようなHTMLが生成されます。
<!-- ...略... -->
<script src="http://localhost:1313/js/index.js"></script>
<!-- ...略... -->
生成されるファイル名は、バンドルする対象のファイル名と同じです。名前を変更するには、js.Build
に渡すオプションとしてtargetPath
を指定します。
{{ with resources.Get "js/index.ts" }}
{{ $js := resources.Get . | js.Build (dict "targetPath" "js/main.js") }}
<script src="{{ $js.Permalink }}"></script>
{{ end }}
ファイルをMinifyするには、js.Build
で渡すオプションに"minify" true
を渡すか、resources.Minify
にパイプで渡します。 参考:Asset minification
"minify" true
を渡す例(オプションが冗長になってきたので、別変数に切り出し){{ with resources.Get "js/index.ts" }} {{ $option := dict "targetPath" "js/main.js" "minify" true }} {{ $js := resources.Get . | js.Build $option }} <script src="{{ $js.Permalink }}"></script> {{ end }}
Reactのビルド&バンドル
node_modulesからのインポートをサポートしているので、Reactアプリケーションもバンドルできます。 今回は、HUGO v0.74.2で追加されたdefines
を利用します。
次のようなReactアプリケーションをバンドルすることを考えます(参考: Components and Props)。
import * as React from "react";
import * as ReactDOM from "react-dom";
function Welcome(props) {
return <p>Hello, {props.name}</p>;
}
function App() {
return (
<>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</>
);
}
ReactDOM.render(
<App />,
document.getElementById("react")
);
npm install
で利用するモジュールをインストールします。
package.json
およびnode_modules
はバンドルするテンプレートディレクトリに配置する必要があります。 たとえば、テーマディレクトリ内のテンプレートで利用する場合には、テンプレートディレクトリの下に配置します。
npm init -y
npm install --save react react-dom
バンドルしたいテンプレートファイルに、次のように記述します。
{{ with resources.Get "js/App.jsx" }}
<div id="react"></div>
{{ $options := dict "targetPath" "js/app.js" "minify" true "defines" (dict "process.env.NODE_ENV" "\"development\"") }}
{{ $js := resources.Get . | js.Build $options }}
<script src="{{ $js.Permalink }}"></script>
{{ end }}
HUGOでビルドすると、jsファイルと次のようなHTMLが生成されます。
<!-- ...略... -->
<div id="react"></div>
<script src="http://localhost:1313/js/app.min.js"></script>
<!-- ...略... -->
ReactをHUGOでバンドルできると、AlgoliaのReact InstantSearchを利用して実装する検索画面も組込みきます。 検索画面のためのソースコードを別リポジトリで管理する必要がなくなるので、便利だなと感じます。