WordPressでJavaScriptを読み込ませるならこうすると便利です(2018年)

# はじめに
WordPressでJavaScriptを使う機会があり読み込ませる方法について検討してみました。

結論を先にまとめると「小さいなら`add_action()`+無名関数」で、「大きくなったら`wp_enqueue_script()`」です。

# 直接読み込ませる
WordPressの公式サイトでは[header.phpに記述したりして直接読み込ませる方法](https://codex.wordpress.org/Using_Javascript)が紹介されていますが、`header.php`ではなくテンプレートごとに記述する方法を取ります。

## 投稿や固定ページで呼び出す場合
一つのテンプレートファイルだけで使うスクリプトを記載したい場合には`wp_headers`や`wp_footer`にフックして書きます。

```PHP
<?php
/**
 * フッターで呼び出し。
 */
add_filter( 'wp_footer', function() {
    ?>
    <script>
        console.log('Hello World!');
    </script>
    <?php
} );
```

<img width="594" alt="Screen Shot 2018-03-12 at 15.59.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/ab65cead-8566-c5e0-ebae-adbb9abf2c9b.png">
<img width="516" alt="Screen Shot 2018-03-12 at 15.58.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/2dac4b90-02bd-5b40-790d-cb09c70d7de6.png">

無名関数＋PHPの閉じタグ、開始タグと一緒に書くことでヒアドキュメント風に書ける上にエディタがJavaScriptとして認識しやすいので見栄えがスッキリします。

ただしJavaScriptの処理が大きくなって来た場合にはJSファイルとして分離し、`wp_enqueue_script()`で登録すると見通しが良いです。


# wp_enqueue* 系関数を使って読み込ませる方法
WordPressの標準関数、`wp_enqueue_script()`で読み込ませる方法です。

| 関数名 | 目的 |
|-------|------|
| `wp_enqueue_script()` | JavaScriptファイルをロードさせる |
| `wp_register_script()` | ロードさせる前に登録させたい場合に使う |
| `wp_localize_script()` | 変数をページ内にロードさせたい場合に使う | 
| `wp_dequeue_script()` | エンキューをやめる |


## wp_enqueue_script
よく「WordPress JavaScript」でググると出てくる方法です。
`wp_enqueue_script()` を `add_action()` で登録した関数に入れたりします。

```PHP
<?php
add_action( 'wp_enqueue_scripts', function() {
wp_enqueue_script( 'wspc',
   plugins_url( '/js/wspc.js', __FILE__ ),
    array( 'jquery' ) );
});
```

特に理由がなければ`header.php`に`<script src="...">`で直接記載するより`wp_enqueue_script()`を使う方が良いです。
JavaScriptファイルのミニファイ（圧縮）やフッターでのロード、依存関係の順序、多重読み込み防止といった利点があります。
「enqueue(エンキュー)」は「『キュー』（待ち行列）に並ばせる」という意味で、実際にHTMLへ出力する前に色んなスクリプトファイルをエンキューしておいて、ヘッダーやフッターでロードさせます。

### 無名関数

```PHP
<?php
add_action( 'wp_enqueue_scripts', function() {
wp_enqueue_script( 'wspc',
   plugins_url( '/js/wspc.js', __FILE__ ),
    [ 'jquery' ] );
});
```

上記の例ですと[PHPの無名関数](http://php.net/manual/ja/functions.anonymous.php)を使ってロードしています。
無名関数を使う場合の利点はコードがシンプルでキレイになることです。
参考: https://torounit.com/blog/2013/05/23/1548/

無名関数を使うデメリットは`enqueue_scripts`に限らず、「ロードとりやめ」が難しいことです。
`add_action()`したアクションは`remove_action()`で取りやめできますが、無名関数の場合には難しいです。
ただ`wp_enqueue_script()`については「一旦エンキューしたファイルをデキューしたい。（やっぱロードさせない）」場合には`wp_dequeue_script()`が使えます。


### テーマでロードする場合

作成したテーマディレクトリにあるjsファイルをロードする方法です。

```PHP
<?php
add_action( 'wp_enqueue_scripts', function() {
  wp_enqueue_script( 'my_script', 
  get_stylesheet_directory_uri().'/js/hoge.js', 
  array('jquery'), '1.0.0', true);
});
```

`get_stylesheet_directory_uri()`を使って場所を特定します。

### プラグインでロードする場合
WordPressでは見た目をテーマに、機能をプラグインにという原則があります。
JavaScriptファイルがどちらに属するか迷うところもありますが、Ajax処理などを記載する場合には機能としてプラグインに分離した方が良いです。

プラグインディレクトリにおいたjsファイルを読ませる場合には`plugins_url()`を使います。

```PHP
add_action( 'wp_enqueue_scripts', function() {
    wp_enqueue_script( 'wspc',
        plugins_url( '/js/wspc.js', __FILE__ ), 
        [ 'jquery' ] );
    );
});
```

`plugins_url()`を使うと「ファイルが存在するか」を調べてロードしてくれます。
呼び出し方は下記のように第二引数に `__FILE__` としてプラグインディレクトリにあるファイルを指定する方法が一般的です。


```PHP
plugins_url( '/js/myscript.js', __FILE__ ), 
```

### JSファイルをキャッシュさせない
第四引数に`date('U')`を付けておくとブラウザがキャッシュしません。
特に開発中はオンにしておいたほうが幸せになれます。

```PHP
wp_enqueue_script( 'curl_generator', get 
 _theme_file_uri('/js/curl_generator.js'),
  array('jquery'),
  date('U'),
true);
```

こんな感じで?の後ろに時間が付きます。

<img width="451" alt="Screen Shot 2018-03-12 at 16.10.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/8ba45115-8bb6-124c-1362-39eb2b80cd37.png">


第四引数が設定されている場合にはscriptタグのクエリストリングとして出力されます。
現在時刻のUNIXタイムスタンプを付けておけば大体のブラウザはキャッシュしないです。
CDNを挟んだ時のキャッシュも回避しやすいので便利です。
開発中や修正中にキャッシュが原因で時間を取られることも多いので基本的には付けておく、運用開始後に遅いなーと思って、[Google PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/)などでサーバ高速化の際に見つけたら取る、って感じです。
静的キャッシュ系のプラグインを入れている場合には、JSファイルの変更日時を付けるという方法も使っています。

### 管理画面（admin panel）でJavaScriptファイルを読み込ませたい場合
管理画面でJavaScriptファイルを読み込ませたい場合、`admin_enqueue_scripts`[^admin1]を利用します

[^admin1]: https://developer.wordpress.org/reference/hooks/admin_enqueue_scripts/

```php
add_action( 'admin_enqueue_scripts', function() {
    wp_enqueue_script( 'wspc',
        plugins_url( '/js/wspc.js', __FILE__ ), 
        [ 'jquery' ] );
    );
});
```

接頭語が`wp_`ではなく`admin_`になります。


## wp_add_inline_script
非常に短いコードであれば `wp_add_inline_script()`を使うと便利です。 （@ykatombn さんありがとうございます！
具体的には `wp_enqueue_script` で読み込んだライブラリの起動コードを書くと便利です。

```php
 wp_enqueue_script('object-fit', get_template_directory_uri() . '/js/ofi.min.js', array(), null, true);
 wp_add_inline_script('object-fit', 'objectFitImages();');
```

## wp_register_script
`wp_enqueue_script()`でエンキューの登録を行う前に、ハンドル名を付けて登録する関数です。
あまり使わないですね。

参考: https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wp_enqueue_script

プラグインやライブラリ系を`wp_register_script()`で登録しておいて、必要になった時に`wp_enqueue_script()`で呼ぶ、とすると見栄えが良いです。

## wp_localize_script

ページごとの変数を入れる関数です。

```PHP
wp_localize_script( 'wspc', 'wspc',
	array(
		'ajax_url' => admin_url( 'admin-ajax.php' ),
		'post_id'  => $post_id,
		'count_range' => array(500, 1000),
) );
```

上記のように書いておけば、下記のように`<![CDATA[ ... ]]>`でいい感じに出力してくれます。

<img width="927" alt="Screen Shot 2018-03-12 at 15.18.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/b3202853-d08e-7ff4-e247-1bd72d1bc737.png">

PHPからページごとにJavaScriptの変数を埋め込む際に使います。

とはいえ、本来の使い方はは関数名にlocalizeと入っているとおり、JavaScript系の*Localize（翻訳用）*用です。
ただし公式マニュアルを意訳すると変数用に使っていいよ、とのことでした。

> Though localization is the primary use, it can be used to make any data available to your script that you can normally only get from the server side of WordPress.
https://codex.wordpress.org/Function_Reference/wp_localize_script

意訳後

> 基本的にはローカライズ用ですが、サーバからの変数取得に使われてます。

最近まで知らなかったんですがこれ便利です。


# その他

この記事で書いたことの注意点などです。


## バージョンなど
[WordPressの推奨PHPバージョンは7.2以上です！！](https://wordpress.org/about/requirements/)（強く伝えたい）

なのですが、5.2.4以上であれば動くことが保証されています。

無名関数はPHP 5.3で導入されました。
配列を`[ 'foo', 'bar' ];`が使えるのはPHP5.4以降です。
5.3以前は`array( 'foo', 'bar' );`です。 

[`__DIR__`はPHP 5.3で導入](http://php.net/manual/en/language.constants.predefined.php)されています。
PHP5.2以前では使えません。2018年でも5.2案件が降ってくるのですが…、慣れました ☺


そのためPHP5.2.4には無い無名関数、配列の角括弧が使えないことも多々あります。
特に配布用のテーマ、プラグインの場合には動かない原因となるので注意が必要です。

## 固定ページのslugと一致するjsを自動で読み込ませる

```php5
/**
 * JSファイルを読み込ませる
 */
function load_scripts() {
    if ( $pagename = get_query_var( 'pagename' ) ) {
        if ( file_exists( get_stylesheet_directory() . '/js/' . $pagename . '.js' ) ) {
            wp_enqueue_script( $pagename, get_stylesheet_directory_uri() . '/js/' . $pagename . '.js');
        }
    }
}
add_action( 'wp_enqueue_scripts', 'load_scripts' );
```

別の記事に書いていたものです。WordPressのシステム開発の場合、固定ページごとにJSファイルを読み込ませたい、ということ多々あります。
上記のように書いておけばslugと一致した固定ページの場合、自動的にJSファイルがロードされます。

[エンジニアな自分がWordPressで何度も調べたり感心したりした事](https://qiita.com/yousan/items/c925f0a241be02a55292)