🙅♂️
WordPressの記事内に書いたJSを動かしたい←やめて
結論
「CMS上の記事にJavaScriptを書いて動かしたい」という要望には、エンジニアとしては“No”と答えるべき。
理由:
- 表示制御の責任が不明瞭になる
- セキュリティリスクが高すぎる(XSSなど)
- SPA構成では意図通りに動かない
- 保守性・再利用性・デバッグ性すべてが下がる
ユーザーの要望(よくあるパターン)
WordPressの記事中にJavaScript書いたら、ユーザーの操作に応じてアラートを出したいんだけど?
→ 構成によってはリロード時には動くが、SPA遷移時には動かない
→ セキュリティ・運用面でもやってはいけない
構成
- CMS(例:WordPress)でコンテンツ管理
- フロントエンドは静的サイトジェネレーター(例:Nuxt、Next)で構築
- 静的HTMLとしてビルド、CDN等でホスティング
- ページ遷移はクライアントサイドで処理される(SPA構成)
問題
- CMSの記事本文にJSを埋め込んでも動作しない
- ページリロード直後、URLを直接開いたときはJSが動く
- クライアントサイド遷移(SPA)時はJSが動かない
原因
- 静的HTMLに含まれる
<script>は初回ロード時のみ実行される - SPAのページ遷移はHTML差し替えのみで、JSは再評価されない
- DOM上にあっても、ブラウザは再実行しない
一時的な解決策(非推奨)
やろうと思えば、以下のようにフロント側でJSを無理やり実行させることはできる。
plugin例(Nuxt想定)
// plugins/embed-script.client.ts
export default defineNuxtPlugin(() => {
onNuxtReady(() => {
const scripts = document.querySelectorAll('[data-embedded-script]');
scripts.forEach((el) => {
try {
const code = el.textContent || '';
const fn = new Function(code);
fn();
} catch (e) {
console.error('Script execution error:', e);
}
});
});
});
CMS側のマークアップ例
<div>
<input id="sample-input" value="こんにちは" />
</div>
<div data-embedded-script>
const val = document.getElementById('sample-input')?.value;
if (val) alert(val);
</div>
※ evalやFunctionを使う時点でXSSリスクが高く、保守不能。おすすめしない
なぜやってはいけないのか
設計の問題
- 表示ロジックがCMSに混入し、責任が不明瞭になる
- 非エンジニアがJSを書き始めると品質が保証できない
- ロジックの再利用性や型安全性が消滅する
セキュリティの問題
- JSを自由に埋め込める構成はXSSの温床
- 悪意あるJSでユーザーのクッキーや入力情報を盗まれる
- CSPとの整合性が取れず、セキュリティポリシー導入が難しくなる
運用の問題
- 表示仕様の変更がCMS依存になり、移行や設計変更が困難に
- 自動テストでの動作保証ができない
- 障害調査時の責任分界が曖昧になる
正しい設計方針
- 表示に関わるJSはフロントエンド側が持つ
- CMSは構造化されたデータのみを提供する
- フロントがそのデータを解釈して描画・動作を制御する
例:CMSからの構造化データ
{
"type": "formEmbed",
"formId": "1234"
}
→ フロント側で "type": "formEmbed" を判定して該当するUIコンポーネントを描画
まとめ
- CMSにJSを書かせる構成は動作もセキュリティも保守性も破綻する
- 一時的に動かす手段はあっても、根本的に「やってはいけない設計」
- JSは常にフロント側が責任を持ち、CMSはデータ提供に徹するべき
Discussion