Make WordPress Core

Opened 18 years ago

Closed 9 years ago

Last modified 4 weeks ago

#3372 closed feature request (maybelater)

Consolidated JavaScript/CSS Plugin API

Reported by: robertaccettura's profile robertaccettura Owned by:
Milestone: Priority: lowest
Severity: normal Version: 2.1
Component: Script Loader Keywords:
Focuses: Cc:


WordPress plugins are great, they really are. One problem with them is they often include their own styles and scripts. The problem here is that several plugins with useful features mean a browser needs to download 10+ javascripts and stylesheets. This isn't good for page load. It's awful. See:

My suggestion would be an API that allows all plugin/css to be included in 1 PHP generated CSS and Javascript. This would drastically consolidate requests. For performance reasons it should ideally be cached so that it's only regenerated when a plugin is loaded/reloaded.

This is becoming a bigger issue as plugins become more common and useful. I hope a solution is found that gives plugin authors the freedom they need, and blog owners the performance they want, without having to sacrifice features. I think channeling all the requests into 1 JS and 1 CSS file would achieve that. They could use a numerical ranking system to calculate position in the file (to avoid conflicts) similar to how (iirc) filter work.

Attachments (1)

combine.php (2.4 KB) - added by DD32 16 years ago.

Download all attachments as: .zip

Change History (46)

#1 @Viper007Bond
18 years ago

  • Milestone set to 2.2
  • Priority changed from normal to low
  • Severity changed from normal to minor
  • Version set to 2.1

Not a bad idea IMO, but large changes such as this are best discussed via the wp-hackers mailing list first. Much easier to discuss, propose solutions, etc. :)

#2 follow-up: @RuddO
18 years ago

This is a GREAT idea!

And it would also free plugin writers from having to do the wp-content/plugins/plugin_basename(FILE) chicanery.

All that's needed, in my opinion, would be functions "plugin_add_css", "plugin_add_js", and then on wp_head() WP can inject an URL that points to an internal file which releases the added CSS and JS. This function could be loaded as part of the plugin initialization trigger (can't recall its name right now).

This has definitive advantages to feeding JS and CSS inline on wp_head() directly.

Note that, due to the nature of the requests, it's impossible to make distinctions based on which page the reader is visiting, because the custom CSS and JS is released to the browser separately from the original request.

#3 @foolswisdom
18 years ago

robertaccettura, thanks for participating in WordPress! I love what you have done with Mozilla particularly Report a Website.

Viper007Bond suggestion is a good one, variations of this topic have come up before, but like Mozilla's Bugzilla having an enhancement ticket seldom moves the idea into implementation, so please don't let that frustrate you or leave it at that.

#4 @ryan
18 years ago

2.1 has a script loader API.

It doesn't group scripts into one big script, however. Extending it to do that probably wouldn't be too hard, though, if someone wants to take a crack at it.

#5 in reply to: ↑ 2 @robertaccettura
18 years ago

Replying to RuddO:

Note that, due to the nature of the requests, it's impossible to make distinctions
based on which page the reader is visiting, because the custom CSS and JS is released
to the browser separately from the original request.

Ah but you can. i.e.

<script type="text/javascript" src="/wp-javascript.php?path=/archives/2006/11/22/monkey-love/"></script>

<script type="text/javascript" src="/wp-javascript.php?path=/"></script>

#6 @foolswisdom
17 years ago

  • Milestone changed from 2.2 to 2.4

#7 @darkdragon
16 years ago

  • Keywords hunted-sendnext added

Suggest candidate for next release.

#8 @lloydbudd
16 years ago

  • Keywords hunted-sendnext removed
  • Milestone changed from 2.4 to 2.6

#9 @jacobsantos
16 years ago

  • Milestone changed from 2.7 to 2.8

You know, it would be nice.

#10 @DD32
16 years ago

One of the problems with consolodating everything (particually styles) is that they're not all unique, In the sense that some styles conflict between stylesheets..

Theres also Conditionals which need to be taken into consideration for styles, Then theres styles which are only registered if they're needed on a page.

Then theres the extra load on the webserver having to load all of WordPress's files, where before it could mearly load half a dozen static files (Which load incredibly fast compared to PHP).

Scripts are a bit easier to combine, But still can have conflicts.

If you wish to have the files compressed, Most webservers come with modules/functions to automatically compress the static files with gzip.

Theres also Gears which is caching scripts and styles locally for users..

And now theres this plugin i just wrote up to do the job.. It doesnt support ltr styles, It breaks the CSS on every page, and most Javascript refuse to load, and it doesnt compress (unless PHP is set to auto-compress), It was mearly to see what can be done, and as a base for someone else to work off potentially. (See Attachment)

16 years ago

#11 @xenlab
15 years ago

This is a great idea. On other systems that I've done this with, the bandwidth and HTTP request savings were ENORMOUS! For high traffic sites (1M+ per day) you'd be silly not to do this, since saving those extra requests mean you can serve more traffic with the same hardware stack. I've seen it. It really is amazing.

With the evangelizing aside, I want to address a couple of comments, and then add my own two cents...

First styles never conflict, they cascade. The order the files are added should be something that is respected. I believe this is already being taken into account. If you are using conditionals, they will probably go under the aggregated file and pick up the cascade (applying only to IE) after the fact, to fix IE's lovely bugs.

If scripts are conflicting, then there is a problem long before the aggregation takes hold. All this should do is concatenate the files, one after the other, into one 'super' file, so that is only one file to be served up.

This shouldn't be done dynamically on each page load. The file should be created and cached to disk. This way the file can be pre-generated on the first request, but fetched from disk on all other requests.

While there would be a little processing overhead upfront, I think it should md5 the file contents and use this hash as the file name. This way if new files are added, they could be checked against the hash and regen'd as needed. This has the added benefit of always serving a fresh aggregate file if the contents have changed, forcing user agents to update their local cache because the md5 hash file name would change. Speed tests would need to be performed as this may be more trouble than its worth, but md5'ing at least the original file names would be a good way to come up with a naming convention.

In addition you should include a way to for scripts to be able to 'target' wp_head or wp_footer. This way you can add some scripts in the header if that's whats needed but put the majority of scripts near the footer so that they fire after the page has loaded. This could be easily accomplished with a paramater to the add_js function.

And last but not least, we should be gziping the file that's output.

#12 @projct
15 years ago

I've been continuing some work on this based on DD32's plugin -

#13 @jacobsantos
15 years ago

There are two more plugins, WP Speedy and mine, when I get it up.

I think this is really Plugin material, but it would be nice if WordPress made it easier to do in plugins.

#14 @jacobsantos
15 years ago

  • Keywords needs-patch added

#15 @jacobsantos
15 years ago

  • Type changed from enhancement to feature request

#16 @djr
15 years ago

  • Cc djr added

Would love to see this, as Yslow ( is constantly complaining about too many requests.

#17 @ryan
15 years ago

  • Milestone changed from 2.8 to Future Release

Core scripts now support concatention. Doing this for plugins will require some more work. Moving to future release.

#18 @Denis-de-Bernardy
15 years ago

  • Milestone changed from Future Release to 2.9
  • Priority changed from low to high
  • Resolution set to duplicate
  • Severity changed from minor to major
  • Status changed from new to closed

let's bump the priority somewhat. this gets really annoying on sites with loads of assets.

#19 @Denis-de-Bernardy
15 years ago

  • Resolution duplicate deleted
  • Status changed from closed to reopened

woops. shouldn't be closed :P

#20 @demetris
15 years ago

  • Cc dkikizas@… added

#21 @Denis-de-Bernardy
15 years ago

  • Keywords dup added

adding keywords, I'm sure there's a dup or two of this one

#22 @Denis-de-Bernardy
15 years ago

  • Keywords dup removed

#23 @hakre
15 years ago

  • Keywords reporter-feedback added

Okay, nice Idea but this ticket is missing a working concept and a concrete implementation suggestion at least. The main description is mainly "goals" leaving the whole ticket foggy. I suggest as won't fix because the suggest code is a plugin (therefore there is no need that this goes into the core) _and_ it's not working as reported. This needs first of all reporters feedback. Suggestions to existing concepts etc. For example this can mean that WordPress should become it's own MVC implementation.

Close because of lack of traktion?

#24 @hakre
15 years ago

  • Component changed from Optimization to JavaScript
  • Priority changed from high to lowest
  • Severity changed from major to trivial

#25 follow-up: @dd32
15 years ago

  • Keywords reporter-feedback removed
  • Milestone changed from 2.9 to Future Release

The fact that the code was presented as a plugin means nothing, It was simply the easiest way to show it.

At present, This is done for core scripts and styles already. Expanding it to non-core files however isnt exactly the simplest thing to do.. But can potentially be done. I believe there -may- be another ticket elsewhere asking for that, not 100%.

I'm setting this back to Future Release pending a patch or developer/commiter actually working on it due to it being a feature request/enhancement.

#26 in reply to: ↑ 25 @hakre
15 years ago

Replying to dd32:

At present, This is done for core scripts and styles already. Expanding it to non-core files however isnt exactly the simplest thing to do.. But can potentially be done. I believe there -may- be another ticket elsewhere asking for that, not 100%.

You mean the script loader thingy? Plugin authors can add their CSS and scripts already, too. So this is actually not an issue any longer, right?

#27 @dd32
15 years ago

You mean the script loader thingy? Plugin authors can add their CSS and scripts already, too. So this is actually not an issue any longer, right?

The script loader can only compress/combine core files, Whilst plugin and theme authors are suggested to use the script loader, it'll only output an item in the head, not actually add it to the compress/combine lists (Due to the way that the script loader is a separate component, It doesnt load WordPress&Plugins so as to reduce memory footprint)

#28 @hakre
15 years ago

Well there are different paths to follow in optimization, some suggest to link a javscript file that loads larger modules only on demand then. Are such improvements in the scope of this ticket as well?

#29 @westonruter
15 years ago

  • Cc westonruter added
  • Severity changed from trivial to normal

I just submitted a plugin to the directory called “Optimize Scripts” which accomplishes most of what is discussed in this ticket, namely:

  1. Concatenates enqueued scripts together.
  2. Respects head and footer groups.
  3. Minifies code using Google's Closure Compiler.
  4. Caches the concatenated/minified code and rebuilds it only when one of its source scripts expires or changes.
  5. Filename for concatenated/minified script is the md5 of all the handles concatenated together (thus if an additional handle is provided, a new concatenated script is generated).
  6. Provides a filter to limit which scripts get concatenated (i.e. jQuery on should be left alone); by default, all scripts on local host are concatenated, and remote scripts are left alone.
  7. Removes the default 'ver' query parameter which WordPress adds to every script src if no version argument is supplied on wp_enqueue/register_script: this is important for Web-wide caching of scripts loaded from, for example. When registering new scripts, pass the filemtime in as the version so that whenever a file changes, the concatenated script will be regenerated.

And there are more options. The current alpha-version of the plugin can be found at:

Once the plugin is approved for the directory, it'll be found at:

For example, consider the following code:

wp_deregister_script('jquery');	//remove locally jQuery in favor of Google's
//since no verion provided, no ver query param will be added to script@src
wp_enqueue_script('jquery', '');
   true //in_footer
   true //in_footer

Without this plugin, the previous code would be generated by WordPress as:

<script src=""></script>
<script src=""></script>
<script src=""></script>

But with this plugin enabled, the output would be as follows:

<script src=""></script>
<script src=""></script>

I'd love to get your feedback, suggestions, and contributions to make the code better so that we can boost WordPress frontend performance.

#30 @voyagerfan5761
15 years ago

  • Cc voyagerfan5761+wptrac@… added

#31 @rspindel
14 years ago

  • Cc rspindel added

#32 @abischof
13 years ago

  • Cc abischof added

#33 @azizur
13 years ago

  • Cc azizur added

#34 @dangayle
12 years ago

  • Cc dangayle@… added
  • Keywords dev-feedback added

This is still a good idea, and becoming ever more so as mobile sites require higher performance from our WP installs. I have a client with something like 4 scripts and 10 styles being enqueued, all of which are required but slow the site down a bit.

#35 @stephenh1988
12 years ago

  • Cc stephen@… added

#36 @wvega
12 years ago

  • Cc wvega added

#37 @CaptainN
12 years ago

  • Cc CaptainN added

Is there any interest in a patch for this?

My stab at the things at a minimums to address for theme side use of concatenation:

  • A new argument for wp_register_script, wp_enqueue_script, etc. at the end of the list - $allowConcat, defaulted to false. This would allow scripts to opt in to concatenation. Many (all?) of the core libs are concat safe, so they could be set to true by default.
  • unit tests.

With this data in place the existing WP_Scripts concat stuff could be used (with maybe some minor edits) to implement the rest.

#38 @jasonrhodes
11 years ago

  • Cc jason.matthew.rhodes@… added

#39 @retlehs
11 years ago

  • Cc retlehs added

#40 @joshbroton
11 years ago

While there are plugins that accomplish this, as the web moves more to mobile, it becomes increasingly important to concatenate and minify JS/CSS. We'd be helping the entire Internet by making this core functionality.

I'd love to see another parameter of the wp_enqueue_script() function: $in_concat_group, that allows the developer to specify a group that the script gets added to. WordPress could then cache that concatenated version until a script is replaced or an admin requests a re-concat.

#41 @rickalee
11 years ago

  • Cc ricka@… added

Number of JS/CSS requests in themes/plugins are simply getting out of hand.

I would love to see this worked into core as part of enqueue. Better WordPress Minify plugin does the trick if you are a diligent developer and know which files to manually exclude such as CSS files containing path references to @font-face and admin-bar from concatenation.

An additional argument to wp_register_script and wp_enqueue_script seems the most straightforward approach. Integrate best practice into Underscores functions and the community will quickly start adoption.

#42 @mboynes
11 years ago

  • Cc mboynes@… added

#43 @nacin
10 years ago

  • Component changed from JavaScript to Script Loader
  • Focuses javascript performance added

#44 @chriscct7
9 years ago

  • Focuses javascript performance removed
  • Keywords needs-patch dev-feedback removed
  • Milestone Future Release deleted
  • Resolution set to maybelater
  • Status changed from reopened to closed

No movement in almost 2 years. Closing as maybelater. Feel free to reopen when renewed interest (ideally with a patch) emerges, but this feels like plugin territory at this point

This ticket was mentioned in Slack in #core-performance by swissspidy. View the logs.

4 weeks ago

Note: See TracTickets for help on using tickets.