diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 8791a941453..505907de299 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -4425,20 +4425,24 @@ $wgResourceLoaderSources = []; $wgResourceBasePath = null; /** - * Maximum time in seconds to cache resources served by ResourceLoader. - * Used to set last modified headers (max-age/s-maxage). + * How long a CDN or browser may cache a ResourceLoader HTTP response. * - * Following options to distinguish: - * - versioned: Used for modules with a version, because changing version - * numbers causes cache misses. This normally has a long expiry time. - * - unversioned: Used for modules without a version to propagate changes - * quickly to clients. Also used for modules with errors to recover quickly. - * This normally has a short expiry time. + * Maximum time in seconds. Used for the `max-age` and `s-maxage` Cache-Control + * headers. * - * Expiry time for the options to distinguish: - * - server: Squid/Varnish but also any other public proxy cache between the - * client and MediaWiki. - * - client: On the client side (e.g. in the browser cache). + * Valid keys: + * + * - versioned: Used for URLs carrying a "version" parameter. + * This applies to the bulk of load.php transfers, and may have a long cache + * duration (e.g. weeks or months), because a change in the module bundle will + * naturally produce a different URL and thus automatically bust the cache. + * + * - unversioned: Used for URLs that must not carry a "version" parameter. + * This includes the startup manifest and controls how quickly changes (in + * the module registry, dependency tree, and module version) will propagate + * to clients. This should have a short cache duration (e.g. minutes). + * + * @since 1.35 */ $wgResourceLoaderMaxage = [ 'versioned' => 30 * 24 * 60 * 60, // 30 days diff --git a/includes/resourceloader/ResourceLoader.php b/includes/resourceloader/ResourceLoader.php index 359b4fe6747..680f030b316 100644 --- a/includes/resourceloader/ResourceLoader.php +++ b/includes/resourceloader/ResourceLoader.php @@ -57,62 +57,54 @@ use Wikimedia\WrappedString; * @since 1.17 */ class ResourceLoader implements LoggerAwareInterface { - /** @var Config */ - protected $config; - /** @var MessageBlobStore */ - protected $blobStore; - /** @var DependencyStore */ - protected $depStore; + /** @var int */ + public const CACHE_VERSION = 9; + /** @var string JavaScript / CSS pragma to disable minification. * */ + public const FILTER_NOMIN = '/*@nomin*/'; - /** @var LoggerInterface */ - private $logger; - - /** @var HookContainer */ - private $hookContainer; - - /** @var HookRunner */ - private $hookRunner; - - /** @var ResourceLoaderModule[] Map of (module name => ResourceLoaderModule) */ - protected $modules = []; - /** @var array[] Map of (module name => associative info array) */ - protected $moduleInfos = []; - /** - * Associative array mapping framework ids to a list of names of test suite modules - * like [ 'qunit' => [ 'mediawiki.tests.qunit.suites', 'ext.foo.tests', ... ], ... ] - * @var array - */ - protected $testModuleNames = []; - /** @var string[] List of module names that contain QUnit test suites */ - protected $testSuiteModuleNames = []; - /** @var array Map of (source => path); E.g. [ 'source-id' => 'http://.../load.php' ] */ - protected $sources = []; - /** @var array Errors accumulated during current respond() call */ - protected $errors = []; - /** @var string[] Extra HTTP response headers from modules loaded in makeModuleResponse() */ - protected $extraHeaders = []; - - /** @var array Map of (module-variant => buffered DependencyStore updates) */ - private $depStoreUpdateBuffer = []; - - /** @var array Styles that are skin-specific and supplement or replace the - * default skinStyles of a FileModule. See $wgResourceModuleSkinStyles. - */ - private $moduleSkinStyles = []; + /** @var string */ + private const RL_DEP_STORE_PREFIX = 'ResourceLoaderModule'; + /** @var int How long to preserve indirect dependency metadata in our backend store. */ + private const RL_MODULE_DEP_TTL = BagOStuff::TTL_WEEK; /** @var int|null */ protected static $debugMode = null; - /** @var int */ - public const CACHE_VERSION = 9; + /** @var Config */ + private $config; + /** @var MessageBlobStore */ + private $blobStore; + /** @var DependencyStore */ + private $depStore; + /** @var LoggerInterface */ + private $logger; + /** @var HookContainer */ + private $hookContainer; + /** @var HookRunner */ + private $hookRunner; - /** @var string */ - private const RL_DEP_STORE_PREFIX = 'ResourceLoaderModule'; - /** @var int Expiry (in seconds) of indirect dependency information for modules */ - private const RL_MODULE_DEP_TTL = BagOStuff::TTL_WEEK; - - /** @var string JavaScript / CSS pragma to disable minification. * */ - public const FILTER_NOMIN = '/*@nomin*/'; + /** @var ResourceLoaderModule[] Map of (module name => ResourceLoaderModule) */ + private $modules = []; + /** @var array[] Map of (module name => associative info array) */ + private $moduleInfos = []; + /** @var string[] List of module names that contain QUnit test suites */ + private $testSuiteModuleNames = []; + /** @var string[] Map of (source => path); E.g. [ 'source-id' => 'http://.../load.php' ] */ + private $sources = []; + /** @var array Errors accumulated during a respond() call. Exposed for testing. */ + protected $errors = []; + /** + * @var string[] Buffer for extra response headers during a makeModuleResponse() call. + * Exposed for testing. + */ + protected $extraHeaders = []; + /** @var array Map of (module-variant => buffered DependencyStore updates) */ + private $depStoreUpdateBuffer = []; + /** + * @var array Styles that are skin-specific and supplement or replace the + * default skinStyles of a FileModule. See $wgResourceModuleSkinStyles. + */ + private $moduleSkinStyles = []; /** * Load information stored in the database and dependency tracking store about modules @@ -238,8 +230,11 @@ class ResourceLoader implements LoggerAwareInterface { } /** - * Register core modules and runs registration hooks. - * @param Config $config + * @param Config $config Required configuration: + * - EnableJavaScriptTest + * - LoadScript + * - ResourceLoaderMaxage + * - UseFileCache * @param LoggerInterface|null $logger [optional] * @param DependencyStore|null $tracker [optional] */ @@ -248,11 +243,10 @@ class ResourceLoader implements LoggerAwareInterface { LoggerInterface $logger = null, DependencyStore $tracker = null ) { - $this->logger = $logger ?: new NullLogger(); - $services = MediaWikiServices::getInstance(); - $this->config = $config; + $this->logger = $logger ?: new NullLogger(); + $services = MediaWikiServices::getInstance(); $this->hookContainer = $services->getHookContainer(); $this->hookRunner = new HookRunner( $this->hookContainer ); diff --git a/tests/phpunit/ResourceLoaderTestCase.php b/tests/phpunit/ResourceLoaderTestCase.php index d17822b0398..1ca47d2149c 100644 --- a/tests/phpunit/ResourceLoaderTestCase.php +++ b/tests/phpunit/ResourceLoaderTestCase.php @@ -56,8 +56,12 @@ abstract class ResourceLoaderTestCase extends MediaWikiIntegrationTestCase { public static function getSettings() { return [ - // For ResourceLoader::inDebugMode since it doesn't have context + // For ResourceLoader class 'ResourceLoaderDebug' => true, + 'LoadScript' => '/w/load.php', + 'EnableJavaScriptTest' => false, + // For ResourceLoader::respond() - TODO: Inject somehow T32956 + 'UseFileCache' => false, // For ResourceLoaderModule 'ResourceLoaderValidateJS' => false, @@ -71,17 +75,11 @@ abstract class ResourceLoaderTestCase extends MediaWikiIntegrationTestCase { 'ResourceBasePath' => '/w', 'ParserEnableLegacyMediaDOM' => true, - // For ResourceLoader::expandUrl() + // For ResourceLoader::getSiteConfigSettings and ResourceLoaderStartUpModule 'Server' => 'https://example.org', - // For ResourceLoaderStartUpModule and ResourceLoader::__construct() 'ScriptPath' => '/w', 'Script' => '/w/index.php', - 'LoadScript' => '/w/load.php', - 'EnableJavaScriptTest' => false, 'ResourceLoaderEnableJSProfiler' => false, - - // For ResourceLoader::respond() - TODO: Inject somehow T32956 - 'UseFileCache' => false, ]; }