- Removed space after cast
- Removed spaces in array index
- Removed double spaces
- Added spaces around string concat
- Fixed mixed tabs and spaces at begin of line
Change-Id: I38e849723f055d2d4c05cba72f5c245a28e8d5da
Nested media queries are not allowed in CSS 2 and not supported
in older browsers.
This reverts commit 11e47561e4.
Bug: T108727
Change-Id: Ibef40e79a5d5e229df8f874b7dea5b590f3f7320
Rewrite OutputPage::addVaryHeader which had a very confusing
structure.
There is one breaking change: the $option argument was declared
as array|null, but the function accepted everything and showed
inconsistent behavior; e.g.
$op->addVaryHeader( 'Foo', 'bar' )
resulted in 'X-Vary-Options: Foo;bar' but
$op->addVaryHeader( 'Foo' )
$op->addVaryHeader( 'Foo', 'bar' )
resulted in 'X-Vary-Options: Foo'. With the patch, non-array
arguments (other than null) result in an error.
Change-Id: Id31d95fe27b01b00ec8a1d7a3996275fc0aacf3c
The $options parameter to OutputPage::addVaryHeader() is undocumented as
to what exactly is supposed to be passed to it. Fix that.
Change-Id: I5fcbb8cf6219c6ab001962a4c2170e1733732426
I don't want to roll this out until our WebPageTest infrastructure is ready
and can show whether or not this is beneficial. I should have indicated this
clearly on the change rather than leave it open, sorry.
This reverts commit b7c0e537eb.
Change-Id: I43e3295873a94da1c2febe2c1a19ad20ca914254
Follows-up d7905627fd which makes all script loading asynchronous,
thus obsoleting this experiment.
We do still have separate top and bottom queues, but that's tracked
under T109837 for later consideration.
Change-Id: I1d6ea47c59bb47977594aff94952a38cc0a9ce34
As the waterfall chart in
http://www.webpagetest.org/result/150817_ER_1E66/1/details/ clearly
demonstrates, the <link rel=stylesheet> for the bottom CSS queue is clearly
render-blocking. The fact that it is in the bottom of <body> only means the
browser discovers it later, when its connection to the server is already
saturated by requests for images that are referenced in the body HTML.
Change-Id: Icf0968c5984f4d3c3dbac1c7e1d539052fa5bd74
Emit styles and scripts in the following order:
* Inline <script>...</script> tags.
* External stylesheets.
* External script tags.
I have attempted this before in I98d383a6, and subsequently reverted (in
I151f74a41) when it failed to show a performance improvement. Our ability
to measure performance were substantially poorer then, so I would like to
give this another try and see if it makes a dent in first render times.
Change-Id: I5e6c79c7041aa77bcdc6130e91e77aa538334c42
Since external CSS is render-blocking, it should be discoverable to the browser
as soon as possible. So move it up to the top of <head>.
Change-Id: I68a6cce2f33ceb7f6461fcbb7323ae13c413aa89
Split the 'mediawiki.legacy.commonPrint' styles into a separate <style>
tag which sets media="print", which will make it a non-render blocking
resource.
Bug: T108413
Change-Id: Ife1d65b31bc79f96d7b89b94fdaeb2babf7ddf40
Follows-up Icba6d7a87b2 which removed this code in the
assumption that they're now taken care of by mw.loader.load.
While that is the case, they are still in the HTML and when earlier
modules require these modules the loader should not initiate a separate
request.
This was especially problematic for the 'user' module which mw.loader
was requesting with a version from the startup module which is
not associated with the current user. This would've caused edits
to a user's personal scripts post-Icba6d7a87b2 to not propagate
correctly. The second request would be ignored by mw.loader since
it implements a module that is already implemented.
This only affected wikis that were manually depending on the 'user'
module from Common.js or a default-loaded gadget.
Bug: T108275
Change-Id: I1b863a3ee23191adaf34f66b58973618487118b2
Page startup:
* Due to the startup module and top queue being asynchronous now,
move client-nojs/client-js class handling to OutputPage to ensure
there is no flashes of wrongly styled or unstyled content.
To preserve compatibility for unsupported browsers, undo the
class swap at runtime after the isCompatible() check.
ResourceLoader startup module:
* Load the startup module with <script async>.
* Use DOM methods instead of 'document.write' to create base module request (jquery|mediawiki).
mw.loader:
* Drop 'async' parameter from mw.loader.load().
* Remove the now-unused code paths for synchronous requests.
OutputPage:
* Drop '$loadCall' parameter from makeResourceLoaderLink().
Asynchronous is now the default and only way to load JavaScript.
This means the 'user' module "conditional document-write scripts"
are now a simple "mw.loader.load( url )" call.
* Fix incorrect @return of makeResourceLoaderLink(). This returns
an array not a string.
* Improve documentation of makeResourceLoaderLink().
* Drop '$inHead' parameter from getScriptsForBottomQueue(). No longer used.
Compatibility with the $wgResourceLoaderExperimentalAsyncLoading
feature is maintained. It just no longer needs to change the
way the queue works since it's always asynchronous. The feature
flag now only controls whether the bottom queue starts at the bottom
or starts at the top.
* Remove jQuery.ready() optimisation.
This was mostly there to avoid the setTimeout() loop jQuery does to detect
dom-ready in IE6/IE7 (which we no longer serve JavaScript at all).
And for a bug in Firefox with document.write (which is no longer used as of
this commit).
Bug: T107399
Change-Id: Icba6d7a87b239bf127a221bc6bc432cfa71a4a72
These were never enabled or used in production and are not
compatible with the upcoming async changes (T107399). To avoid
having to maintain compatibility with this, remove it for now.
The current on-going request to operations for ESI support is unrelated
to this code.
Considered making makeResourceLoaderLink() protected as it's not
used anywhere in @wikimedia Git outside mediawiki-core. And the unit
test actually treated it as protected already. However it's called
in SpecialJavaScriptTest so leaving that as-is for now.
In Icba6d7a87b239 the signature will change again with the removal
of the $loadCall parameter, which is obsolete in an async world
due to document.write being forbidden.
Change-Id: I9f557cc794638ffd15329934865e21e1027f7cfa
Update unit test to account for the internal 'html' prop now
being an array instead of string. And update expected values to
no longer have a trailing line break.
Bug: T27202
Change-Id: I105b6ef2e64ab8b891562e16940edb88592bd415
Instead of having inline statements be plain statements wrapped
in an if-conditional block, convert them to inline functions
pushed into a queue.
The queue is kept in-memory until the startup module is loaded
at which point it transforms into a function that is immediately
invoked.
This is a prerequisite to making the top queue asynchronous.
Until then these functions will just run immediately as they
occur in the HTML after the startup module.
This is based on the previously reverted commit e86e5f8460.
Bug: T107399
Change-Id: Ifb38efca219c10ab973ad4c4ebb21c6a4239b005
Regression from 19a40cd3ad which made the 'site' module load asynchronously,
but the 'user' module was still loaded synchronously which meant it ran before
the site module finished.
Full test script at <https://gist.github.com/Krinkle/5db1d237da241b243485>.
Also:
* This changes the 'user' module to load asynchronously.
* Similar to 19a40cd3ad for site module, this makes the styles for the user
module load twice. Harmless but doesn't look pretty internally.
* Remove the obsolete XXX-comment from 0b5389d98d (r56770).
* Add comment documenting the fact that the 'excludepages' feature can cause
User/common.js and User/vector.js to be mis-ordered when the user previews
common.js edits. This has always been the case (since 2009) and is merely
being documented here.
Bug: T32358
Bug: T106736
Bug: T102077
Change-Id: Id599b6be42613529fb7f4dd3273f36ccadb3a09e
* No longer a dedicated <script> with only=scripts.
This means it creates no extra script request and becomes a versioned
request using data from the startup module.
* No longer in group=site.
This means it collapses into the existing bottom queue.
Not even one dedicated script request, but zero.
* No longer exclude from module storage. This can be cached like any other module.
It was previously excluded because it was already loaded separately.
* Change mw.loader#execute to special-case the 'site' module with $.globalEval.
* Add hack to ensure the styles of the 'site' module still load without
JavaScript, in the top, and after the ResourceLoaderDynamicStyles marker.
This unfortunately stays its own request. Not sure how to avoid that.
Bug: T32358
Bug: T106736
Bug: T102077
Change-Id: I291a8c3aae1a71760bec58161891c1bd77c9b724
This change adds the possibility to enable OOUI out of the parser,
which enabled parser tag functions to easily enable OOUI, if they
need it, for every page view out of the function that handles the
parser tag.
Bug: T106949
Change-Id: If1e139d4f07be98e418e11470794ea42e8a9b2eb
We allow skins to choose the appropriate OOUI theme for it
using 'SkinOOUIThemes', but we ignored that here. Luckily this
was not a problem for the Apex theme (the only one other than
the default, MediaWiki theme), the additional CSS classes
this generated were just ignored.
Depends on Apex and MonoBook skins being updated to use canonical
case for theme names, see I1a88092f0ceb210c642bbee875e368ded3c186f8.
Change-Id: I368804cca141acf9cc15a348d9b7244046395a70
* Add PHP version of NamespaceInputWidget, co-authored by Florian,
which consists of a DropdownInputWidget offering a choice of
namespaces and two CheckboxInputWidgets allowing to also match
associated namespace (talk/content) or to invert the choice.
* Add an incomplete JS version of NamespaceInputWidget, which is only
really functional when infused from the PHP version (it can't
generate the dropdown by itself, for example). Implement some JS to
improve the experience of selecting the "all namespaces" option in
the dropdown (by disabling the checkboxes when this happens).
* Split off a 'mediawiki.widgets.styles' module, which has the basic
styles for PHP widgets which are to be loaded in the head. Make
OutputPage::enableOOUI() also add this module (which should stay
reasonably small).
* Use the new widget in HTMLForm's HTMLSelectNamespace field. It can
be seen in action on Special:LinkSearch, for example.
Co-Authored-By: Florian <florian.schmidt.welzow@t-online.de>
Co-Authored-By: Bartosz Dziewoński <matma.rex@gmail.com>
Change-Id: I5cbfa9d0f6a8641148ce476b7dbe65e9096b4485
Follows-up 91d8a51825.
Having the default variant advertised seems useful, however for
wikis and/or pages that have no variants or translated versions,
outputting this header doesn't seem useful.
https://support.google.com/webmasters/answer/189077 doesn't
justify sending it unconditionally.
To try out, setting $wgLanguageCode = 'zh'; will result in all
pages having hreflang=x-default and all variants. And setting to
'en' or 'de' will result in none of those link tags.
Change-Id: I21cd072534ae1df960209e657b19c96889ece27c
Canonical URLs allow webmasters to indicate the preferred URL form for
accessing some content that can be reached via a multitude of URL patterns.
It is usually (but not always) distinct from the request URL, which may
feature things like aliases and session-specific query parameters.
We currently derive canonical URLs from request URLs, which is backwards:
it is the web application, not the client, that ought to know the canonical
way to refer to some content.
This patch ensures MediaWiki derives a clean canonical URL for all wiki
pages from the request context's title object and action.
For some assurance that this is the correct approach, see:
http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html
This Google blog post identifies Wikia as exemplary in its usage of canonical
URLs. Wikia disregards things like the requested revision ID (oldid=NNN) when
constructing the canonical URL. See, for example:
http://fallout.wikia.com/wiki/Aqua_Pura_delivery_program?oldid=2171222
Wikia goes as far as canonicalizing the action=history to the page view URL.
I think that this is incorrect, because the history and info actions are not
views of the page content, but rather its associated metadata.
This affects all requests where "setArticleRelated" is true. This is typically
all urls that show content (title query, curid, oldid, diff), and all actions
thereof (edit, delete, purge, info, history etc.). It does not apply to
File pages and Special pages.
Bug: T67402
Change-Id: I1549ca056637981a0d751020c634b9fab387f7bc
wfSuppressWarnings() and wfRestoreWarnings() were split out into a
separate library. All usages in core were replaced with the new
functions, and the wf* global functions are marked as deprecated.
Additionally, some uses of @ were replaced due to composer's autoloader
being loaded even earlier.
Ie1234f8c12693408de9b94bf6f84480a90bd4f8e adds the library to
mediawiki/vendor.
Bug: T100923
Change-Id: I5c35079a0a656180852be0ae6b1262d40f6534c4
* Convert existing use of WebResponse::header() for HTTP status headers
to use this new statusHeader() method.
* Extend unit test forFauxResponse.
I'm not calling HttpStatus::header directly in code. We keep the abstraction
layer of WebResponse so that responses can continue to be mocked/fauxed without
affecting the outer HTTP response.
Change-Id: I8a536e16659fa88b54cffa1457efb889efa5fcd6
As of b1e4006b4, the tokens are different on every request.
Caching these is completely useless because the cache entry is
simply unreachable and is extra overhead on every request for
logged-in users to save content to Memcached.
Whether they should be minified at all and whether they perhaps
shouldn't change on every request is a separate matter.
Bug: T84960
Change-Id: I6016e4b01e44e0acbfd6d49f7d99555e2290c9cb
Currently all styles modules added to the page using
addModuleStyles are put into the head, regardless
of their "position" value.
Bug: T97420
Change-Id: Ie4287e17d6f298cc63f42f257b1f67ee36961b77
Modules now track their version via getVersionHash() instead of getModifiedTime().
== Background ==
While some resources have observeable timestamps (e.g. files stored on disk),
many other resources do not. E.g. config variables, and module definitions.
For static file modules, one can e.g. revert one of more files in a module to a
previous version and not affect the max timestamp.
Wiki modules include pages only if they exist. The user module supports common.js
and skin.js. By default neither exists. If a user has both, and then the
less-recently modified one is deleted, the max-timestamp remains unchanged.
For client-side caching, batch requests use "Math.max" on the relevant timestamps.
Again, if a module changes but another module is more recent (e.g. out-of-order
deployment, or out-of-order discovery), the change would not result in a cache miss.
More scenarios can be found in the associated Phabricator tasks.
== Version hash ==
Previously we virtually mapped these variables to a timestamp by storing the current
time alongside a hash of the value in ObjectCache. Considering the number of
possible request contexts (wikis * modules * users * skins * languages) this doesn't
work well. It results in needless cache invalidation when the first time observation
is purged due to LRU algorithms. It also has other minor bugs leading to fewer
cache hits.
All modules automatically get the benefits of version hashing with this change.
The old getDefinitionMtime() and getHashMtime() have been replaced with dummies
that return 1. These functions are often called from getModifiedTime() in subclasses.
For backward-compatibility, their respective values (definition summary and hash)
are now included in getVersionHash directly.
As examples, the following modules have been updated to use getVersionHash directly.
Other modules still work fine and can be updated later.
* ResourceLoaderFileModule
* ResourceLoaderEditToolbarModule
* ResourceLoaderStartUpModule
* ResourceLoaderWikiModule
The presence of hashes in place of timestamps increases the startup module size on
a default MediaWiki install from 4.4k to 5.8k (after gzip and minification).
== ETag ==
Since timestamps are no longer tracked, we need a different way to implement caching
for cache proxies (e.g. Varnish) and web browsers. Previously we used the
Last-Modified header (in combination with Cache-Control and Expires).
Instead of Last-Modified (and If-Modified-Since), we use ETag (and If-None-Match).
Entity tags (new in HTTP/1.1) are much stricter than Last-Modified by default.
They instruct browsers to allow usage of partial Range requests. Since our responses
are dynamically generated, we need to use the Weak version of ETag.
While this sounds bad, it's no different than Last-Modified. As reassured by
RFC 2616 <http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.3> the
specified behaviour behind Last-Modified follows the same "Weak" caching logic as
Entity tags. It's just that entity tags are capable of a stricter mode (whereas
Last-Modified is inherently weak).
== File cache ==
If $wgUseFileCache is enabled, ResourceLoader uses ResourceFileCache to cache
load.php responses. While the blind TTL handling (during the allowed expiry period)
is still maxage/timestamp based, tryRespondNotModified() now requires the caller to
know the expected ETag.
For this to work, the FileCache handling had to be moved from the top of
ResoureLoader::respond() to after the expected ETag is computed.
This also allows us to remove the duplicate tryRespondNotModified() handling since
that's is already handled by ResourceLoader::respond() meanwhile.
== Misc ==
* Remove redundant modifiedTime cache in ResourceLoaderFileModule.
* Change bugzilla references to Phabricator.
* Centralised inclusion of wgCacheEpoch using getDefinitionSummary. Previously this
logic was duplicated in each place the modified timestamp was used.
* It's easy to forget calling the parent class in getDefinitionSummary().
Previously this method only tracked 'class' by default. As such, various
extensions hardcoded that one value instead of calling the parent and extending
the array. To better prevent this in the future, getVersionHash() now asserts
that the '_cacheEpoch' property made it through.
* tests: Don't use getDefinitionSummary() as an API.
Fix ResourceLoaderWikiModuleTest to call getPages properly.
* In tests, the default timestamp used to be 1388534400000 (which is the unix time
of 20140101000000; the unit tests' CacheEpoch). The new version hash of these
modules is "XyCC+PSK", which is the base64 encoded prefix of the SHA1 digest of:
'{"_class":"ResourceLoaderTestModule","_cacheEpoch":"20140101000000"}'
* Add sha1.js library for client-side hash generation.
Compared various different implementations for code size (after minfication/gzip),
and speed (when used for short hexidecimal strings).
https://jsperf.com/sha1-implementations
- CryptoJS <https://code.google.com/p/crypto-js/#SHA-1> (min+gzip: 2.5k)
http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha1.js
Chrome: 45k, Firefox: 89k, Safari: 92k
- jsSHA <https://github.com/Caligatio/jsSHA>
https://github.com/Caligatio/jsSHA/blob/3c1d4f2e/src/sha1.js (min+gzip: 1.8k)
Chrome: 65k, Firefox: 53k, Safari: 69k
- phpjs-sha1 <https://github.com/kvz/phpjs> (RL min+gzip: 0.8k)
https://github.com/kvz/phpjs/blob/1eaab15d/functions/strings/sha1.js
Chrome: 200k, Firefox: 280k, Safari: 78k
Modern browsers implement the HTML5 Crypto API. However, this API is asynchronous,
only enabled when on HTTPS in Chromium, and is quite low-level. It requires boilerplate
code to actually use with TextEncoder, ArrayBuffer and Uint32Array. Due this being
needed in the module loader, we'd have to load the fallback regardless. Considering
this is not used in a critical path for performance, it's not worth shipping two
implementations for this optimisation.
May also resolve:
* T44094
* T90411
* T94810
Bug: T94074
Change-Id: Ibb292d2416839327d1807a66c78fd96dac0637d0
Method similar to SpecialPage::outputHeader() to avoid registering
tons of system messages and to have -summary and -helppage tidily
listed together in Special:AllMessages by default.
Bug: T45591
Change-Id: Ic849dde00be7379c1909a8486cf20f48c5aea5cf
Benefits:
* Full per-language icons support. Icons that differ for each language
(such as the 'Bold' icon) will now always display correctly
according to user interface language, even on old browsers.
* MediaWiki UI icons support. When the 'mediawiki.ui.icon' module is
loaded, you can use syntaxes such as below to display any OOUI icons
(from the packs that were loaded) without involving OOUI itself.
<div class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check">OK</div>
<div class="mw-ui-icon mw-ui-icon-after mw-ui-icon-check">OK</div>
<div class="mw-ui-icon mw-ui-icon-element mw-ui-icon-check">OK</div>
Summary of changes:
* Resources.php:
* Remove icons CSS files. Include image data JSON files instead.
* Split the images from 'oojs-ui.styles' module to separate ones.
* OutputPage: Update enableOOUI() method for newly split modules.
* ResourceLoaderImageModule: Make it possible to load image data from
a JSON file.
* update-oojs-ui.sh: Copy source files rather than distribution for
icon packs.
This is not an improvement when it comes to code quality, though :(
Issues include some nasty code duplication, using "source code" (image
definitions) from OOUI rather than just distribution files, and hacky
methods to load image data from JSON files live.
Bug: T92551
Change-Id: Id369ecaec7048dcf68ba1e4df748362760533782