Hi @mrclay:
Good questions.
WordPress Multisite is Many Independant Sites, not Many Dependant Sites
To answer your aside, WordPress multisite was designed to be a collections of independent WordPress installs collected into one where each site is likely to be very different, unlike your use-case. So each site has it’s own theme and WordPress wants those themes to work on both single site installs and for sites in a multisite install.
WordPress Out-of-the-Box: Decisions, not Options, but Change with Plugins
While WordPress could have had an option for doing what you want built in the philosophy at WordPress is to make decisions for you instead of giving you a thousand options you’ll feel you need to understand, and then letting plugin developers changes those decisions if needed.
Yes: Central Resources = Better Load Times
Still, it would be nice to be able to do what you are asking as it would improve average load times by leveraging HTTP GET caching for multisites with common themes.
No Need to “Rewrite” URLs
To start, there’s no need to “rewrite” the URLs, just make sure the stylesheet and other resources you want are part of the theme assigned to the main site and then they will be located at the URLs you want.
Creating the “Hook” for style.css
In WordPress you change the out-of-the-box decisions by adding “hooks”; i.e. references to functions that will let you modify values. One such hook is 'stylesheet_uri'
which modifies the URL for the 'style.css'
file that you explicitly referenced. You can copy this code to your theme’s functions.php
file or you can put into the .PHP file of a WordPress plugin you might be writing. Note that I coded this to support either subdomain installs or subdirectory installs:
function normalize_resource_url($url) {
if (MULTISITE) {
$site_url = get_site_url(BLOG_ID_CURRENT_SITE);
if (SUBDOMAIN_INSTALL) {
$url = preg_replace("#^(https?://[^/]+)(/wp-.*\.(css|js))?$#","{$site_url}\\2",$url);
} else {
$url = preg_replace("#^({$site_url})(/[^/]+)(/wp-.*\.(css|js))?$#",'\1\3',$url);
}
}
return $url;
}
Other Resource URLs May Need Their Own Hooks
The code above only modifies the main stylesheet URL; if you need other URLs modified you may not to use other hooks. For example, you may end up needing to use 'style_loader_src'
and/or 'plugins_url'
too but I didn’t have my test system set up with enough use-cases to verify if it’s needed or not:
add_filter('style_loader_src','normalize_resource_url');
add_filter('plugins_url','normalize_resource_url');
Enqueued Scripts and Styles use a base_url
Property
And it turns out that the enqueued scripts and styles use a property named base_url
of the global variables $wp_scripts
and $wp_styles
, respectively to determine their location if a full URL is not passed explicitly by the developer. The property of base_url
is only set once for scripts and left blank for styles; the former is set upon instantiation of a WP_Scripts
object that is then assigned to the global variable $wp_scripts
.
Set the base_url
Property in an Early 'init'
Hook
If you instantiate and assign those early before any calls to wp_enqueue_script()
or wp_enqueue_style()
you can then set the base_url
property immediately after which you can do with an init
hook with a priority of 1
(1
priorities run very early, before most hooks). Here’s the 'init'
hook to accomplish this:
add_filter('init','normalize_base_urls',1);
function normalize_base_urls() {
$GLOBALS['wp_scripts'] = new WP_Scripts();
$GLOBALS['wp_styles'] = new WP_Styles();
$base_url = normalize_resource_url(get_site_url(BLOG_ID_CURRENT_SITE));
$GLOBALS['wp_scripts']->base_url = $base_url;
$GLOBALS['wp_styles']->base_url = $base_url;
}
Or Set the base_url
Property in a Late 'init'
Hook
It’s also possible to use a very high number for the priority for the 'init'
hook (such as 100) after all wp_enqueue_script()
or wp_enqueue_style()
have been called by (higher numbered priority hooks run after those with lower numbers). If so you don’t need to instantiate the globals, just assign the base_url
property:
add_filter('init','normalize_base_urls',100);
function normalize_base_urls() {
$base_url = normalize_resource_url(get_site_url(BLOG_ID_CURRENT_SITE));
$GLOBALS['wp_scripts']->base_url = $base_url;
$GLOBALS['wp_styles']->base_url = $base_url;
}
Might Need to Adjust 'init'
Hook Priorities if Conflicting Plugins
Whichever your preference, I believe either of those two (2) 'init'
hooks will work for you, but if you have plugins that use conflicting priorities you might need to lower the priority number to 0 or less with the first approach, or raise the priority above 100 for the second approach. Again I didn’t have enough use-case test scenarios to 100% verify so let me know if some use cases are not working for you.