BLOG

ブログ

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

こんにちは!
最近ヒゲを生やすのにハマった中谷です。

今回業務の中でGulpを使用する機会があったのでWordPressテーマ制作に役立つ便利なボイラープレートをGulp4とDockerで作りました。

ボイラープレートの設定と簡単な使用方法まで解説していきます!
(PCはM1 Macを使用しています)

最終目標

今回ボイラープレートを用意する上で必要になる条件をまとめました。

  • ejsテンプレートでパーツ分けしhtmlを効率よく制作できる
  • scssを使用できる
  • 画像を圧縮できる
  • 制作ファイルとテーマファイルのコピーの手間を無くす
  • ローカルを更新したらローカルサーバーが自動で更新される
  • ローカルでWordPressの表示確認ができる

※コードの圧縮やトランスパイルは今回必要ないので入れていませんが、設定をいじれば簡単に追加可能です。

動作環境

node16.15.0
gulp4.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に書きました。
ご自由にご利用ください!

https://github.com/ShalCan/wp_boilerplate