2019年もおわるのにまだ Gulp を使って WordPress のモダンな開発環境を考えてみる

# 🎄🎄🎄皆さんメリークリスマス！！！！！！！！！！！！！！！🎄🎄🎄

さくらインターネットで思い出したのですが、ボクは石黒正数の『外天楼』に出てくる桜場冴子が大好きです。

関係ないですが、今日（投稿日前日の定時１５分前）もう時間もないので書きながらこのネタを考えています。

そう言えば最近さくらインターネットの社内では WordPress を社内用に建てる案件が増えているのですが、ローカルで立てるのに昔は LAMP 環境を自分のローカルPCに頑張って作ったりしませんでしたか？

かく言うボクも頑張って MySQL やら PHP やら apache やらをインストールして WordPress をインストールしてみたいなことをしていたのですが、これがハイパーめんどくさいので最近は Docker をつかってローカル開発環境を作るようにしています。

docker-compose を使えばもう一発ですね。これもう半分革命だろ・・・

```yml:docker-compose.yml

version: "3.3"

services:
    db:
        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
        build: .
        ports:
            - "8000:80"
        restart: always
        environment:
            WORDPRESS_DB_HOST: db:3306
            WORDPRESS_DB_USER: wordpress
            WORDPRESS_DB_PASSWORD: wordpress
            WORDPRESS_DEBUG: "true"
        volumes:
            - ./config/php.ini:/usr/local/etc/php/conf.d/php.ini
            - ./src/themes/:/var/www/html/wp-content/themes/:cached
            - ./src/uploads/:/var/www/html/wp-content/uploads/:cached

volumes:
    db_data:
```

たったこれだけで WordPress の環境が手に入る！！！！！！！！すごい！！！小学生並みの感想しか出てこない。ヤバい。渋い。php.ini なんかは適当に設定を変えたいとき用にマウントするなりすればいいし、こんなに楽なことがあっていんですか？？？？！！！！

いいんです！！！！！！！！！！！！！！！！！！！！！！！！これだけでもう WordPress の環境が立ち上がる！！！

```bash
$ docker-compose up
```

`localhost:8000` で WordPress のインストール画面が出ましたか！でましたか！！！よかった！

じゃあ細かい話は置いといて、ざっくり directory 構成を見てみますか！！！！

```bash
$ tree .                                                                                                                   .
├── Dockerfile
├── README.md
├── build.sh
├── config
│   └── php.ini
├── docker-compose.yml
├── gulpfile.js
├── package-lock.json
├── package.json
├── prod.Dockerfile
├── src
│   ├── themes
│   │   ├── foo
│   │   │   ├── 404.php
│   │   │   ├── archive.php
│   │   │   ├── assets
│   │   │   │   ├── css
│   │   │   │   │   ├── _base.scss
│   │   │   │   │   ├── _variables.scss
│   │   │   │   │   ├── _wordpress-core.scss
│   │   │   │   │   ├── lib
│   │   │   │   │   │   └── normalize.css
│   │   │   │   │   └── style.scss
│   │   │   │   ├── img
│   │   │   │   │   ├── common
│   │   │   │   │   │   └── logo.png
│   │   │   │   │   └── icons
│   │   │   │   │       ├── sakura_logo.ico
│   │   │   │   │       ├── sakura_logo.png
│   │   │   │   │       ├── sakura_logo_16.png
│   │   │   │   │       └── sakura_logo_32.png
│   │   │   │   └── js
│   │   │   │       ├── lib
│   │   │   │       │   ├── axios.min.js
│   │   │   │       │   └── vue.min.js
│   │   │   │       └── main.js
│   │   │   ├── author.php
│   │   │   ├── category.php
│   │   │   ├── comments.php
│   │   │   ├── components
│   │   │   │   ├── description.php
│   │   │   │   ├── gtm_noscript.php
│   │   │   │   ├── gtm_script.php
│   │   │   │   └── title.php
│   │   │   ├── footer.php
│   │   │   ├── functions.php
│   │   │   ├── header.php
│   │   │   ├── home.php
│   │   │   ├── index.php
│   │   │   ├── loop.php
│   │   │   ├── page.php
│   │   │   ├── screenshot.png
│   │   │   ├── search.php
│   │   │   ├── sidebar.php
│   │   │   ├── single.php
│   │   │   └── tag.php
│   │   └── index.php
│   └── uploads
│       └── 2019
│           └── 12
└── version_incrementer.sh

```

今すごい適当にテーマを作ってみたのですがこんな感じで謎のファイルがたくさんありますね！でも安心してください。**テーマの話は一切しません。一切しません！**だいたいビルドに関するはなししかしないのですからね！！！だから無視して大丈夫です。必要なことは今から数分で説明します。みなさんも数分でよんでください。

一点、`style.scss` の中で、下記の通り他の scssファイルを `@import` している点にご注意ください。この `style.scss`、後で重要になってくるので注意してね。

```scss:style.scss
/*
  Theme Name: さくらのてんぷら🍴
  Theme URI: https://example.com
  Description: さくらのテンプレート
  Version: 1.0.0
  Author: Saeko Sakuraba
*/

@import "variables";
@import "base";
```

さてまず `docker-compose.yml` でビルドに使う `Dockerfile` を用意します。ルートディレクトリにありますね。なかったら創ろう！！！創造していこう！！！！スクラップアンドスクラップ！！！！！！！！！

```Dockerfile:Dockerfile
FROM wordpress:latest

RUN apt-get update
RUN apt-get -y install wget unzip

WORKDIR /tmp/wp-plugins
# 使いたいプラグインは適当に定義する
RUN wget https://downloads.wordpress.org/plugin/wordpress-importer.0.6.4.zip

RUN unzip './*.zip' -d /usr/src/wordpress/wp-content/plugins

RUN apt-get clean
RUN rm -rf /tmp/*

RUN chown -R www-data:www-data /usr/src/wordpress/wp-content

WORKDIR /var/www/html
```

これで好き放題プラグインを入れることが出来ますね。もちろん wp-cli を使ってもいいよチョット面倒だけど便利だしおすすめ。今日は時間がないので諦めます。

さて、そろそろなぜもうすぐ 2019年も終わりになるのに gulp を使っているかを説明せねばなるまい！！我々の目的は WordPress 開発でも scss や js で最新のシンタックスが使いたい！！ でも WordPress をラップしてトランスパイルするオレオレシステムなんてまっぴらごめんだし、WordPress は WordPress、js や scss は別レーンでなんとかして WordPress の themeファイルと融合させたい！これが我々の目的です！！

そして回りくどい説明は省く！！なぜこの目的達成のために gulp を今更選択したのか!!!！**理由は他のモダンなモジュールバンドラなにがしよりも、やりたいことに対して近道だったからです！** 
当初 parcel で試すも小回りがきかず（理由省略。時間があれば後日） webpack はやりたいことに対してオーバーキルだった。そこで原点に立ち戻り gulp を使うと gulp がちょうどよく動いた！！我々は gulp によって勝利したのだ！！！！！！！バンジャーイ！!

では肝心の gulp の設定ファイルを見てみましょう！最近の gulp はシンタックスも素晴らしく簡潔です。

```js:gulpfile.js
'use strict'

const { src, dest, parallel, watch } = require('gulp')
const sass = require('gulp-sass')
const postcss = require('gulp-postcss')
const autoprefixer = require('autoprefixer')

function sassTask() {
  return src('./src/themes/foo/assets/css/**/*.scss')
    .pipe(sass({
      outputStyle: 'expanded'
    }))
    .pipe(postcss([ autoprefixer() ]))
    .pipe(dest('./src/themes/foo/'))
}

function watchStyle() {
  watch('./src/themes/foo/assets/css/**/*.scss', sassTask)
}

exports.watch = watchStyle
exports.default = parallel(sassTask)
```

ああああーこれで `npm run watch` するだけで docker上の WordPress に scss で書いたファイルが `style.css` として foo という theme に書き出される！！！！やりたいことはこれだけ、必要十分ではないか！！でも gulp4 は正直使ったことなかったし、なにもわからんかったから調べました！学習は大事だね :heart: 

じゃあこの `gulpfile.js` を動かすための `package.json` を見てみようかな。

```json:package.json
{
  "name": "foo",
  "version": "1.0.0",
  "description": "さくらのてんぷら",
  "main": "",
  "scripts": {
    "watch": "gulp watch",
    "build": "gulp",
    "dev": "npm run watch && docker-compose up"
  },
  "author": "Saeko Sakuraba",
  "devDependencies": {
    "autoprefixer": "^9.6.1",
    "gulp": "^4.0.2",
    "gulp-postcss": "^8.0.0",
    "gulp-sass": "^4.0.2",
    "stylelint": "^9.9.0",
    "stylelint-config-recommended-scss": "^3.2.0",
    "stylelint-scss": "^3.4.0"
  }
}
```

それじゃあ node_modules をインストールして早速トランスパイルができるようにしてみましょう。 node.js は v10.3.0 で試してますが動かなかったらごめんなさい。

```bash
$ npm install
$ npm run watch
```

これで gulp が scssファイルの変更を感知して `style.css` を theme フォルダに書き出してくれるはずです。あとは `docker-compose up` してあげれば docker と gulp がそれぞれ別ポートで起動してくれるはずです。

```bash
$ docker-compose up
```

※ そもそも Docker が動いていない人はピンチだぞ :heart: 

docker-compose と gulp を同時に起動したければ `npm run dev` を実行すれば docker と gulp が同時に起動して頑張ってくれるはずですね！みんなは頑張りすぎると体によくないゾ😘

```bash
$ npm run dev
```

そうそう、 今回は気分で stylelint もあるんだね :heart: じゃあこの設定も見ておこう。これは正直好みだから詳細は割愛！！！！

```json:.stylelintrc
{
  "extends": "stylelint-config-recommended-scss",
  "rules": {
    "color-hex-length": "long",
    "block-no-empty": null
  }
}
```

仕上げに、 `.gitignore` でバージョン管理したくないファイルを定義しておきましょう。gulp でトランスパイルされるはずの `style.css` は除外がいいですね。

```.gitignore:.gitignore
node_modules/

src/themes/foo/style.css
src/uploads/
```

CI でいろいろやらない場合にはリリース前に単に以下のコマンドで `style.css` を `src/themes/foo` フォルダに書き出せばOK！

```bash
$ npm run build
```

### CI 連携について

つぎに　`prod.Dockerfile` と `build.sh` . これはもう CI 用だから、 CI を使わない方は無視してよいです。何らかの CI 上で動く docker で `prod.Dockerfile` を使って docker build して scss とか js とかを npm でビルドしてトランスパイルされたファイルを theme に吐き出すようにしているんですね。ヤバイ！！

```Dockerfile:prod.Dockerfile
FROM node:10.13-alpine

WORKDIR /home/node

RUN apk add --no-cache git

COPY . /home/node

RUN npm ci
RUN npm run build
```

```bash:build.sh
#!/bin/bash

set -eu

DOCKER_TAG=foo_build

docker build -t ${DOCKER_TAG} \
  -f ./prod.Dockerfile .
docker run --name build_application ${DOCKER_TAG}
docker cp build_application:/home/node/src/themes/foo/style.css "$(dirname $0)"/src/themes/foo/
docker rm build_application
docker rmi ${DOCKER_TAG}
```

最後に。また CI の話になっちゃうんですが、WordPress の theme のバージョン情報書き換えるのってめんどくさくないですか？？ `style.css` の上部に書かれている `version` の値が使われるんですけど、毎回更新してもそのバージョン変更するの忘れませんか？むしろコード管理上変更しない可能性すらありますよね。

わざわざ `style.css` の値を書き換えるの面倒ですよね？？？？？？ボクは死ぬほど面倒です。

ということで CI でビルドが成功したら勝手にこのシェルスクリプトを実行して、 `package.json` と `style.scss` のバージョンを上げるようにしちゃいましょう。最終的に `style.scss` は foo という theme の `style.css` にトランスパイルされるので、ファイル上部のパッチバージョン情報が更新されることになるんだね！便利！！ざっくり書いたけど本番運用のときにはもう少し丁寧にマッチ判定したほうがいいかもですね！

Special Thanks kimura2！！
 
```bash:version_incrementer.sh
#!/bin/bash

declare -r PACKAGE_JSON="package.json"
declare -r THEME_SETTINGS_CONF="src/themes/foo/assets/css/style.scss"

CURRENT_VERSION=$(grep '"version":' ${PACKAGE_JSON} | cut -d'"' -f4)

a=( ${CURRENT_VERSION//./ } )
((a[2]++))
NEXT_VERSION="${a[0]}.${a[1]}.${a[2]}"

# package.json と style.scss にNEXT_VERSIONを書き込み
sed -i -e "1,/${CURRENT_VERSION}/s/${CURRENT_VERSION}/${NEXT_VERSION}/" ${PACKAGE_JSON}
sed -i -e "1,/${CURRENT_VERSION}/s/${CURRENT_VERSION}/${NEXT_VERSION}/" ${THEME_SETTINGS_CONF}

# gitにpush
git add "${PACKAGE_JSON}"
git add "${THEME_SETTINGS_CONF}"
git commit -m "bump to ${NEXT_VERSION}"
git push origin HEAD:master
```

## まとめ
docker でローカル開発ができるし CI と絡めればさらにバージョンアップや自動デプロイも簡単にできちゃうね！！ WordPress の更新で悩んでる人はおすすめです！！！

桜場冴子、桜場冴子をよろしくお願いいたします!!!!!!!
おわり