* Added some release notes for ResourceLoader globals.
* Changed when OutputPage appends timestamps to style/script-only requests - now they are only made into versioned requests if the module is a ResourceLoaderWikiModule or a ResourceLoaderUserPreferencesModule - because they might be changed on-wiki and require immediate feedback. This would only affect logged-in users however, as cached pages will contain the latest version number as of the time they were generated. This strategy may need to be adjusted to work with ESI to add version parameters to everything all the time, but this at least presents a reasonable fallback in the event that ESI is not setup.
$wgUseMemCached, $wgDisableSearchContext, $wgColorErrors,
$wgUseZhdaemon, $wgZhdaemonHost and $wgZhdaemonPort.
* (bug 24408) The include_path is not modified in the default LocalSettings.php
-* $wgVectorExtraStyles has been removed, and is no longer in use.
+* $wgVectorExtraStyles was removed, and is no longer in use.
+* $wgLoadScript was added to specify alternative locations for ResourceLoader
+ requests.
+* $wgResourceLoaderVersionedClientMaxage, $wgResourceLoaderVersionedServerMaxage,
+ $wgResourceLoaderUnversionedClientMaxage and
+ wgResourceLoaderUnversionedServerMaxage were added to specify maxage and
+ smaxage times for responses from ResourceLoader based on whether the request's
+ URL contained a version parameter or not.
=== New features in 1.17 ===
* (bug 10183) Users can now add personal styles and scripts to all skins via
$wgClockSkewFudge = 5;
/**
- * Maximum time in seconds to cache resources served by the resource loader on
- * the client side (e.g. in the browser cache).
+ * Maximum time in seconds to cache versioned resources served by the resource
+ * loader on the client side (e.g. in the browser cache).
*/
-$wgResourceLoaderClientMaxage = 30*24*60*60; // 30 days
+$wgResourceLoaderVersionedClientMaxage = 30 * 24 * 60 * 60; // 30 days
/**
- * Maximum time in seconds to cache resources served by the resource loader on
- * the server side. This means Squid/Varnish but also any other public proxy
- * cache between the client and MediaWiki.
+ * Maximum time in seconds to cache versioned resources served by the resource
+ * loader on the server side. This means Squid/Varnish but also any other public
+ * proxy cache between the client and MediaWiki.
*/
-$wgResourceLoaderServerMaxage = 30*24*60*60; // 30 days
+$wgResourceLoaderVersionedServerMaxage = 30 * 24 * 60 * 60; // 30 days
+
+/**
+ * Maximum time in seconds to cache unversioned resources served by the resource
+ * loader on the client.
+ */
+$wgResourceLoaderUnversionedClientMaxage = 5 * 60; // 5 minutes
+
+/**
+ * Maximum time in seconds to cache unversioned resources served by the resource
+ * loader on the server. This means Squid/Varnish but also any other public
+ * proxy cache between the client and MediaWiki.
+ */
+$wgResourceLoaderUnversionedServerMaxage = 5 * 60; // 5 minutes
/**
* Enable data URL embedding (experimental). This variable is very temporary and
if ( $group === 'user' ) {
$query['user'] = $wgUser->getName();
}
- $context = new ResourceLoaderContext( new FauxRequest( $query ) );
+ // Users might change their stuff on-wiki like site or user pages, or user preferences; we need to find
+ // the highest timestamp of these user-changable modules so we can ensure cache misses upon change
$timestamp = 0;
foreach ( $modules as $name ) {
- if ( $module = ResourceLoader::getModule( $name ) ) {
- $timestamp = max( $timestamp, $module->getModifiedTime( $context ) );
+ $module = ResourceLoader::getModule( $name );
+ if (
+ $module instanceof ResourceLoaderWikiModule ||
+ $module instanceof ResourceLoaderUserPreferencesModule
+ ) {
+ $timestamp = max(
+ $timestamp,
+ $module->getModifiedTime( new ResourceLoaderContext( new FauxRequest( $query ) ) )
+ );
}
}
- $query['version'] = wfTimestamp( TS_ISO_8601, round( $timestamp, -2 ) );
+ // Add a version parameter if any of the modules were user-changable
+ if ( $timestamp ) {
+ $query['version'] = wfTimestamp( TS_ISO_8601, round( $timestamp, -2 ) );
+ }
// Make queries uniform in order
ksort( $query );
// Automatically select style/script elements
* Dynamic JavaScript and CSS resource loading system
*/
class ResourceLoader {
+
/* Protected Static Members */
// @var array list of module name/ResourceLoaderModule object pairs
* @param $context ResourceLoaderContext object
*/
public static function respond( ResourceLoaderContext $context ) {
+ global $wgResourceLoaderVersionedClientMaxage, $wgResourceLoaderVersionedServerMaxage;
+ global $wgResourceLoaderUnversionedServerMaxage, $wgResourceLoaderUnversionedClientMaxage;
+
// Split requested modules into two groups, modules and missing
$modules = array();
$missing = array();
}
}
- // Calculate the mtime and caching maxages for this request. We need this, 304 or no 304
- $mtime = 1;
- $maxage = PHP_INT_MAX;
- $smaxage = PHP_INT_MAX;
+ // If a version wasn't specified we need a shorter expiry time for updates to propagate to clients quickly
+ if ( is_null( $context->getVersion() ) ) {
+ $maxage = $wgResourceLoaderUnversionedClientMaxage;
+ $smaxage = $wgResourceLoaderUnversionedServerMaxage;
+ }
+ // If a version was specified we can use a longer expiry time since changing version numbers causes cache misses
+ else {
+ $maxage = $wgResourceLoaderVersionedClientMaxage;
+ $smaxage = $wgResourceLoaderVersionedServerMaxage;
+ }
+ // To send Last-Modified and support If-Modified-Since, we need to detect the last modified time
+ $mtime = 1;
foreach ( $modules as $name ) {
$mtime = max( $mtime, self::$modules[$name]->getModifiedTime( $context ) );
- $maxage = min( $maxage, self::$modules[$name]->getClientMaxage() );
- $smaxage = min( $smaxage, self::$modules[$name]->getServerMaxage() );
- }
-
- // Output headers
- if ( $context->getOnly() === 'styles' ) {
- header( 'Content-Type: text/css' );
- } else {
- header( 'Content-Type: text/javascript' );
}
+ header( 'Content-Type: ' . ( $context->getOnly() === 'styles' ? 'text/css' : 'text/javascript' ) );
header( 'Last-Modified: ' . wfTimestamp( TS_RFC2822, $mtime ) );
- $expires = wfTimestamp( TS_RFC2822, min( $maxage, $smaxage ) + time() );
header( "Cache-Control: public, max-age=$maxage, s-maxage=$smaxage" );
- header( "Expires: $expires" );
+ header( 'Expires: ' . wfTimestamp( TS_RFC2822, min( $maxage, $smaxage ) + time() ) );
- // Check if there's an If-Modified-Since header and respond with a 304 Not Modified if possible
+ // If there's an If-Modified-Since header, respond with a 304 appropriately
$ims = $context->getRequest()->getHeader( 'If-Modified-Since' );
-
- if ( $ims !== false && wfTimestamp( TS_UNIX, $ims ) == $mtime ) {
+ if ( $ims !== false && $mtime >= wfTimestamp( TS_UNIX, $ims ) ) {
header( 'HTTP/1.0 304 Not Modified' );
header( 'Status: 304 Not Modified' );
return;
protected $user;
protected $debug;
protected $only;
+ protected $version;
protected $hash;
/* Methods */
$this->user = $request->getVal( 'user' );
$this->debug = $request->getBool( 'debug' ) && $request->getVal( 'debug' ) === 'true';
$this->only = $request->getVal( 'only' );
+ $this->version = $request->getVal( 'version' );
// Fallback on system defaults
if ( !$this->language ) {
$this->skin = $wgDefaultSkin;
}
}
-
+
public function getRequest() {
return $this->request;
}
return $this->only;
}
+ public function getVersion() {
+ return $this->version;
+ }
+
public function shouldIncludeScripts() {
return is_null( $this->only ) || $this->only === 'scripts';
}
public function getHash() {
return isset( $this->hash ) ?
$this->hash : $this->hash = implode( '|', array(
- $this->language, $this->direction, $this->skin, $this->user, $this->debug, $this->only
+ $this->language, $this->direction, $this->skin, $this->user, $this->debug, $this->only, $this->version
) );
}
}
\ No newline at end of file
$this->name = $name;
}
- /**
- * The maximum number of seconds to cache this module for in the
- * client-side (browser) cache. Override this only if you have a good
- * reason not to use $wgResourceLoaderClientMaxage.
- *
- * @return Integer: cache maxage in seconds
- */
- public function getClientMaxage() {
- global $wgResourceLoaderClientMaxage;
- return $wgResourceLoaderClientMaxage;
- }
-
- /**
- * The maximum number of seconds to cache this module for in the
- * server-side (Squid / proxy) cache. Override this only if you have a
- * good reason not to use $wgResourceLoaderServerMaxage.
- *
- * @return Integer: cache maxage in seconds
- */
- public function getServerMaxage() {
- global $wgResourceLoaderServerMaxage;
- return $wgResourceLoaderServerMaxage;
- }
-
/**
* Get whether CSS for this module should be flipped
*/
return $this->modifiedTime[$hash];
}
- public function getClientMaxage() {
- return 300; // 5 minutes
- }
-
- public function getServerMaxage() {
- return 300; // 5 minutes
- }
-
public function getFlip( $context ) {
global $wgContLang;