【Gulp4 + Docker】WordPressテーマ制作用の最強ボイラープレート

こんにちは!
最近ヒゲを生やすのにハマった中谷です。
今回業務の中でGulpを使用する機会があったのでWordPressテーマ制作に役立つ便利なボイラープレートをGulp4とDockerで作りました。
ボイラープレートの設定と簡単な使用方法まで解説していきます!
(PCはM1 Macを使用しています)
最終目標
今回ボイラープレートを用意する上で必要になる条件をまとめました。
- ejsテンプレートでパーツ分けしhtmlを効率よく制作できる
- scssを使用できる
- 画像を圧縮できる
- 制作ファイルとテーマファイルのコピーの手間を無くす
- ローカルを更新したらローカルサーバーが自動で更新される
- ローカルでWordPressの表示確認ができる
※コードの圧縮やトランスパイルは今回必要ないので入れていませんが、設定をいじれば簡単に追加可能です。
動作環境
node | 16.15.0 |
gulp | 4.0.2 |
Gulpの下準備
まずターミナルでnpm initを叩きpackage.jsonを作成します。
npm init
package.jsonにこちらを挿入します。
{
// 以下を挿入
"devDependencies": {
"browser-sync": "^2.27.10",
"del": "^6.1.1",
"gulp": "^4.0.2",
"gulp-changed": "^4.0.3",
"gulp-dart-sass": "^1.1.0",
"gulp-ejs": "^5.1.0",
"gulp-html-beautify": "^1.0.1",
"gulp-imagemin": "^7.1.0",
"gulp-plumber": "^1.2.1",
"gulp-rename": "^2.0.0",
"imagemin-mozjpeg": "^9.0.0",
"imagemin-pngquant": "^9.0.2"
}
}
※2023/10/12追記・・・gulp-sassはインストールできなくなったためgulp-dart-sassに変更しました。
ターミナルでこちらのコマンドを叩き必要なパッケージをインストールします。
npm install
gulpfile.jsを作成し以下を記入します。
(const themeName = ‘test’ はテーマ名に書き換えてください)
"use strict"
// 出力するWPテーマ名を記入
const themeName = 'test'
// gulp関連のモジュールを読み込む
const bs = require("browser-sync")
const { src, dest, series, parallel, watch } = require("gulp")
const sass = require("gulp-dart-sass")
const ejs = require("gulp-ejs")
const htmlbeautify = require("gulp-html-beautify")
const rename = require("gulp-rename")
const plumber = require("gulp-plumber")
const imageMin = require('gulp-imagemin')
const mozjpeg = require('imagemin-mozjpeg')
const pngquant = require('imagemin-pngquant')
const changed = require('gulp-changed')
const del = require("del")
// BrowserSyncの初期化とサーバーの設定
function bsInit(done) {
bs.init({
server: {
baseDir: "app/product/"
},
notify: false,
})
done()
}
// BrowserSyncでリロード
function bsReload(done) {
bs.reload()
done()
}
// scssをコンパイルして出力
function scssCompile(done) {
src("app/src/sass/**/*.scss")
.pipe(
sass({
outputStyle: "expanded"
})
.on("error", sass.logError)
)
.pipe(dest("app/product/assets/css"))
.pipe(dest(`themes/${themeName}/assets/css`))
done()
}
// ejsをコンパイルしてhtmlに変換
function ejsCompile(done) {
src(["app/src/ejs/**/*.ejs", "!" + "app/src/ejs/**/_*.ejs"])
.pipe(plumber())
.pipe(ejs())
.pipe(rename({ extname: ".html" }))
.pipe(htmlbeautify({
// インデント幅2文字
indent_size: 2
}))
.pipe(dest("app/product"))
done()
}
// 画像を圧縮して出力
function imageCompile(done) {
src('app/product/assets/image/**/*')
.pipe(changed(`themes/${themeName}/assets/image`))
.pipe(
imageMin([
pngquant({
quality: [.80, .90],
speed: 1
}),
mozjpeg({ quality: 80 }),
imageMin.svgo(),
imageMin.optipng(),
imageMin.gifsicle({ optimizationLevel: 3 }),
])
)
.pipe(dest(`themes/${themeName}/assets/image`))
done()
}
// jsファイルをテーマへコピー
function jsPipe(done) {
src('app/product/assets/js/**/*.js')
.pipe(plumber())
.pipe(dest(`themes/${themeName}/assets/js`))
done()
}
// アセットフォルダをテーマへコピー(画像は非圧縮)
function assetsPipe(done) {
src('app/product/assets/**')
.pipe(plumber())
.pipe(dest(`themes/${themeName}/assets`))
done()
}
// アセットフォルダを削除
function assetsDel(done) {
del(`themes/${themeName}/assets`)
done()
}
// ファイルの変更を監視してタスクを実行
function watchTask(done) {
watch(["app/src/sass/**/*.scss"], series(scssCompile))
watch(["app/src/ejs/**/*.ejs"], series(ejsCompile))
watch(["app/product/assets/image/**/*.+(jpg|jpeg|png|gif|svg)"], series(imageCompile))
watch(["app/product/assets/js/**/*.js"], series(jsPipe))
watch(["app/product/**"], series(bsReload))
}
// gulpのデフォルトタスク
exports.default = series(bsInit, bsReload, watchTask)
// 個別のタスク
exports.sass = series(scssCompile)
exports.ejs = series(ejsCompile)
exports.imagemin = series(imageCompile)
exports.js = series(jsPipe)
exports.assets = series(assetsPipe)
exports.assetsDel = series(assetsDel)
gulpファイルの準備はこれで完了です。
gulpfileの書き方の秘密
ちなみにgulpfile.jsは一見複雑そうですが仕組みとしては単純です。
"use strict"
// 出力するWPテーマ名を記入
const themeName = 'test'
// gulpで使うことのできるメソッドを呼び出す
const { src, dest, series, parallel, watch } = require("gulp")
function jsPipe(done) {
// app/product/assets/js/フォルダ配下のすべての「js」ファイルをコンパイル元とする
src('app/product/assets/js/**/*.js')
// テーマの中へ出力する(この場合は処理がないのでただのコピーとなる)
.pipe(dest(`themes/${themeName}/assets/js`))
// 関数を終了する
done()
}
// npx gulp jsでjsPipeを実行
exports.js = series(jsPipe)
.pipe()を使えば処理をこのようにどんどん繋げていくことができます。
src(["app/src/ejs/**/*.ejs", "!" + "app/src/ejs/**/_*.ejs"])
// エラーによるタスク停止を防止
.pipe(plumber())
// ejsコンパイル
.pipe(ejs())
// ejs拡張子をhtmlへ変更
.pipe(rename({ extname: ".html" }))
// 出力されたhtmlを整形する
.pipe(htmlbeautify({
// インデント幅2文字
indent_size: 2
}))
// app/productフォルダへ出力
.pipe(dest("app/product"))
またwatch()を使えばファイルの監視も可能です。
function watchTask(done) {
// app/src/sass/フォルダのscssが更新されたらscssCompileを実行する
watch(["app/src/sass/**/*.scss"], series(scssCompile))
}
Gulpを起動する
以下のコマンドを叩けばローカルサーバー http://localhost:3000/ が自動的に起動し、ファイルの変更があると自動でコンパイルが行われます。
npx gulp
※現段階だとhtmlファイルがないので「Cannot GET /」しか表示されません
また以下のコマンドを叩けば単独でそれぞれのコンパイル機能を実現できます。
npx gulp sass
:scss ファイル の変換npx gulp ejs
:ejs ファイル の変換npx gulp imagemin
:画像の圧縮npx gulp js
:js ファイルをテーマへコピーnpx gulp assets
:assets フォルダをテーマへコピーnpx gulp assetsDel
:テーマの assets フォルダを削除
テストファイルの作成
今回は以下のように必要なフォルダとファイルを作成します。
.
└── app/
└── src
├── ejs
│ ├── about.ejs
│ ├── common
│ │ ├── _footer.ejs
│ │ └── _header.ejs
│ └── index.ejs
└── sass
└── style.scss
せっかくなので、ファイル編集と同時にコンパイルされるのを確認するため「npx gulp」を叩いてローカルサーバーが起動した状態で作成していきましょう。
ejsファイルの作成
app/src/ejs/common/_header.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,user-scalable=yes" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="description" content="<%= description %>">
<title><%= title %></title>
<link href="./assets/css/style.css" rel="stylesheet" />
</head>
<body>
<header class="c-header">
<h1 class="c-header_title">共通タイトル</h1>
<%_ if (pageId === 'home'){ -%>
<p class="c-header_subTitle">トップページのみ表示されるタイトル</p>
<%_ } else { -%>
<p class="c-header_subTitle"><%= title %></p>
<%_ } -%>
</header>
app/src/ejs/common/_footer.ejs
<footer class="c-footer">
<p class="c-footer_text">©test.inc</p>
</footer>
</body>
</html>
app/src/ejs/index.ejs
<%
let title = 'トップページ';
let description = 'トップページのディスクリプション';
let pageId = 'home';
%>
<%- include('./common/_header', { title, description, pageId }) %>
<main class="topMain c-main">
<section class="topContents">
<div class="topContents_wrap">
<h2 class="topContents_title">トップページ</h2>
<p class="topContents_text">テキスト</p>
<a href="about.html" class="c-button">会社概要ページへ<span></span></a>
</div>
</section>
</main>
<%- include('./common/_footer') %>
app/src/ejs/about.ejs
<%
let title = '会社概要';
let description = '会社概要ページのディスクリプション';
let pageId = 'about';
%>
<%- include('./common/_header', { title, description, pageId }) %>
<main class="aboutMain c-main">
<section class="aboutContents">
<div class="aboutContents_wrap">
<h2 class="aboutContents_title">会社について</h2>
<p class="aboutContents_text">テキスト</p>
<a href="./" class="c-button">会社概要ページへ<span></span></a>
</div>
</section>
</main>
<%- include('./common/_footer') %>
この時点でapp/productフォルダにindex.htmlとabout.htmlが自動で出力されたと思います。
header.ejsではページに設定した変数を用いてタイトル・ディスクリプション設定や、if文を用いて「トップページのみ表示されるタイトル」を表示したりしています。
EJSは条件分岐やPHPのようにhtmlをパーツ分けできるためマスターするとサイト制作でとても便利です。
使い方はこちらを参考にすると分かりやすいです。
scssファイルの用意
テスト用に簡単なscssを書きます。
app/src/sass/style.scss
// 色設定
$colorBlack: #222;
$colorWhite: #fff;
$colorGray: #888;
// 最大幅設定
@mixin inner {
width: 100%;
max-width: 1000px;
margin: auto;
}
body {
background: #efefef;
font-family: "游ゴシック体", "Yu Gothic", YuGothic, "ヒラギノ角ゴ Pro",
"Hiragino Kaku Gothic Pro", "メイリオ", Meiryo, "MS Pゴシック", "MS PGothic",
sans-serif;
}
.c {
&-header {
@include inner;
border-bottom: solid 1px $colorGray;
&_title {
color: $colorBlack;
}
&_subTitle {
color: $colorGray;
}
}
&-footer {
@include inner;
border-top: solid 1px $colorGray;
margin-top: 60px;
}
&-main {
@include inner;
margin-top: 60px;
}
&-button {
display: block;
position: relative;
margin-top: 20px;
background: $colorWhite;
color: $colorBlack;
text-decoration: none;
width: 200px;
padding: 20px;
border-radius: 50px;
font-size: 14px;
text-align: center;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
span {
content: '';
width: 5px;
height: 5px;
border-top: 1px solid $colorBlack;
border-right: 1px solid $colorBlack;
transform: rotate(45deg) translateY(-50%);
position: absolute;
top: 50%;
right: 20px;
}
}
}
これでapp/product/assets/css/style.cssへ自動的にコンパイルされました。
scssは入れ子形式でcssを記述でき、コンパイルすることで通常のcssを出力できるとても便利な技術です。
こちらが書き方の参考になります。
http://localhost:3000/ をリロードまたはアクセスするとテストサイトができているのが確認できます。

ローカルでWordPressを立ち上げる
さて、WordPressを立ち上げるための設定を行います。
まず公式サイトからDocker Desktopをダウンロード・インストールしておきます。
Docker Desktopを起動したら準備ができました。

docker-composeの準備
ルートフォルダにdocker-compose.ymlを作成します。
※今回はテーマの作成のためvolumesはテーマフォルダとしています。
version: "3"
services:
db:
platform: linux/x86_64
image: mysql:5.7
volumes:
- ./db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- ./themes:/var/www/html/wp-content/themes
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
volumes:
db_data:
docker-composeを実行します。
docker-compose up -d
http://localhost:8000/ へアクセスするとWordPressの設定画面が現れるので、初期設定を行います。

http://localhost:8000/ のトップページがちゃんと表示されていればWordPressの準備は完了です。
※ちなみにDockerコンテナを停止するにはこちらを叩きます。
docker-compose down
WordPressテーマの作成
いよいよテーマを作成します。
既に自動的にthemes/test/フォルダが作成されていると思うのでこれを利用します。
(testはgulpfileで指定したテーマ名に変わります)
今回は最短工程でテーマを作るため、動作する最低限のファイルで制作します。
themesのフォルダ構成はこちら
└── themes
├── test
│ ├── assets
│ │ └── css
│ │ └── style.css
│ ├── footer.php
│ ├── header.php
│ ├── index.php
│ ├── page-about.php
│ └── style.css
(他のテーマは省略)
themes/test/header.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,user-scalable=yes" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title><?php bloginfo('name'); wp_title('|', true, 'left'); ?></title>
<link href="<?php echo get_template_directory_uri(); ?>/assets/css/style.css" rel="stylesheet" />
<?php wp_head(); ?>
</head>
<body>
<header class="c-header">
<h1 class="c-header_title">共通タイトル</h1>
<?php if ( is_home() && is_front_page() ) : ?>
<p class="c-header_subTitle">トップページのみ表示されるタイトル</p>
<?php else : ?>
<p class="c-header_subTitle"><?php the_title(); ?></p>
<?php endif; ?>
</header>
themes/test/footer.php
<footer class="c-footer">
<p class="c-footer_text">©test.inc</p>
</footer>
<?php wp_footer(); ?>
</body>
</html>
themes/test/index.php
<?php get_header(); ?>
<main class="topMain c-main">
<section class="topContents">
<div class="topContents_wrap">
<h2 class="topContents_title">トップページ</h2>
<p class="topContents_text">テキスト</p>
<a href="<?php echo esc_url( get_home_url() ); ?>/about" class="c-button">会社概要ページへ<span></span></a>
</div>
</section>
</main>
<?php get_footer(); ?>
themes/test/page-about.php
<?php get_header(); ?>
<main class="aboutMain c-main">
<section class="aboutContents">
<div class="aboutContents_wrap">
<h2 class="aboutContents_title">会社について</h2>
<p class="aboutContents_text">テキスト</p>
<a href="<?php echo esc_url( get_home_url() ); ?>" class="c-button">トップページへ<span></span></a>
</div>
</section>
</main>
<?php get_footer(); ?>
themes/test/style.css
@charset "utf-8";
/* CSS Document */
/*
Theme Name: testオリジナルテーマ
Description: testオリジナルテーマ
Version: 1.0
*/
※今回はディスクリプションは反映しませんので、必要な場合はAIOSEOプラグインなどを使用してください。
オリジナルテーマの適応
WordPress管理画面でサイドメニューの「外観」>「テーマ」を選び、testオリジナルテーマを有効化すればテーマが適応されます。

WordPressのページ作成
このままではaboutページが作成されていないため、WordPress管理画面でページを作成していきます。
サイドメニューで「固定ページ」>「新規追加」をクリック、タイトルを「home」として公開します。

左上の「W」マークを押して固定ページ一覧に戻り、「about」ページも同様に追加します。
日本語のタイトル表記を設定するため、固定ページ一覧のaboutのクイック編集をクリックしてタイトルを「会社概要」とします。


homeも「トップページ」として編集します。

「設定」>「パーマリンク」をクリック、数字ベースを選択し保存します。

http://localhost:8000/ へアクセスすればトップページが表示され、「会社概要ページへ」ボタンをクリックすればaboutページへ推移できるようになりました!

※WordPressはファイル更新をしても自動リロードはされないので、手動でブラウザリロードして下さい。
その他の機能について
上の方で少し触れていますが、
画像を圧縮する機能や、js ファイルをテーマへコピーする機能などがあります。
画像圧縮機能
app/product/image へ画像を入れると themes/test/assets/image へ自動的に30%ほど圧縮されて出力されます。

jsコピー機能
app/product/assets/js にjsファイルを作成すると themes/test/assets/js へ自動的にデータがコピーされます。
まとめ
一通りgulpfileやDockerの設定方法からWordPressへの反映まで、使い方を一通り説明できました。
これでWordPress制作効率が爆速になること間違いなしです!
その他、詳しい内容はGitHubに書きました。
ご自由にご利用ください!