Web制作会社や代行業者のWordPress開発業務は、常に競争率が高い分野です。複数の顧客に対してそれぞれプロジェクトを抱えている場合には、最大限の効率性と一貫性が求められます。

開発者としてどれほどスキルと経験を磨いても、開発テーマやプラグインのポートフォリオ全体を管理するには、ワークフローの効率化という点で継続的な努力が必要になります。そこで活用したいのが、wp-scriptsです。 wp-scriptsは、従来のWordPress開発業務に革命を起こす開発ツールキットです。

今回は、wp-scriptsの機能を取り上げ、ビルドプロセスのテクニックをご紹介します。コンパイルとバンドルの最適化、リンティング(コードの品質や一貫性を確認し、エラーや警告を特定して修正を促すプロセス)、ユニットテストなど、複数のWordPressプロジェクトを抱えるWeb制作会社に役立つ有益な情報を見ていきます。

ビルドプロセスの概念

wp-scriptsについて掘り下げる前に、まずはウェブ開発のビルドプロセスというより広義な概念を理解しましょう。ビルドプロセスは、ソースコードを本番環境で使用可能なアプリやウェブサイトに仕上げるための、一連の自動化されたタスクで構成されます。

この自動化により、以下のようなタスクが効率化されます。

  • 最新のJavaScriptをブラウザ互換のコードに変換(コンパイル)
  • CSSプリプロセッサ言語(Sassなど)を標準CSSに変換(トランスパイル)
  • JavaScript、CSS、メディアなどのアセットの最小化および最適化
  • リンター(linter)を実行して潜在的なエラーを検出し、コーディング標準を適用
  • より良いコード機能を保証するためのユニットテストの実行

上記は、あらゆる開発ワークフローにおいて自動化したいタスクですが、複数のプロジェクト(そしてチーム間)で一貫性を保つことができるため、Web制作会社にとっては特に重要です。

この一貫性を活かして、非常に複雑なプロジェクトでも効率的なサイクルで開発とデプロイを行い、すべてのプロジェクトを維持することが可能になります。またパフォーマンスの最適化により、エンドユーザーの全体的なエクスペリエンスも改善されます。

GulpGruntのようなツールを使って、または手動で独自のビルドプロセスを「寄せ集める」という、Web制作会社に見られる一般的なアプローチでは、メンテナンス業務の負担が膨れ上がることはもちろん、プロジェクト間の不整合につながる可能性があります。

WordPress開発のワークフローに革命を起こすwp-scripts

WordPressでは、ビルドプロセスはテーマとプラグイン開発を大きく効率化してくれます。最新のツールとプラクティスを使用しながら、同時にプラットフォームの互換性を確保することができます。

@wordpress/scriptsパッケージ(この記事ではwp-scripts)は、WordPressプロジェクトのビルドプロセスを簡素化するための設定ファイルとスクリプトのコレクションです。

プロジェクトで使用するスクリプトのためのwp-scriptsの一部
プロジェクトで使用するスクリプトのためのwp-scriptsの一部

ブロックエディターとサイトエディターに欠かせないこのパッケージは、Make WordPress Coreチームによって開発・保守管理されています。カスタムテーマやプラグインの開発にも使用可能です。

大規模なWordPress開発に取り組む場合は、wp-scriptsがワークフローの中心になります。wp-scriptsは単なるビルドツールではなく、高度な開発ワークフローの要件に沿った、最新のWordPressプロジェクト向けの包括的なソリューションです。

wp-scriptsの主な機能

モダンJavaScriptのプラクティスがWordPressのエコシステムに浸透するにつれ、それに対応するための標準ビルドツールが必要になります。wp-scriptsの形で統一されたビルドツールセットは、WordPress開発のエコシステム全体に利益をもたらします。

wp-scriptsには、WordPress開発を効率化する以下のような機能があります。

  • 設定不要なセットアップ─複雑なwebpackの設定なしで使い始めることができる
  • モダンJavaScriptのサポート─ES6のコードがブラウザ互換性のためにトランスパイルされ、正確性が高まる
  • 組み込みのCSS処理SassのようなCSSプリプロセッサを使用している場合はすぐにサポートを利用できる
  • コードレビューツールESLintとPrettier両方を統合し、一貫したコードスタイルと品質を実現
  • テストユーティリティパッケージ内でJestを使用できるため、ユニットテストや簡単な実行が可能
  • ホットリロード変更を本番環境で即座に変更内容が反映されることで開発作業が効率化される

wp-scriptsのこのような機能群は、複数のWordPressプロジェクトを管理するWeb制作会社にとって大きなメリットがあります。例えば、すべてのプロジェクトで開発環境を標準化し、新規プロジェクトにもビルドプロセスを複製することができます。ビルドツールの依存関係を一元化し、更新やセキュリティパッチの管理も簡素化されます。

全体としては、互換性の問題に関する心配が減り、セットアップにかかる時間が短縮され、適切でないビルドプロセスで発生する一般的なエラーの多くを排除することができます。

wp-scriptsと一般的なWordPress開発プロセスの比較

一般的なWordPress開発では、スクリプトやスタイルを手動でエンキューすることが多々あります。またVanilla JSjQueryを書いたり、サードパーティのビルドツールに頼ったり、ビルドプロセスが全くないこともあります。

wp-scriptsは対照的に、ほとんどすべての領域において、最新の統合されたアプローチを提供します。

一般的な開発 wp-scripts
JavaScript 通常はVanilla JSまたはjQuery ES6とReact
CSS 直接CSSを書くか基本的なプリプロセッサ SassとPostCSS処理
ビルドプロセス GulpまたはGruntを使用した手動または独自のセットアップ パッケージに統合されたwebpackを使用し設定不要
コード品質 手作業によるリンティング、またはコードエディターに統合された別のツール 組み込みのESLintとPrettier
ユニットテスト 通常は別のセットアップ(無視されなければ) 組み込みのJestテスト

wp-scriptsは異なるツールとの統合により、全体としてより柔軟性に優れています。例えば、PostCSSwebpackJestをセットアップする手間は省略できます。

wp-scriptsを組み込む開発環境のセットアップ方法

wp-scriptsを使うにはそれなりの要件がありますが、すでに使用している必要ツールがあるかもしれません。必要に応じて、Node.jsとnpmをローカルのWordPress開発環境とともにインストールしてください。DevKinstaDocker上で動作し、Kinstaのステージング環境と互換性があるため、おすすめのソリューションです。

DevKinstaのインターフェース
DevKinstaのインターフェース

WordPressブロックプラグインの開発にすでにcreate-blockパッケージを使用している場合は、wp-scriptsを他のアセットと一緒にインストールして、セットアップを開始することができます。

wp-scriptsでWordPressプロジェクトを立ち上げる

WordPressのwp-contentディレクトリ内で作業を行います。サブディレクトリは、作成するプロジェクトの種類によって異なります。テーマの場合はwp-content/themes、プラグインの場合はwp-content/pluginsです。

いずれにしても、プロジェクトフォルダには以下のファイルとディレクトリが含まれます。

  • package.json ファイル
  • buildディレクトリ
  • index.jsファイルを含むsrcディレクトリ

package.jsonファイルを作成するには、ターミナルまたはコマンドラインアプリを使用してプロジェクトディレクトリに移動します。npm initコマンドを実行すると、対話型のセットアッププロセスが行われ、エントリーポイントはbuild/index.jsになります。

npm initプロセスの一部を実行し、エントリーポイントの値を入力するプロンプトを表示
npm initプロセスの一部を実行し、エントリーポイントの値を入力するプロンプトを表示

続いて、wp-scriptsを開発依存としてインストールします。

npm install @wordpress/scripts --save-dev

自動生成されたディレクトリとファイル、node_modulespackage-lock.jsonも表示されます。いずれにしても、package.jsonファイル内の定義済みスクリプトを参照する必要があります。

"scripts": {
  "build": "wp-scripts build",
  "start": "wp-scripts start",
}

このファイルは、必要に応じてスクリプトを追加するために頻繁に参照することになります。

…

"lint:js": "wp-scripts lint-js",
"lint:css": "wp-scripts lint-style",
"lint:pkg-json": "wp-scripts lint-pkg-json",
"test": "wp-scripts test-unit-js"
…

また、ここでテーマやプラグインのアセットをエンキューし、変更を保存する必要があるかもしれません。

wp-scriptsでwebpackを使用する

wp-scriptsは、裏でアセットをバンドルするためにwebpackを使用しています。この設定を自分で行う必要はありませんが、その役割を理解することで、wp-scriptsをより効果的に活用することができます。webpackは、セットアップにおいて以下のような重要な役割を果たします。

  • JavaScriptモジュール間の依存関係を解決
  • モダンJavaScriptをブラウザ互換のコードにトランスパイル
  • スタイルの処理と最適化
  • ソースマップを生成してデバッグを簡素化
  • 本番環境ですぐに使えるように最小化されたバンドルを作成

wp-scripts内にすでにデフォルトのwebpack設定があり、ほぼすべてのWordPressプロジェクトでうまく機能しますが、場合によってはカスタム設定を作成する必要があるかもしれません。

Web制作会社向けの高度なwebpack設定

デフォルトのwebpack設定は、大体の開発プロジェクトに適用できますが、複雑なテーマ構造や独自のプラグインアーキテクチャを扱う際など、特定の要件に応じて設定を行う必要があることもあります。この場合は、プロジェクトルートにあるwebpack.config.js ファイルが便利です。

const defaultConfig = require("@wordpress/scripts/config/webpack.config");

const path = require('path');


module.exports = {
  ...defaultConfig,
  entry: {
    main: path.resolve(__dirname, 'src/js/main.js'),
    admin: path.resolve(__dirname, 'src/js/admin.js'),
    // 必要に応じてエントリーポイントを追加
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist'),
  },
  // ここにカスタムローダーやプラグインを追加
};

この設定は、複数のエントリーポイントを可能にし、WordPressの管理画面やフロントエンドの異なる部分に別々のスクリプトを必要とするテーマやプラグインに特に有用です。このようにデフォルトの設定を拡張して、wp-scriptsの利点を活かすことができます。

wp-scriptsの基本的な使い方

適切な開発環境、ファイルおよびフォルダ構造があれば、wp-scriptsを使い始めることができます。頻繁に使うことになる基本的なコアコマンドはいくつかあります。

startコマンドは、ファイルの変更を監視し、その場でアセットを再コンパイルし、開発を効率化するホットリロードを起動します。

npm run start

build/index.jsファイル内でコンパイルされたコードを最適化することはできませんが、開発サーバーを起動するために最初に使用します。

プロジェクトをデプロイする必要がある場合は、buildコマンドを使って本番ようにアセットをコンパイルすることができます。

npm run build

これを実行すると、JavaScriptのトランスパイル、SassとSCSSをCSSにコンパイル、アセットの最小化、ソースマップの生成などのタスクが処理されます。最後に、すべてがbuild/index.jsファイルに出力され、ビルドプロセスでは、キャッシュバスト用にbuild/index.asset.phpファイルも生成されます。

wp-scriptsパッケージには、高いコード品質を維持するためのlintコマンドもあります。

  • npm run lint:js:JavaScriptファイルのリンティング
  • npm run lint:css:CSSやSassファイルのリンティング
  • npm run lint:pkg-jsonpackage.jsonファイルを検証

ユニットテストの場合は、npm run testを呼び出すだけでJestを使ったテストが実行されます。

wp-scriptsのコアユーティリティ

基本的なビルドタスクには時間がかかり、一般的なコマンドには多くの自動化が必要になりますが、wp-scriptsには、WordPress開発の複雑な要件を満たす高度なユーティリティが用意されています。

  • 高度なコンパイル─設定が最適化されており、ECMAScript Modules(ESM)や Javascript XML(JSX)を含む最新のJavaScriptのトランスパイル、Sassのコンパイルが可能
  • 高度なバンドル─webpackのコード分割とTree shakingを活用して、アセットの配布を最適化できる
  • 包括的なリンティング─JavaScript、CSS、package.jsonファイル全体にコーディング標準を適用できる
  • 統合テスト─Jestを使用してユニットテストとカバレッジレポートを実行できる
  • 開発サーバー─ホットリロードで複数のプロジェクトにまたがる開発が効率化される

テーマやプラグインに関係なく、それぞれのデフォルト機能を拡張して、より柔軟なWordPress開発プロセスを確立できます。

JSXとモダンJavaScriptの扱い方

多くのWordPressプロジェクトでは、Reactコンポーネント、アロー関数、分割代入(デストラクチャリング)、async/awaitなど、モダンJavaScript要素を使用します。ブロックエディターのようなコアコードベースの側面もモダンJavaScriptによって構築されています。

しかし、ブラウザはこれらの高度な構文にデフォルトでは対応していないため、トランスパイルやコンパイルにはより多くの作業が必要になります。

JSXを使えば、JavaScriptの中にHTMLのようなコードを書くことができ、インターフェースやその他の要素がどのように見えるべきかを簡単に書けるようになります。これにより、可読性と保守性が向上するだけでなく、動的なユーザーインターフェース(UI)を作成するための強力なReactコンポーネントにアクセスすることができます。

wp-scriptsは、JavaScriptトランスコンパイラであるBabelを使用して、モダンJavaScriptとJSXをブラウザが理解できるコードに変換します。複雑で必要な設定をすべて処理してくれるため、コードの記述に専念できます。

これはsrc/index.js ファイルを通して活用します。wp-scriptsを使ってJSXとモダンJavaScriptを実装する簡単な例を見てみましょう。

import { render } from '@wordpress/element';

// JavaScriptの最新機能: アロー関数
const HelloWorld = () => {
    // JavaScriptの最新機能: テンプレートリテラル
    const greeting = `Hello, ${wp.data.select('core/editor').getCurrentPost().title}!`;    

    // JSX
    return (
        <div className="hello-world">
            <h1>{greeting}</h1>
            <p>これはWordPressのReactコンポーネントです</p>
        </div>
    );
};

// JavaScriptの最新機能: オプションの連鎖
const rootElement = document.getElementById('hello-world-root');
if (rootElement?.innerHTML) {
    render(<HelloWorld />, rootElement);
}

また、テーマのfunctions.phpファイル内、またはメインのプラグインファイル内でスクリプトをエンキューする必要があります。

function enqueue_hello_world_script() {
    wp_enqueue_script(
        'hello-world-script',
        get_template_directory_uri() . '/build/index.js',
        ['wp-element'],
        filemtime(get_template_directory() . '/build/index.js'),
        true
    );
}

add_action('wp_enqueue_scripts', 'enqueue_hello_world_script');

npx wp-scripts buildコマンドを実行すると、wp-scriptsはモダンJavaScriptとJSXをトランスパイルし、ブラウザと互換性のあるbuild/index.jsファイルを作成します。

コード品質チェックと洗練されたリンティング

wp-scriptsでは質の高いコードを維持しながら、ESLintやPrettier、さらにCSSとSCSSのリント(コードの検査)にstylelintを利用して、プロジェクト全体で一貫したスタイルを保つことができます。

まずは、package.jsonファイルにlintingスクリプトを追加します。

"scripts": {
  "lint:js": "wp-scripts lint-js",
  "lint:css": "wp-scripts lint-style",
  "lint": "npm run lint:js && npm run lint:css"
}

続いて、プロジェクトのルートディレクトリにカスタム設定ファイルを作成します。例えば、ESLintでは.eslintrc.jsファイルの中で作業しなければなりません。今回の例では(部分的に)JavaScriptコードの文字列にテンプレートリテラルを使用することを強制しています。

…
module.exports = {
  extends: [
    'plugin:@wordpress/eslint-plugin/recommended',
  ],
  rules: {
    // ここにカスタムルール
    'no-console': 'error',
    'react-hooks/exhaustive-deps': 'warn',
    'prefer-template': 'error',
  },
};
…

stylelintでは、.stylelintrc.jsファイルを編集します。

…
module.exports = {
  extends: [
    '@wordpress/stylelint-config/scss',
  ],
  rules: {
    // ここにカスタムルール
    'selector-class-pattern': '^[a-z]+(-[a-z]+)*$',
    'max-nesting-depth': 3,
  },
};
…

複数のプロジェクトにまたがる大規模なコードベースを管理する場合、一貫したコードスタイルの確保は非常に重要です。この方法で、デフォルトのESLintとstylelintの設定を拡張して、コーディング標準に従うことができます。

ここからnpm run lintを実行することで、特定のlintタイプを拡張することができます。例えば、以下のような基本的な連結を記述したコードがあるとします。

const name = "World";
console.log("Hello " + name + "!");

npm run lint:jsを実行するとエラーが表示され、代わりにテンプレートリテラルを使用するように促されます。

const name = "World";
console.log(`Hello ${name}!`);

これは、WordPressのテーマやプラグインのコードをリントするのに非常に役立ち、特定の要件や標準に合わせてルールセットを調整する余地を与えてくれます。

ユニットテスト

ユニットテストは、コードベースの信頼性と保守性を確保するのに欠かせません。wp-scriptsはテストフレームワークとしてJestを使用します。

testコマンドを実行すると、Jestは.test.jsまたは.spec.jsの拡張子を持つファイル、あるいは__tests__ディレクトリにあるファイルを探し、これらのファイルで定義されたテストを実行して結果を返します。

まずは、package.jsonファイル内でテストスクリプトを参照する必要があります。

…
"scripts": {
  "test": "wp-scripts test-unit-js"
}
…

必要であれば、src/utils.jsのようなファイルを作成してください。

…
export function capitalizeString(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

export function sum(a, b) {
  return a + b;
}
…

ここから、src/__tests__/utils.test.jsのようなテストファイルを作成します。

import { capitalizeString, sum } from '../utils';

describe('capitalizeString', () => {
  it('文字列の最初の文字を大文字にする', () => {
    expect(capitalizeString('hello')).toBe('Hello');
  });
  it('空の文字列が与えられた場合、空の文字列を返す', () => {
    expect(capitalizeString('')).toBe('');
  });
});

describe('sum', () => {
  it('2つの数字を正しく足す', () => {
    expect(sum(2, 3)).toBe(5);
  });
  it('負の数を扱う', () => {
    expect(sum(-1, 1)).toBe(0);
  });
});

npm run testコマンドを実行すると、wp-scriptsは自動的に.test.jsという拡張子のファイルをすべて特定して実行します。また、テストカバレッジのような高度なテストをサポートするために、デフォルトのJest設定を拡張することも可能です。

// jest.config.js
const defaultConfig = require('@wordpress/scripts/config/jest-unit.config');
module.exports = {
  ...defaultConfig,
  setupFilesAfterEnv: ['<rootDir>/tests/setupTests.js'],
  collectCoverageFrom: [
    'src/**/*.js',
    '!src/tests/**/*.js',
    '!src/vendor/**/*.js',
  ],
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80,
    },
  },
};

この設定は、カスタム設定ファイルを追加して、カバレッジレポートに含めるファイルを指定してしきい値を設定し、プロジェクト全体で包括的なテストカバレッジを保証します。これらのテストを実行すると、Jestが成功したテストと失敗したテストを示す出力を提供します。

上記のようにユニットテストの機能を拡張することで、WordPressのテーマやプラグインの品質と信頼性を大幅に改善し、開発プロセス全体を効率化することができます。

wp-scriptsをワークフローに組み込む方法

wp-scriptsは用途に応じて好きなだけ拡張できます。以下、wp-scriptsを使って一般的なタスクを自動化する方法をいくつかご紹介します。

再利用可能なプロジェクトテンプレートの作成

新規プロジェクトを頻繁に立ち上げる場合、wp-scriptsをあらかじめ設定しておくことで、カスタムプロジェクトテンプレートを作成でき、セットアップにかかる時間を大幅に短縮することができます。

wp-scriptsのセットアップを含むWordPressテーマまたはプラグインという基本的なプロジェクトから始めます。

mkdir my-agency-base-theme
cd my-agency-base-theme
npm init -y
npm install --save-dev @wordpress/scripts

次にプロジェクトの構造を設定して、必要なディレクトリとファイルを作成します。

mkdir src build
touch src/index.js src/style.scss
touch functions.php style.css

この時点でwp-scriptsを設定し、package.jsonファイルを関連コマンドで更新します。

{
  "scripts": {
    "build": "wp-scripts build",
    "start": "wp-scripts start",
    "lint:js": "wp-scripts lint-js",
    "lint:css": "wp-scripts lint-style",
    "test": "wp-scripts test-unit-js"
  }
}

これを発展させて、webpack、ESLint、stylelintの設定を作成することができます。

これを再利用可能なテンプレートにして簡単にアクセスできるようにするには、GitHubリポジトリを使うのがおすすめです。例えば、リモートオリジンとしてhttps://github.com/your-agency/theme-template.gitのようなURLを使用できます。

プロジェクトを立ち上げる際には、以下のような簡単なコマンドを実行できます。

npx create-wordpress-theme@latest my-new-theme --template your-agency/theme-template

これでテンプレートリポジトリが複製され、あらかじめ定義したwp-scriptsの設定でテーマがセットアップされます。

よく使用する関数やコンポーネントなど、固有のコードを追加することで、テンプレートをさらにカスタマイズすることも。テンプレートリポジトリは、最新のwp-scriptsバージョンを使用し、決まったワークフローの改善を取り入れて、常に最新の状態に保つことが重要です。

バージョン管理とコラボレーション

wp-scriptsを使用する作業はバージョン管理に関しては、さらに多くのことを実げMできます。ただし、コードの品質を保つため、通常は以下のようなプラクティスを取り入れる必要があります。

  • package.jsonpackage-lock.jsonをバージョン管理に含める。これにより、チーム間で統一して同じ依存関係を使用できる。
  • .gitignoreファイルに/build/node_modulesなどのビルドアーティファクトを必ず含める。
  • コミットする前に、package.jsonファイル内で必要なスクリプトをすべて参照するようにする。
  • .nvmrcファイルを使用して、プロジェクトの正しいNode.jsバージョンを指定する。

Huskyのようなツールを使用して、コミット前のフックを実装することも可能です。以下は一例ですが、コミット前にリントを行うのに便利です。

…
"husky": {
    "hooks": {
        "pre-commit": "npm run lint:js && npm run lint:css"
    }
}
…

これにより、コミットやプッシュの前に自動的にリントやテストを実行できます。チーム全体でコードの品質を維持できるもう1つの方法です。

継続的インテグレーション・継続的デプロイメント(CI/CD)

wp-scriptsをCI/CDパイプラインに統合することで、テーマとプラグイン両方のデプロイプロセスを効率化できます。例えば、GitHub Actionsを使ってwp-scriptsの設定に統合することができます。

まずは、リポジトリのworkflowsディレクトリに専用のワークフローファイルを作成します。

name: CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '14'
    - name: Cache dependencies
      uses: actions/cache@v2
      with:
        path: ~/.npm
        key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
    - name: Install dependencies
      run: npm ci
    - name: Run linters
      run: |
        npm run lint:js
        npm run lint:css
    - name: Run tests
      run: npm run test
    - name: Build
      run: npm run build
    - name: Deploy
      if: github.ref == 'refs/heads/main'
      run: |
        # ここにデプロイスクリプトを追加
        # 例えば、リモートサーバーにrsyncを使う場合:
        # rsync -avzc --delete ./build/ [email protected]:/path/to/wp-content/themes/your-theme/

デプロイ手順はホストによって異なり、rsyncを使ったり、DeployHQBuddyのようなサービスと統合したり、シンプルにcURLで統合したりします。デプロイにパスワードやキーが必要な場合は、GitHubリポジトリの設定にシークレットとして追加してください。

このワークフローは、プッシュやプルリクエストのたびにlint、テスト、プロジェクトのビルドを実行します。メインブランチに変更をプッシュした時にだけデプロイされるのが便利な特徴です。

コマンドラインインターフェース(CLI)ツールの作成

カスタムツールが必要な場合も、wp-scriptsが一役買ってくれます。例えば、会社の要件に応じた独自のコマンドラインインターフェース(CLI)ツールをデプロイしたいことがあるかもしれません。

場合によっては、ツールにいくつかの依存関係が必要になります。

npm install @wordpress/scripts commander chalk

上の例では、Commanderはコマンドライン引数を解析し、chalkは出力テキストの視覚的な表示を改善します。

ここから、wp-scriptsを活用したツールのコードを書き始めます。例えば、以下のようになります。

#!/usr/bin/env node
const { program } = require('commander');
const { spawn } = require('child_process');
const path = require('path');
const chalk = require('chalk');

const wpScripts = path.resolve(__dirname, './node_modules/.bin/wp-scripts');

const runWpScripts = (script, args) => {
  console.log(chalk.blue(`wp-scripts ${script} を実行中...`));
  const result = spawn(wpScripts, [script, ...args], { stdio: 'inherit' });
  result.on('exit', (code) => {
    if (code !== 0) {
      console.log(chalk.red(`wp-scripts ${script} failed with code ${code}`));
    }
  });
};

program
  .version('1.0.0')
  .description('エージェンシーXYZのためのカスタムWordPress開発CLI');

program
  .command('build')
  .description('プロジェクトの構築')
  .action(() => runWpScripts('build'));

program
  .command('start')
  .description('開発サーバーの起動')
  .action(() => runWpScripts('start'));

program
  .command('lint')
  .description('JavaScriptとCSSファイルのリント')
  .action(() => {
    runWpScripts('lint-js');
    runWpScripts('lint-style');
  });

program
  .command('test')
  .description('ユニットテストの実行')
  .action(() => runWpScripts('test-unit-js'));

program
  .command('deploy')
  .description('プロジェクトのデプロイ')
  .action(() => {
    console.log(chalk.green('プロジェクトをデプロイ中...'));
    // ここにデプロイメントロジックを追加
    // 例えば:
    // spawn('rsync', ['-avz', 'build/', 'user@server:/path/to/wordpress/wp-content/themes/your-theme/']);
  });

program.parse(process.argv);

package.jsonファイルにbinフィールドを追加すると、CLIツールを実行ファイルにすることができます。

…
{
  "name": "agency-wp-cli",
  "version": "1.0.0",
  "bin": {
    "agency-wp": "./cli.js"
  },
  // その他のフィールド
}
…

CLIをローカルにインストールするためにリンクするには、npm linkを実行するだけでOKです。これで、ターミナルアプリケーションでCLIをテストできるようになります。

agency-wp build
agency-wp lint
agency-wp deploy

他のメンバーが自由にインストールできるよう、プライベートなnpmレジストリにツールを公開します。

npm publish --registry=https://your-private-registry.com

必要時にnpm install --save-dev agency-wp-cliを実行するだけで、ツールをインストールすることができます。ここからpackage.jsonのCLIを参照します。

{
  "scripts": {
    "build": "agency-wp build",
    "start": "agency-wp start",
    "lint": "agency-wp lint",
    "test": "agency-wp test",
    "deploy": "agency-wp deploy"
  }
}

このようなツールを作成して使用することで、社内の全員が同じコマンドとプロセスを使用できるようになります。これにより、矛盾やエラーが削減され、WordPress開発のワークフローがさらに効率化されます。

パフォーマンスの最適化

トラフィックの多いWordPressサイトを複数管理する場合、パフォーマンスの最適化がサイトの成功を左右します。wp-scriptsでは、いくつかの高度なテクニックを導入することができます。

高度なコード分割

たとえば、コード分割を使用すると、JavaScriptバンドルを小さな塊に分割し、オンデマンドで読み込むことができます。特に大規模なアプリケーションでは、これにより最初の読み込み時間が短縮されます。

まず最初にwebpack.config.jsファイルを修正して、コード分割を有効にします。

const defaultConfig = require('@wordpress/scripts/config/webpack.config');

module.exports = {
  ...defaultConfig,
  entry: {
    main: './src/index.js',
    admin: './src/admin.js',
  },
  output: {
    filename: '[name].js',
    chunkFilename: '[name].[contenthash].js',
  },
  optimization: {
    ...defaultConfig.optimization,
    splitChunks: {
      chunks: 'all',
      minSize: 0,
      cacheGroups: {
        vendor: {
          test: /[\/]node_modules[\/]/,
          name(module) {
            const packageName = module.context.match(/[\/]node_modules[\/](.*?)([\/]|$)/)[1];
            return `vendor.${packageName.replace('@', '')}`;
          },
        },
      },
    },
  },
};

JavaScriptのコード全体を通して、動的インポートを使って小さな塊に分割します。

// 代わりに: import { heavyFunction } from './heavyModule';

button.addEventListener('click', () => {
  import('./heavyModule').then(module => {
    module.heavyFunction();
  });
});

また、WordPressファイル内で各分割をエンキューする必要があります。

function enqueue_split_scripts() {
  $asset_file = include(get_template_directory() . '/build/index.asset.php');  

  wp_enqueue_script('main', get_template_directory_uri() . '/build/main.js', $asset_file['dependencies'], $asset_file['version'], true);
  wp_enqueue_script('admin', get_template_directory_uri() . '/build/admin.js', $asset_file['dependencies'], $asset_file['version'], true);
}
add_action('wp_enqueue_scripts', 'enqueue_split_scripts');

これにより、読み込み時間が短縮され、実装にもそれほど時間はかかりません。

Tree shaking

Tree shakingとは、JavaScriptの文脈では未使用のコードを取り除くことです。wp-scriptswebpackのいずれも、本番のビルドではTree shakingを行いますが、さらに最適化することも可能です。アプリケーションは以下にご説明するよりも複雑ですが、いずれにしてもES6のインポートおよびエクスポート構文は確実に使用したいところです。

// Tree shakingに適している
export function usedFunction() { /* ... */ }

// Tree shakingに適していない
module.exports = {
  usedFunction: function() { /* ... */ },
};

次に、副作用を持つファイルを指定します。

{
  "name": "your-package",
  "sideEffects": ["*.css", "*.scss"]
}

または副作用を持たないことを明示的に指定します。

{
  "name": "your-package",
  "sideEffects": false
}

大規模なライブラリの中には、Tree shakingをサポートしていないものもあります。その場合はプラグインを使用してください。

npm install --save-dev babel-plugin-transform-imports

エラーのない最適化されたインストールを実現するには、babelの設定ファイルも更新する必要があります。

アセットの最適化

wp-scriptsのビルドプロセスは、CSSとJavaScriptファイルを自動で最小化します。例えば、特定の画像最適化プラグインをインストールすることができます。

npm install --save-dev imagemin-webpack-plugin

これをwebpackの設定ファイルに追加すると、functions.phpファイルまたはメインのプラグインファイルに適切なコードを追加することで、リソースヒントを使用できます。

function add_resource_hints( $urls, $relation_type ) {
  if ( 'preconnect' === $relation_type ) {
    $urls[] = 'https://fonts.googleapis.com';
    $urls[] = 'https://fonts.gstatic.com';
  }
  return $urls;
}

add_filter( 'wp_resource_hints', 'add_resource_hints', 10, 2 );

このようなタスクから、wp-scriptsの柔軟性がうかがえます。

バンドルサイズの分析

最適化には、バンドルの構成を理解することが重要です。wp-scriptsを使用すると、--analyzeフラグで簡単に分析できます。

npm run build -- --analyze

最初のステップとして、package.jsonファイルに関連するスクリプトを追加します。

{
  "scripts": {
    "analyze": "wp-scripts build --analyze"
  }
}

analyzeコマンドを実行すると、バンドル内の各モジュールのサイズを示すレポートが生成されます。このシンプルな実装は、最適化のための領域を特定するのに役立ちます。

重要なCSSの実装

サイトのクリティカルCSSは、ページがAbove the foldのコンテンツを読み込むために必要な最低限のCSSです。このCSSをインラインに配置することで、読み込み時間を改善することができます。

これを実現するには、Critical CSS Webpackプラグインを使用します。

npm install --save-dev critical-css-webpack-plugin

続いて、プラグインを参照するようにwebpackの設定ファイルを更新します。

const CriticalCssPlugin = require('critical-css-webpack-plugin');
const defaultConfig = require('@wordpress/scripts/config/webpack.config');

module.exports = {
  ...defaultConfig,
  plugins: [
    ...defaultConfig.plugins,
    new CriticalCssPlugin({
      base: 'dist/',
      src: 'index.html',
      target: 'styles/critical.css',
      extract: true,
      inline: true,
      minify: true,
      dimensions: [
        {
          height: 500,
          width: 300,
        },
        {
          height: 900,
          width: 1300,
        },
      ],
    }),
  ],
};

プラグインを使用するには、header.phpファイルにスニペットを追加します。

<style>
  <?php echo file_get_contents(get_template_directory() . '/build/styles/critical.css'); ?>
</style>

上記は初期レンダリングを高速化するために重要なCSSを抽出し、インライン化するものです。特定のビューポートサイズに対応する重要なCSSを生成し、テーマの読み込み時間を改善します。

まとめ

Web制作会社や代行業者にとって、wp-scriptsは、テーマとプラグイン両方の開発プロジェクトのワークフローを大幅に強化できる強力なツールです。標準化されたビルドプロセス、モダンJavaScriptのサポート、統合されたテストとリンティングツールを活用することで、重要なタスクの一部を自動化しながら、優れたWordPressプロジェクトの開発に集中することができます。

wp-scriptsで最新の開発プラクティスに対応できるだけでなく、WordPress開発の最前線に立ち、制作会社が遭遇しがちな課題に対処することができます。

Steve Bonisteel Kinsta

Kinstaのテクニカルエディター。救急車や消防車を追いかける記者としてキャリアをスタート。1990年代後半からインターネット関連の技術情報を担当している。