複数の<script>
タグによるパフォーマンスの低下を避けるために、スクリプトを定期的に連結し、1つの単一のbundle.min.js
JSファイルと'jsbundle'
識別子を生成します。
問題は、プラグインなど、その後に追加されるものは、存在するが登録された1つ以上のライブラリに依存するが、汎用の'jsbundle'
にパックされることです。
Wordpressに'jsbundle'
が暗示することを通知する方法はありますか、たとえば'jquery'
、'backbone'
、... 1)リソースが2回ロードされない2)満たされない依存関係のために失敗しない?
私はwp_register_script
のソースを試し、WP_Scripts()
クラスを見つけ、WPの利用可能なスクリプトについて「嘘をつく」ことを試みましたが、運はありません。
それらのバンドルをすでに作成しているためにJavaScriptライブラリがロードされないようにするには、次の手順を実行します。
次の通常のエンキューをまとめます。
function the_js() {
wp_enqueue_script('bundle_js', get_template_directory_uri() . '/js/bundle.js', array(), false, false);
}
add_action('wp_enqueue_scripts', 'the_js');
そして、あなたがあなたのバンドルの中に次のライブラリがあるとしましょう(ハンドルをリストします):
jquery
backbone
colorpicker
bootstrap_js
1、2、3はすでにコアになっており、4はサードパーティーです。4を別々のリソースとしてロードしたくないため、4をすべてバンドルしています。
あなたは登録を解除し(登録されていれば、コアのものは既に登録されているでしょう)、あなたのバンドルの中にあるライブラリーのそれぞれを登録しなければなりません:
function the_js() {
wp_enqueue_script('bundle_js', get_template_directory_uri() . '/js/bundle.js', array(), false, false);
//DEREGISTER the SCRIPTS THAT ARE IN YOUR BUNDLE
wp_deregister_script('jquery'); //because its a Core-Registered Script
wp_deregister_script('backbone'); //because its a Core-Registered Script
wp_deregister_script('colorpicker'); //because its a Core-Registered Script
//REGISTER THEM THIS TIME USING YOUR BUNDLE AS DEPENDENCY
wp_register_script('jquery', FALSE, array('bundle_js'), '', FALSE);//THE KEY HERE IS THE SRC BEING FALSE
wp_register_script('backbone', FALSE, array('bundle_js'), '', FALSE);
wp_register_script('colorpicker', FALSE, array('bundle_js'), '', FALSE);
}
add_action('wp_enqueue_scripts', 'the_js');
ここで重要なのは、登録済みのスクリプトがエイリアスになるように$src
をFALSE
に設定することです。コアコードの this line を確認してください。
// A single item may alias a set of items, by having dependencies, but no source.
if ( ! $obj->src ) {
return true;
}
そのjquery
が現在行っていること、依存関係としてjquery
を置くとき、それはjquery
をロードしませんそれはjquery-core
とjquery-migrate
をロードします、これはjquery
のために登録されたオブジェクトです:
object(_WP_Dependency)#329 (6) {
["handle"]=>
string(6) "jquery"
["src"]=>
bool(false)
["deps"]=>
array(2) {
[0]=>
string(11) "jquery-core"
[1]=>
string(14) "jquery-migrate"
}
["ver"]=>
string(6) "1.12.4"
["args"]=>
NULL
["extra"]=>
array(0) {
}
}
そのため、bundle_js
は、スクリプトがいずれかのライブラリ(jquery
、backbone
、colorpicker
)の依存関係として存在する場合にロードされ、WP_Dependencies
のロジックがすでにqueue
配列にあるかどうかをチェックするため、1回ロードされます。
スクリプトが既に登録されているかどうかを確認したい場合は:
global $wp_scripts;
$wp_scripts->query('jquery'); //jquery as example handle
登録されていればWP_dependency
オブジェクトを、そうでなければfalse
を返します。
さらに理解を深めるためのリンク
class.wp-dependencies.php
class.wp-scripts.php
functions.wp-scripts.php
Alexanderによって提案された解決策は合理的に見えます。次のように、すべての縮小された依存関係(この例ではlibs.js)を1つのファイルに、スクリプトを2番目のファイルに保存できます。
wp_enqueue_script( 'libs', get_template_directory_uri() . '/assets/js/libs.js', [], '1.0.0', true );
// third parameter here will make sure that libs.js is loaded before jsbundle:
wp_enqueue_script( 'jsbundle', get_template_directory_uri() . '/assets/js/jsbundle.min.js', [ 'libs' ], '1.0.0', true );
スクリプトをバンドルすることはページの読み込み速度を最適化するためのよく知られた方法であり、ほとんどの場合は良い考えですが、それが常に最もパフォーマンスの高い解決策とは限りません。私はいつも他の選択肢を検討し、特定のユースケースに最適なものを決定します。
この答えで にリストされているすべての利点を得るためにあなたのサードパーティのライブラリに利用可能なCDNの1つを使いたいかもしれません。
例えば。あなたがグーグルまたはフェイスブックのCDNを使うならば、あなたの訪問者はすでに彼らのブラウザにキャッシュされた人気のあるスクリプトを持っていて、それを再びダウンロードする必要がないだろうという大きな可能性があります。
その場合、サードパーティのスクリプトをバンドルするとこの利点がなくなり、たとえその一部がすでにブラウザのキャッシュに保存されている場合でも、バンドル全体をダウンロードする必要があります。
CDNからスクリプトをwp_enqueue_script()
で簡単にエンキューできます。$ver
パラメータを省略するだけで、キャッシュされたスクリプトを更新したくないためです。
wp_enqueue_script( 'jquery', 'https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js', [], null, true );
私が考慮するもう一つのことは、より多くのスクリプトを登録し、それらが実際に使用されているページでのみそれらを呼び出すことです。これはスクリプトを頻繁に更新する場合に特に有効です。
すべてのスクリプトを1つのバンドルにまとめておく場合、1つの小さな変更を適用するには、スクリプト全体のキャッシュを無効にする必要があります。スクリプトの一部を分離しておく方が良い場合があるので、実際に編集したチャンクに対してのみバージョンを変更できます。
私のホームページでfoo.js
スクリプトを使っていて、そこではあまり起こっていないのですぐには変更するつもりはありませんが、同時に保守と更新が必要な複雑なbar.js
スクリプトがあります。その場合は、スクリプトを個別に登録することをお勧めします。
また、ライブラリの中には、あまり頻繁にはアクセスされないサブページでしか使用されないものもあります(あまり一般的ではないサブページではmasonry
を使用するとします)。その場合は、//石積みを登録しますが、まだエンキューしないでくださいwp_register_script( 'masonry'、get_template_directory_uri()。 '/assets/js/masonry.min.js'、[]、1.0、true) ;
// foo.js is my implementation of masonry.js
wp_register_script( 'foo.js', get_template_directory_uri() . '/assets/js/masonry.min.js', [ 'masonry' ], 1.0, true );
// in bar.js I keep functions used all over my page so I enqueue it everywhere immediately
wp_enqueue_script( 'bar.js', get_template_directory_uri() . '/assets/js/masonry.min.js', [], 1.0, true );
// masonry.js and foo.js can wait until the user reaches my less popular subpage as it won't be needed most of the time
if ( is_post_type_archive( 'unpopular-posts' ) ){
wp_enqueue_script( 'foo.js' );
}
私の以前の答えの下で@janhとの素早い交換は私に異なるアプローチについて考えるように促しました。私はまだすべてのサードパーティ製ライブラリを1つの別々のバンドルファイル(bundlejs
)に縮小し、そしてグローバルな$wp_scripts
変数で作業します(その考えの名誉は このスレッド に行きます)
Janhが気付いたように、他の人が自分のプラグインやテーマでスクリプトを呼び出す方法を予測することは不可能です。私の関数では、バンドルファイルに含まれているスクリプト名の配列を使用しています。重複の可能性を倍増するために、ハンドルだけではなくスクリプトファイル名のサポートも追加しました。
管理スクリプトの中には、まったく触れてはいけないものがあります( codex を参照)。
解決策はかなり未加工です、私はそれがさまざまな方法で完成できると確信しています、間違いなくいくつかのリファクタリングとWPキャッシュサポートを使うことができます。また、それが実際のケースでパフォーマンスにどのように影響するかもわかりません。しかし、それはあなたが一般的な考えと多分いくらかのインスピレーションを得るためにあなたのためにここにあります:
function switch_dependencies_to_bundle(){
global $wp_scripts;
/**
* array of scripts that our bundle file contains - can be either script name or handle name
* it's never going to be bulletproof tho', as plugin authors can change file names, i.e.
* include other version of script
*/
$bundled = [
'jquery',
'masonry',
'masonry-js',
'masonry.js',
'masonry.min.js', //we can use file name too
'backbone',
'backbone.min.js'
];
$deps_to_remove = [];
// register our bundle script
wp_register_script( 'bundlejs', get_template_directory_uri() . '/assets/js/bundle.min.js', [], '1.0.0', true );
wp_enqueue_script( 'bundlejs' );
// get registered scripts that our bundle file would duplicate
foreach( $wp_scripts->registered as $handle => $script ){
$file_name = substr( $script->src , strrpos( $script->src, "/" ) + 1 );
if ( in_array( $handle, $bundled, true ) || in_array( $file_name, $bundled, true ) ){
$deps_to_remove[] = $handle;
}
}
//get rid of redundant scripts with deregister and dequeue.
//NOTE: does not work for some admin scripts, see codex
foreach( $deps_to_remove as $script ){
wp_deregister_script( $script );
wp_dequeue_script( $script );
}
// take care of remaining scripts' dependencies (they wouldn't load with deps missing)
// add our bundle as dependency, as it contains the same scripts that we just removed
foreach( $wp_scripts->registered as $script ){
if ( ! empty( array_intersect( $deps_to_remove, $script->deps ) ) ) {
$script->deps[] = 'bundlejs';
$script->deps = array_diff( $script->deps, $deps_to_remove );
}
}
}
// load the function with high priority so it kickes in after other plugins registered their scripts
add_action('wp_enqueue_scripts', 'switch_dependencies_to_bundle', 9999);