ベースがLaravelで作られたサイトに、WordPressでブログ機能を追加したい。これはよくある話です。
さらにサイトとブログをシームレスにしたい、つまり同一の外観(同じサイト)に見せたいこともたまにあります。
そんな時どうするかと言えば
- 既存サイトのヘッダー・フッターのHTMLをコピー
- Laravel(Vite)で作られたCSSをWordPressからも読み込む
……というのが、良くも悪くもてっとり早い方法です。別システムですからね。
そんな時、Laravel側の更新(build)が絡むとブログのデザインが崩れてしまう、という問題が発生します。
本ページでは、この問題の対策方法について考えてみたいと思います。これが最善かはわかりませんが、一例として参考になれば幸いです。
非エンジニアのWordPress開発者の方もコピペで可能です。
問題が起こる方法をおさらい
まずは、問題が発生する可能性がある方法をおさらいしてみましょう。
(WPの)header.phpからLaravelのCSSを読み込む
Laravelで作られたサイトのHTMLソースを表示させ、ヘッダー部分からCSS等必要な箇所をWordPressのテーマのheader.php
に貼り付けます。
以下の例では、7-8行目で読み込んでいます。※7行目は無くても動きます。
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="profile" href="http://gmpg.org/xfn/11">
<link rel="preload" as="style" href="/build/assets/app-xag6c3h5.css">
<link rel="stylesheet" href="/build/assets/app-xag6c3h5.css">
<link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>">
<?php if ( is_singular() && pings_open( get_queried_object() ) ) : ?>
<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>">
<?php endif; ?>
<?php wp_head(); ?>
</head>
もちろんheader.php
に書かずとも、functions.php
からフックで読ませても良いと思います。
残りのHTMLを貼り付ける
後はfooter.php
やsidebar.php
など含め、サイトの共通部分(グローバルナビゲーションやフッター等)のHTMLを適所に貼り付けます。
これが最も簡単で安直な方法だと思います。
問題
この方法では、まるっと貼り付けただけで機能するので楽です。しかしながら、Laravelの修正が絡むととたんに厄介になります。
問題無く動作していたところ、忘れた頃に「ブログのデザインだけ崩れてるよ!」という連絡が入ることになるかもしれません。
一時的に問題無くとも、いつか冷や汗をかく可能性があるのがこの実装方法です。
こういう連絡はドキっとして嫌なものです。
何が悪い?
Laravel(Vite)でbuildすると、CSSのファイル名が変わってしまうからです。
こういうやつです→app-xag6c3h5.css
つまり最新のCSSを参照することができなくなるため、ブログ部分だけデザインの崩れが発生することがあります。
これはLaravel(Vite)がキャッシュを確実にクリアするためにしてくれているから(たぶん)。つまりご厚意でやってくれているのです。
その都度WordPressのheader.php(またはfunctions.php)を変更するのは超面倒臭い……。
ということで考えました。
manifest.jsonの情報からCSSを読む
どうにかならいかな、と何も検索せずに自分の頭で考えましたが、1つの方法を思いつきました。そういえばmanifest.json
に、CSSの情報載ってるやん!と。
manifest.jsonの内容
public/build/manifest.json
には、Viteでbuildした情報が載っています。以下の様に、12行目にありますね。これを取得すれば良さそうです。
// ~省略
"public/img/example.jpg": {
"file": "assets/example.jpg",
"src": "public/img/example.jpg"
},
"resources/js/app.js": {
"file": "assets/app-ce55534219.js",
"isEntry": true,
"src": "resources/js/app.js"
},
"resources/sass/app.scss": {
"file": "assets/app-abcd2e93fg.css",
"isEntry": true,
"src": "resources/sass/app.scss"
}
}
読み込む
PHPにはJSONを読み込むjson_decode()
という便利な関数があります。
以下の様にWordPressのテーマのfunctions.php
に記述すれば、いとも簡単にmanifest.json
を読み込めます。なんで思いつかなかったんだろうというほど、あっけないです。
function load_manifest_css() {
// マニフェストファイルのパスを指定
$manifest_path = realpath(__DIR__ . '/../../../../') .'/build/manifest.json';
if(file_exists($manifest_path)) {
$manifest = json_decode(file_get_contents($manifest_path), true);
$app_css = isset($manifest['resources/sass/app.scss']['file']) ? $manifest['resources/sass/app.scss']['file'] : '';
if($app_css) {
wp_enqueue_style('app-css', get_template_directory_uri() . '/build/' . $app_css);
}
}
}
add_action('wp_enqueue_scripts', 'load_manifest_css');
一応、file_exists
していますが、このCSSが無いと致命的な場合、あえて判定しない方が処理速度的には良さそうです。
これだけで解決しました!
まとめ
ウェブサイトとブログを同じデザインにする……ということは、たまにあります。
通常のHTMLサイトなら、コピペで済ませてしまっても問題になることはそう多くありません。しかしLaravelを使用するなら、こういった対策が重要だなと改めて思いました。
本記事により、冷や汗を書く人が一人でも減れば幸いです。
コメント