仕組みと構成
なぜサイトの外に置いてもうまくいくのか
riebeckite.config.ts の content.directory は、次のルールで解決されます。
| 名前 | 役割 | 既定値 / 解決の基準 |
|---|---|---|
appRoot |
HonoX/Vite アプリケーション。app/、public/、ルート、生成されるスタイル、ビルド出力を管理する |
Vite の root |
configRoot |
riebeckite.config.ts を含むディレクトリ |
appRoot |
contentRoot |
設定したコンテンツディレクトリ、または Obsidian Vault のファイルシステム上の絶対ルート | path.resolve(appRoot, content.directory) |
ここで押さえたいのは、相対パスの content.directory が常に appRoot を基準に解決され、configRoot や作業ディレクトリが変わっても基準が動かないことです。統合側はコンテンツやプラグインを実行する前に3つのルートを解決し、CLI も同じ結果を使います。そのため、入れ子のディレクトリから実行しても、CI の作業ディレクトリから実行しても、エディタのタスクから実行しても、同じ Vault を読みます。
Diagram source
flowchart TD
App["appRoot"]
Config["content.directory<br/>../vault"]
Resolve["path.resolve()"]
Content["contentRoot"]
App --> Resolve
Config --> Resolve
Resolve --> Content
// site/riebeckite.config.ts
export default defineConfig({
content: {
directory: "../vault", // relative to appRoot
},
});
この値は process.cwd() から組み立てないでください。appRoot を Vault に向けるのも避けてください。Vault はソースデータであり、Vite アプリケーションのルートはサイトのままにします。
ルートはどの順番で決まるか
順番を追うと、よくあるつまずきどころが見えてきます。
- CLI は作業ディレクトリから親方向へ
riebeckite.config.ts/.js/.mjsを探します。最初に見つかったファイルのディレクトリがconfigRootです。見つからなければCould not find riebeckite.config.*で失敗します。 - appRoot は
configRootの下を走査してvite.config.ts/.js/.mjsを探して決まります(node_modules、.git、testsは除外)。見つからなくても、複数見つかってもエラーです。 - contentRoot は
path.resolve(appRoot, content.directory)で解決します。directoryが絶対パスでも、解決結果は同じです。
Diagram source
flowchart TD
CLI["CLI を実行"]
Config["riebeckite.config.* を探す"]
ConfigRoot["configRoot"]
Vite["vite.config.* を探す"]
AppRoot["appRoot"]
Directory["content.directory"]
ContentRoot["contentRoot"]
CLI --> Config
Config --> ConfigRoot
ConfigRoot --> Vite
Vite --> AppRoot
AppRoot --> ContentRoot
Directory --> ContentRoot
riebeckite.config.ts を意図的に Vite アプリケーションの外に置く場合は、riebeckiteVite() に configRoot と appRoot を渡してください。どちらの場合も、相対 content.directory の基準は appRoot のままです。
つまり、「どこから実行しても同じ Vault を読む」というのは、設定がサイトの中(またはその親)にあり、appRoot が一意に決まる場合に限り成り立ちます。関係のないディレクトリから実行すれば設定ファイル自体が見つかりませんし、vite.config.* が複数あるモノレポでは Found multiple Vite applications で失敗します。どちらも、どのサイトの設定を使うべきかをツールが特定できなかったという意味です。
アプリケーション側からコンテンツを読む
統合側は、解決済みの設定と、そのまま使える ContentManager を、フレームワーク側が管理するモジュールとして公開しています。アプリケーションのコードは riebeckite.config.ts を読み直すのではなく、これらを import します。
import { config } from "virtual:riebeckite/config";
import { content } from "virtual:riebeckite/content";
config.content.directory はすでに絶対パスです。これを別の基準で解決し直すのが、よくある不具合の原因になります。Vite の外で動くスクリプトでは、@riebeckite/honox/runtime の resolveHonoxConfig を使えば同じ値を解決できます。
やってはいけないこと
content.directoryをprocess.cwd()から組み立てる。実行場所によって結果が変わります。appRoot(Vite のroot)を Vault に向ける。サイトのapp/、public/、ビルド出力まで移動してしまいます。- 相対
directoryがconfigRoot基準だと思う。基準は常にappRootです。
判断の目安は次のとおりです。
使わない
→ process.cwd()
基準
→ appRoot
3つの構成から選ぶ
| 構成 | レイアウト | 選ぶ条件 | デプロイ時の注意 |
|---|---|---|---|
| A. 1つのリポジトリにまとめる | サイトと記事を1つの Git リポジトリに置く(content/ を使う) |
個人ブログを1つのリポジトリで管理したい | 追加の設定は不要 |
| B. 1つのリポジトリでフォルダを分ける | site/ と vault/ を同じリポジトリに並べる |
履歴は共有したいが、場所は分けたい | サイト側で content.directory: "../vault" を設定する |
| C. リポジトリを分ける(推奨) | 記事は非公開、サイトは公開 | 記事を非公開にしたい、更新を切り離したい | CI で記事リポジトリを取得する設定が必要 |
A: 1つのリポジトリにまとめる
blog/
├─ riebeckite.config.ts ← appRoot (directory: "content")
├─ app/
├─ public/
└─ content/ ← articles live here
└─ index.md
最も単純な構成で、create-riebeckite が生成するのもこの形です。記事の公開範囲はリポジトリの公開範囲と同じになります。
B: 1つのリポジトリでフォルダを分ける
notes-repo/
├─ site/ ← appRoot (contains riebeckite.config.ts)
│ └─ riebeckite.config.ts
└─ vault/ ← referenced by directory: "../vault"
リポジトリも履歴も1つで、置き場所だけを分けます。公開範囲は A と同じくリポジトリ単位のままです。A との違いは content.directory: "../vault" だけです。
1つの Vault を複数のサイトで共有する
C の応用です。Vault を独立した場所に置き、複数のサイトから参照します。
workspace/
├─ notes/ ← shared vault (its own private repository)
├─ blog/ ← site 1 (directory: "../notes")
└─ docs/ ← site 2 (directory: "../notes")
Vault は読み取り専用のソースデータとして扱い、exclude、publishStrategy、プラグインはサイトごとに変えます。どのサイトも Vault に書き戻さないため、同じノートを異なる形で公開できます。各サイトは個別にデプロイし、それぞれの CI にコンテンツの取得とデプロイの起動は別に考えるで説明する追加チェックアウトを設定してください。
Diagram source
flowchart TD
Vault["プライベート Vault"]
Vault --> Blog["ブログ"]
Vault --> Docs["ドキュメント"]
Blog --> BlogRules["ブログの設定<br/>exclude / プラグイン"]
Docs --> DocsRules["ドキュメントの設定<br/>exclude / プラグイン"]
各サイトは exclude、publishStrategy、プラグイン、テーマ、デプロイを独立して設定できます。そのため、同じノートでもサイトごとに公開範囲や見せ方を変えられます。
どの構成を選ぶか
- 記事を非公開にしたい、更新を切り離したい → C。
- 記事とサイトの公開範囲が同じで構わない → 次へ。
- 場所と設定だけを分けたい → B。1つのリポジトリにまとめたい → A。
- 1つの Vault を複数のサイトで使いたい → C + Vault の共有。