mcpField
F
frappe-ops-frontend-build

frappe-ops-frontend-build

github.com/impertio-studio開発198110 回インストール30 週間前に更新
リポジトリ

frappe-ops-frontend-build について

Frappe v14およびv15以降のフロントエンドアセット構築を開発者向けに解説します。v14のbuild.json方式とv15以降のesbuildパイプラインを扱い、バンドル設定、アセット読み込み、開発時の監視、本番ビルドを説明します。

主な機能

  1. 01v14とv15以降のビルド方式解説
  2. 02バンドルのエントリーポイント自動検出
  3. 03DeskとPortalのアセット設定
  4. 04監視モードとライブリロード
  5. 05本番ビルドとアセット最適化

活用シーン

  1. 01Frappeアプリのフロントエンドバンドル設定
  2. 02v14のビルド構成をesbuildへ移行
  3. 03開発中のアセット変更を監視
  4. 04圧縮済みの本番アセットを準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/impertio-studio/frappe_claude_skill_package --skill frappe-ops-frontend-build

インストール後、Claude Code で/frappe-ops-frontend-buildを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
.gitkeep
anti-patterns.md
examples.md

詳細

フロントエンドビルドシステム

ビルド設定から本番環境向けの最適化まで、Frappe のフロントエンドアセットバンドルパイプラインを網羅したリファレンスです。

バージョン:v14(build.json)/v15 以降(esbuild)


クイックリファレンス:ビルドコマンド

タスクコマンド
すべてのアプリをビルドbench build
特定のアプリをビルドbench build --app myapp
複数のアプリをビルドbench build --apps frappe,erpnext
本番ビルド(圧縮)bench build --production
強制的に再ビルドbench build --force
ウォッチモード(自動再ビルド)bench watch
アセットをハードリンクbench build --hard-link

判断ツリー:ビルドシステムの選択

Which build system?
├── Frappe v14?
│   └── build.json — Concatenation-based bundling
├── Frappe v15+?
│   └── esbuild — ES module bundling with *.bundle.* convention
└── Migrating v14 → v15?
    └── Replace build.json with *.bundle.* files in public/

ビルドパイプラインの概要

v15 以降(esbuild):現行システム

v15 以降のビルドシステムでは、ES モジュールを高速にバンドルするために esbuild を使用します。public/ ディレクトリをスキャンし、*.bundle.{js|ts|css|scss|sass|less|styl} に一致するファイルを探して、バンドルのエントリーポイントを自動的に検出します。

仕組み:

  1. bench build が各アプリの public/ ディレクトリを再帰的にスキャンします
  2. *.bundle.* に一致するファイルをエントリーポイントとして扱います
  3. esbuild が各エントリーポイントをコンパイル、バンドルし、必要に応じて圧縮します
  4. 出力先は assets/dist/[app]/js/ または assets/dist/[app]/css/ です
  5. キャッシュを更新できるよう、ファイル名にコンテンツハッシュが含まれます:main.bundle.HASH.js

対応するファイル形式:

  • .js — import/export を使用した ES6 モジュール
  • .ts — TypeScript
  • .vue — Vue 単一ファイルコンポーネント
  • .css — 標準 CSS
  • .scss / .sass — SASS/SCSS スタイルシート
  • .less — Less スタイルシート
  • .styl — Stylus スタイルシート
v14(build.json):レガシーシステム

v14 のシステムでは、アプリのルートにある build.json を使用して、ファイルの連結ルールを定義します。

{
  "js/myapp.min.js": [
    "public/js/file1.js",
    "public/js/file2.js"
  ],
  "css/myapp.min.css": [
    "public/css/style1.css",
    "public/css/style2.css"
  ]
}

v15 以降では、esbuild のパイプラインによって無視されるため、build.json は絶対に使用しないでください。


バンドルのエントリーポイント[v15 以降]

バンドルの作成

アプリの public/ ディレクトリに、.bundle. という命名規則に従ったファイルを配置します。

myapp/
└── public/
    ├── js/
    │   └── myapp.bundle.js       # → dist/myapp/js/myapp.bundle.HASH.js
    ├── css/
    │   └── myapp.bundle.scss     # → dist/myapp/css/myapp.bundle.HASH.css
    └── components/
        └── widget.bundle.js      # → dist/myapp/js/widget.bundle.HASH.js
バンドルファイルの内容
// myapp/public/js/myapp.bundle.js
import { createApp } from "vue";
import MyComponent from "./components/MyComponent.vue";

// ES6 imports are resolved by esbuild
import "../css/myapp.bundle.scss";

// npm packages (installed via yarn) can be imported directly
import dayjs from "dayjs";

createApp(MyComponent).mount("#myapp-root");
出力のマッピング
入力出力
public/js/main.bundle.jsassets/dist/[app]/js/main.bundle.[hash].js
public/css/style.bundle.scssassets/dist/[app]/css/style.bundle.[hash].css
public/deep/nested/file.bundle.tsassets/dist/[app]/js/file.bundle.[hash].js

hooks.py でのアセットの指定

Desk アセット(バックエンドインターフェース)
# hooks.py — loads in /app (Desk)
app_include_js = "myapp.bundle.js"
app_include_css = "myapp.bundle.css"

# Multiple files
app_include_js = ["myapp.bundle.js", "extra.bundle.js"]
app_include_css = ["myapp.bundle.css", "extra.bundle.css"]
ポータルアセット(公開ウェブサイト)
# hooks.py — loads on web pages (portal)
web_include_js = "myapp-web.bundle.js"
web_include_css = "myapp-web.bundle.css"
ページ固有のアセット
# hooks.py — loads on specific Desk pages
page_js = {"page_name": "public/js/custom_page.js"}
ウェブフォームアセット(標準ウェブフォームのみ)
# hooks.py — loads on specific Web Forms
webform_include_js = {"ToDo": "public/js/custom_todo.js"}
webform_include_css = {"ToDo": "public/css/custom_todo.css"}
重要なルール
  • v15 以降では、hooks.py に完全なパスではなくバンドルのファイル名を必ず使用してください
  • hooks.py にハッシュを絶対に含めないでください。ハッシュ付きのファイル名は Frappe が自動的に解決します
  • hooks.py を変更した後は、必ず再ビルドしてください:bench build --app myapp
  • 複数のアプリで同じフックを定義できます。アセットはインストール済みのすべてのアプリから累積されます

テンプレートへのアセットの読み込み

Jinja ヘルパー

{{ include_script("myapp.bundle.js") }}


{{ include_style("myapp.bundle.css") }}


<script src="{{ bundled_asset('myapp.bundle.js') }}"></script>
Desk での遅延読み込み
// Load asset on demand (returns Promise)
frappe.require("myapp.bundle.js", () => {
    // Asset loaded, initialize component
    myapp.init();
});

// Multiple assets
frappe.require(["widget.bundle.js", "widget.bundle.css"], () => {
    // Both loaded
});

SCSS/CSS のコンパイル

SCSS バンドルの例
// myapp/public/css/myapp.bundle.scss

// Import Frappe variables (available in all apps)
@import "frappe/public/scss/variables";

// Import partials (NOT bundles — no .bundle. in name)
@import "./components/header";
@import "./components/sidebar";

.myapp-container {
  padding: var(--padding-lg);
  background: var(--bg-color);
}
パーシャルファイル

パーシャル(_ で始まるファイル、またはファイル名に .bundle. を含まないファイル)は、エントリーポイントとしてコンパイルされません。@import を通じてのみ読み込まれます。

public/css/
├── myapp.bundle.scss        # Entry point — compiled
├── _variables.scss          # Partial — imported only
└── components/
    ├── _header.scss         # Partial — imported only
    └── _sidebar.scss        # Partial — imported only

開発ワークフロー

ウォッチモード[v15 以降]
# Auto-rebuild on file changes
bench watch
  • すべてのアプリの public/ ディレクトリを監視し、変更を検出します
  • 影響を受けるバンドルのみを再ビルドします(インクリメンタル)
  • live_reload が有効な場合、アセットの変更時に Desk が自動で再読み込みされます
ライブリロードを有効にする
# Via config
bench set-config -g live_reload true

# Via environment variable
export LIVE_RELOAD=1
開発ビルドと本番ビルド
機能開発(bench build)本番(bench build --production)
圧縮いいえはい
ソースマップはいいいえ
バンドルサイズ大きい最適化済み
ビルド速度高速低速

Frappe UI(Vue.js)のカスタムページ[v15 以降]

Vue ページのセットアップ
// myapp/public/js/mypage.bundle.js
import { createApp } from "vue";
import { FrappeUI } from "frappe-ui";
import App from "./App.vue";

const app = createApp(App);
app.use(FrappeUI);
app.mount("#myapp-page");
ページの登録
# Create a Page DocType or use www/ for web pages
# The bundle loads via hooks.py or include_script()
npm の依存関係
# Install from app directory
cd apps/myapp
yarn add vue frappe-ui dayjs

ビルド時に、esbuild が node_modules/ から依存関係を解決します。


よくあるビルドエラーと解決方法

エラー:「Could not resolve module」
ERROR: Could not resolve "some-package"

解決方法:不足している npm パッケージをインストールします。

cd apps/myapp && yarn add some-package
エラー:「No bundle entry points found」

解決方法:ファイルが *.bundle.* の命名規則に従い、public/ ディレクトリに配置されていることを確認します。

エラー:デプロイ後にアセットが古いままになる

解決方法:キャッシュをクリアして強制的に再ビルドします。

bench build --force
bench clear-cache
エラー:CSS が更新されない

解決方法:SCSS ファイルが正しくインポートされていること、およびエントリーポイントの名前に .bundle. が含まれていることを確認します。

bench build --app myapp --force
エラー:v15 で「build.json」が無視される

解決方法:*.bundle.* エントリーポイントに移行します。build.json は v14 専用の機能です。


本番環境向けのアセット最適化

デプロイ前のチェックリスト
  1. 本番フラグを指定してビルドする:bench build --production
  2. バンドルサイズを確認する:assets/dist/ で予想外に大きなファイルがないか確認します
  3. 遅延読み込みを使用する:あまり使用されない機能を個別のバンドルに分割し、frappe.require() で読み込みます
  4. フックのインクルードを最小限にする:app_include_js/css には必須のアセットのみを含めます
  5. CSS 変数を使用する:スタイルの重複を避け、Frappe に組み込まれている CSS カスタムプロパティを活用します
バンドル分割の方針
public/
├── js/
│   ├── myapp.bundle.js          # Core — loaded on every page via hooks
│   ├── report-widget.bundle.js  # Lazy — loaded only on report pages
│   └── chart-tools.bundle.js    # Lazy — loaded only when charts needed
└── css/
    ├── myapp.bundle.scss        # Core — loaded on every page via hooks
    └── print.bundle.scss        # Lazy — loaded only for print views

バージョンごとの差異

機能v14v15+
ビルドシステムbuild.jsonesbuild
エントリーポイントの規則JSON で定義*.bundle.* を自動検出
TypeScript のサポートなしあり
Vue SFC のサポートなしあり
SCSS のコンパイルビルドパイプライン経由esbuild 経由
ウォッチモードbench watchbench watch(高速)
ライブリロード手動自動(設定可能)
ソースマップ限定的完全サポート
ツリーシェイキングなしあり
npm のインポート手動でのバンドルが必要ES6 のインポートを直接使用

参考ファイル

ファイル内容
examples.mdビルド設定の完全な例
anti-patterns.mdよくあるビルド上の誤りと解決方法

コメント