以下是我为实现这一目标所做的工作。我将此作为一个可能的解决方案发布,也是为了从任何比我有更多WP经验的人那里获得反馈。如果您发现我的实现有任何问题或我没有考虑的任何问题,请告诉我。
Known limitations:
<它只适用于通过
wp_enqueue_script
它输出页脚中的所有脚本,即使它们只注册为在
<head>
页面的节。这可能很容易解决,但对于我的实现,我更喜欢这种方式我看到的
head.js plugin 它似乎只在
<head>
并且事实上,它不允许任何简单的CDN回退功能,这在我看来是以这种方式加载脚本的一个非常好的好处。
好的,这是代码。这是我的通用功能插件中的一个类的一部分,但它也可以很容易地functions.php
或者以其他方式组织。我正在使用yepnope 目前,可以很容易地修改它以使用另一个脚本加载程序。
class example {
function __construct() {
/*
Hook into the script printing functionality and use our own resource loader to load
scripts in a non-blocking, asynchronous, parallel fancy way
*/
if( !is_admin() ) {
add_action( \'wp_print_scripts\', array( &$this, \'deploy_script_loader\' ) );
}
}
/*
If we have any javascripts queued for the page, grab the handles of
all of the ones to be loaded in the header and dequeue them now.
Then, we will check again and reload any that weren\'t queued
yet in the footer.
*/
function deploy_script_loader( ) {
global $wp_scripts;
if ( !empty( $wp_scripts->queue ) && !is_admin() ) {
// Get the queue in our class property, and dequeue everything
foreach ( $wp_scripts->queue as $handle ) {
/*
Check if this script is supposed to be loaded in the header (group isn\'t 1).
If it is, we\'ll grab it now and dequeue it. We\'ll save the rest of the dequeuing
for the footer script or else we\'ll miss some scripts that are queued after
this hook is run.
*/
if ( 1 !== $wp_scripts->registered[$handle]->extra[\'group\'] ) {
/*
Just dequeuing a script here isn\'t enough to prevent it from being
printed in the header if another script that we haven\'t dequeued (ie a footer
script) depends on it. So, we need to make sure that all of the
scripts we just dequeued will be ok loading in the footer (where they will
get dequeued for real before they are printed).
*/
$wp_scripts->registered[$handle]->extra[\'group\'] = 1;
}
}
// Add our hook to load everything in the footer
add_action( \'wp_footer\', array( &$this, \'output_script_loader\' ) );
}
}
/*
Function to be ran in wp_footer to output the js script loader
html content.
*/
function output_script_loader() {
global $wp_scripts;
// Process the scripts dependency tree, but don\'t print anything
ob_start();
$script_queue = $wp_scripts->do_items();
ob_clean();
// Add our script loader
echo \'<script type="text/javascript" src="\' . plugins_url( \'/scripts/yepnope.1.0.2-min.js\', __FILE__ ) . \'"></script><script type="text/javascript">\';
// Loop through the queued scripts and get all of their localization output objects first
foreach( $script_queue as $handle ) {
echo $wp_scripts->registered[$handle]->extra[\'data\'];
}
echo \'yepnope.errorTimeout = 4000; yepnope([\';
$i = 0;
$count = count( $script_queue );
// Loop through the queued scripts again, this time output the script loader syntax
foreach( $script_queue as $handle ) {
if ( \'jquery\' === $handle ) {
$jquery_cdn_url = ( is_ssl() ) ? \'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js\' : \'http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js\';
echo \' { load: "\'. $jquery_cdn_url .\'", callback: function () { if (!window.jQuery) { yepnope("\' . $wp_scripts->base_url . $wp_scripts->registered[\'jquery\']->src . \'"); } } },\';
} else {
$src = $wp_scripts->registered[$handle]->src;
// Check if this is a relative path or if we have the whole thing
if( \'http\' !== strtolower( substr( $src, 0, 4 ) ) ) {
$src = $wp_scripts->base_url . $src;
} else {
$src = ( is_ssl() ) ? \'https\' . substr( $src, strpos( $src, \':\' ), strlen( $src ) ) : \'http\' . substr( $src, strpos( $src, \':\' ), strlen( $src ) );
}
$comma = ( $i == ( $count - 1 ) ) ? \'\' : \',\';
echo \'{ load: "\' . $src . \'" }\' . $comma;
}
$i++;
}
echo \']);</script>\';
}
}
// Instantiate the class
new example;