
はじめに
IIIFビューアであるMiradorの最新版(Mirador 4)に対応した回転プラグイン「mirador-rotation」を開発し、npmで公開しました。本記事では、プラグインの開発から公開、そして実際に利用するための統合方法について解説します。
背景
Mirador 3からMirador 4へのメジャーアップデートに伴い、以下の変更がありました:
- React 16 → React 18
- Material-UI v4 → MUI v7
- その他多数の依存関係の更新
これにより、既存のMirador 3用プラグインはそのままでは動作しなくなりました。
mirador-rotation-pluginの開発
リポジトリ
https://github.com/nakamura196/mirador-rotation-plugin
主な機能
- 画像の回転機能
- Mirador 4のプラグインメニューへの統合
npmへの公開
開発したプラグインはnpmで公開しています:
npm install mirador-rotation
mirador-integrationの更新
公式のmirador-integrationリポジトリを参考に、Mirador 4対応の統合環境を構築しました。
主な変更点
| 項目 | 旧 | 新 |
|---|---|---|
| Mirador | 3.x | 4.0.0 |
| React | 16.14.0 | 18.x |
| ビルドツール | Webpack | Parcel |
| UI | Material-UI v4 | MUI v7 |
package.json
最小限の依存関係で構成しています:
{
"dependencies": {
"mirador": "^4.0.0",
"mirador-rotation": "^4.0.0",
"parcel": "^2.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
外部から利用するための工夫
問題
公式のmirador-integrationをそのままビルドすると、ESモジュール形式で出力されます。しかし、別のHTMLページから<script>タグで読み込んで使いたい場合、グローバル変数としてMiradorが定義されないという問題がありました。
script src="mirador.js">script>
script>
Mirador.viewer({...}); // Mirador is not defined
script>
解決策
1. ライブラリ用エントリーポイントの作成
index.jsでグローバル変数として明示的にエクスポートします:
import Mirador, * as MiradorAll from 'mirador';
import { miradorRotationPlugin } from 'mirador-rotation';
window.Mirador = { ...Mirador, ...MiradorAll };
window.miradorRotationPlugin = miradorRotationPlugin;
重要: * as MiradorAllでnamed exportsもすべて取得し、スプレッド構文でフラット化しています。この理由については後述します。
2. Parcelのビルド設定
package.jsonでグローバル形式での出力を指定:
{
"source": "index.js",
"targets": {
"global": {
"outputFormat": "global",
"distDir": "./dist"
}
},
"scripts": {
"build": "parcel build --target global"
}
}
3. ファイル名の正規化
Parcelはデフォルトでハッシュ付きのファイル名を生成するため、リネームスクリプトを作成:
// scripts/rename-build.js
const fs = require('fs');
const path = require('path');
const distDir = path.join(__dirname, '..', 'dist');
fs.readdirSync(distDir).forEach(file => {
if (file.startsWith('index') && file.endsWith('.js')) {
fs.renameSync(
path.join(distDir, file),
path.join(distDir, 'mirador.js')
);
}
});
使い方
ビルド後、dist/mirador.jsを任意のHTMLで読み込めます:
div id="demo">div>
script src="mirador.js">script>
script>
Mirador.viewer({
id: 'demo',
windows: [{
rotationEnabled: true,
manifestId: 'https://example.com/manifest.json',
}],
}, [...miradorRotationPlugin]);
script>
APIのフラット化問題
問題の発覚
unpkg.comで配布されているMiradorのUMDビルドを使用していた場合、以下のようにAPIを直接呼び出せていました:
Mirador.addCompanionWindow(windowId, { content: 'info' });
しかし、Parcelでビルドした後に同じコードを実行すると、以下のエラーが発生しました:
TypeError: Mirador.addCompanionWindow is not a function
原因の調査
unpkg.comのUMDビルドとParcelビルドを比較した結果、エクスポート構造の違いが原因でした:
| ビルド方法 | エクスポート構造 | API呼び出し |
|---|---|---|
| unpkg.com (UMD) | フラット化 | Mirador.addCompanionWindow() |
| Parcel (default exportのみ) | ネスト | Mirador.actions.addCompanionWindow() |
unpkg.comのUMDビルドでは、すべてのアクション・セレクターがトップレベルにフラット化されています:
// UMDビルドの末尾(抜粋)
G.addCompanionWindow=Oj,
G.removeCompanionWindow=Aj,
G.updateCompanionWindow=yg,
// ... その他多数
一方、単純にimport Mirador from 'mirador'でdefault exportのみを取得した場合:
// default exportの構造
{
viewer: function,
actions: { addCompanionWindow, ... },
selectors: { ... },
// ...
}
解決策
index.jsでnamed exportsもすべて取得し、スプレッド構文でフラット化:
// Before(動かない)
import Mirador from 'mirador';
window.Mirador = Mirador;
// After(動く)
import Mirador, * as MiradorAll from 'mirador';
window.Mirador = { ...Mirador, ...MiradorAll };
これにより、ビルド後のファイルでは以下のようにフラット化されます:
window.Mirador={...f.default,...f}
補足:mirador-rotationのバージョン
mirador-rotationプラグインには4.0系と4.1系があります:
| バージョン | MUI | 対象 |
|---|---|---|
| 4.0.x | v5 | Mirador 4 alpha初期版 |
| 4.1.x | v7 | Mirador 4.0.0 正式版 |
Mirador 4.0.0正式版はMUI v7を使用しているため、mirador-rotation 4.1.x を使用してください。
まとめ
Mirador 4用のプラグイン開発と公開、そして外部から利用可能なライブラリとしてビルドする方法を紹介しました。
ポイント:
- ESモジュール形式ではグローバル変数が定義されない
import Mirador, * as MiradorAllでdefault exportとnamed exportsの両方を取得{ ...Mirador, ...MiradorAll }でフラット化してエクスポート- Parcelの
outputFormat: "global"でグローバル形式ビルド