This page documents an officialWikimedia development policy. There is no current mechanism to make changes, as theTechCom RFC process is defunct. |
| Development policies |
|---|
| See also |
| Development guidelines |
| v·d·e |
Thestable interface policy for MediaWiki frontend code (CSS, JavaScript and HTML) defines what parts ofthe software are considered stable and safe for use by browser-based code from other components.
For guidelines on PHP, seestable interface policy.The frontend stable interface policy is maintained separately from the PHP stable interface policy due to the difference in audience and scope (e.g. this policy also addresses gadget developers).
This document applies to all developers of browser-based code that relies on MediaWiki.The scope of this policy regardswiki-hosted code that runs on one of theWikimedia projects.The policy does not apply to gadgets running on third-party MediaWiki instances.
Gadgets developers on Wikimedia Foundation projects should additionally considerRecommendations for gadget developers on Wikimedia wikis as a complement to this.
mw object to obtain or modify existing elements on the page rather than DOM queries. If there is no utility function that satisfies your use case, please let us know.mw- given they may historically have been used by developers of wiki-based code.mw object, since it must be maintained as a stable API unless it has been marked as @private.mw object andmw.hook signatures compatible for callers. Follow thedeprecation process for breaking changes.All ResourceLoader modules inside MediaWiki coreMUST be considered stable to load and must follow thedeprecation process, unless marked as deprecated.For modules provided by a MediaWiki extension or skin, there is no need to follow the deprecation process, unless you have explicitly designated a module as for consumption by other extensions, skins, or gadgets.
JavaScript code that is considered stableMUST follow thedeprecation process.This includes:
@stable tag. If a property or module is marked as stable that indicates all of its public methods are also stable.// Provider of mediawiki.foo.module:/*** mediawiki.foo.module* @stable for use inside gadgets and extensions*/module.exports={stableMethod};// Consumer of mediawiki.foo.module:varfoo=require('mediawiki.foo.module');foo.stableMethod();
mw object, that has not been documented as@private, regardless of how the code is added (extension, skin or wiki-based code), even if the code has not been marked as@stable.mw.mobileFrontend={/** * Even though this code is on the global mw method it has been documented as * private so it is not stable. * @private */privateMethod:function(){...},/** * If the method is on the mw object and not marked as private, it can be considered * stable. If the provider does not want to consider the method private, the method * must follow the deprecation process. */stableMethod:function(){this.privateMethod();}};// consumer of mw public methodmw.mobileFrontend.stableMethod();
mw.hook object in MediaWiki core codeSHOULD be considered stable unless marked as@private or@internal. Consumers can expect that the hook will be fired in the circumstances described in its documentation.// Hooks are stable.// The firing of a hook without a @private declaration means the hook is stable and subscribers are welcomed:mw.hook('foo').fire(alert,'I am stable');/** @private not a stable API */mw.hook('foo.private').fire(alert,'I am not stable do not use me!');// The following code is safe to use given it uses code that is described as stable.mw.hook.add('foo',function(fn,message){fn(message);});
ProvidersSHOULD document all stable methods ondoc.wikimedia.org and follow currentcoding conventions.
Providers looking to avoid adding code on the publicmw objectSHOULD instead share code between modules usingResourceLoader/Package files (usingmodule.exports andrequire( '<filename>' )). SeeOptionalParamWidget.js as an example of a class that is not defined on the mw object and can only be used bymediawiki.special.apisandbox.
Providers usingResourceLoader/Package filesSHOULD limit what functions are exported in themain module file to those that need to be shared between multiple ResourceLoader modules.
Therequire() function is only accessible to ResourceLoader modules and currentlySHOULD NOT be considered a stable interface outside ResourceLoader modules where it is undefined.
HTML markup and CSS cannot be considered stable (unless explicitly stated).All frontend code (including wiki-hosted code, extensions and skins) relying on HTML structure does so at its own risk.However, consumers often do rely on the DOM structure and unstable identifiers for historic reasons due to missing frontend APIs.For example:
$('<div>Hello world</div>').prependTo(mw.util.$content);
$('<div>Hello world</div>').prependTo('#content');
MediaWiki developers are not required, but have a responsibility to respect gadget developers' existing work byproactively communicating any changes to HTML markup where alternative APIs are not currently available, particularly in projects which have high visibility or operate in the article namespace.This requirement will be dropped 2 years after the roll out of the frontend stable policy (September 2025).
In cases where there might be mutually beneficial for wiki-hosted code developers and MediaWiki developers to share stylesheets, for example for performance reasons, while not advised, the relationshipMUST be documented in the source-controlled code using the@public and@since tags and linking to the on-wiki discussion.Classes defined in HTML class attributes that do wish to be considered stableMUST add an inline comment indicating in which MediaWiki version they were introduced using the@since annotation and must follow the deprecation process in the relevant section below.For example:
/** * When changing this file or associated markup, please take care to note it is stable and in use on various wikis! *//* BEGIN *//** * @public for use by templates * @stable this class is used by 10,000+ templates on page load and should not be removed from the page without following the deprecation process. See discussion on [[mw:Can we share the banana styles?]] for more context. * @since August 2023 (MediaWiki 1.41) */.mw-banana{color:yellow;padding:10px;}
.mw-banana{color:yellow;padding:10px;}
Wiki-hosted codeSHOULD NOT make use of stylesheets defined by MediaWiki core for styling custom HTML markup, as doing so can lead to misuse, misunderstandings and breakage (T213239,T287997) unless the consuming code makes this relationship clear via@public and@since tags (please refer toadvice for providers).Instead Wiki-hosted codeSHOULD define its own class and styling rules.
mw.util.addPortletLink function to add additional menu items, because as part of the mw object it should be considered stable, and if imitating the HTML markup they should also imitate the CSS that goes with it, so it can rely on the styles not changing.MediaWiki developersMUST understand and consider caching implications, namely that HTML from a previous deploy may be served to users alongside newer CSS. For pages subject to cache, MediaWiki developersMUST consider how HTML that is greater than a week old (such as HTML generated during the last train cycle) will be styled.
MediaWiki developersSHOULD first assess the impact of their change to HTML markup on wiki-hosted code, basedon the communication guidelines and whether communication is advised.
Particular careMUST be taken when:
mw- as traditionally the prefix has been associated by some as a stable interface..wikitable and.external).mw- prefix, or an ID that hasn't changed in over 5 years), developersSHOULD consider a longer grace period since there is no way to do backwards compatibility.MediaWiki developersMUST follow the conventions inManual:Coding_conventions/CSS#Naming. The benefits of using naming conventions are twofold:
mw- prefixed selectors, and assume they are stable and not prone to change.For adding items to menus, themw.util.addPortletLink method is encouraged rather than relying on jQuery.For adding subtitles, usemw.util.addSubtitle rather than appending to#contentSub or#mw-content-subtitle elements.
If you find yourself relying on CSS in core youSHOULD request a function for generating markup that is compatible for that CSS.Where APIs do not exist, consumersSHOULD request APIs to access elements or extend existing elements viaPhabricator.
MediaWiki developersMAY change default CSS for content generated by wikitext (such as changing the default link colors or changing typography).While rare, developersSHOULD consult Global Search to inform themselves about potential local overrides made by editors in MediaWiki:Common.css andSHOULD follow the guidelines forcommunicating changes to gadget developers when the change may be controversial or potentially cause visual changes.
For frontend code we do not make a distinction between soft and hard deprecation since we do not log deprecation warnings and their primary purpose is for communicating to developers.When deprecating it is important to reference the MediaWiki version as many gadget developers rely on this to get a sense of how recently the deprecation happened.
Code that was never part of a public MediaWiki release, and never consumed according toCodesearch andGlobal SearchMAY be changed (including marked explicitly as@private) or removed without deprecation, since the code has never become part of the stable interface or used.
When deprecating JavaScript code:
@deprecatedMUST be added to the JavaScript documentation andSHOULD note the MediaWiki release number.mw.log.deprecate ormw.log.makeDeprecatedMUST be used to signal the deprecation of the API. The deprecation messageSHOULD state the release in which the deprecation happened.For example:
mw.util.bar=function(a,b){// ...};// Define mw.util.foo as deprecated alias for mw.util.bar,// and accepts the same arguments./** * @deprecated since 1.40 Use mw.util.bar instead. */mw.log.deprecate(mw.util,'foo',mw.util.bar,'[1.40] Use mw.util.bar instead.');// Define mw.util.quux(a) as deprecated wrapper for mw.util.bar(a, b)/** * @deprecated since 1.40 Use mw.util.bar instead. */mw.log.deprecate(mw.util,'quux',(a)=>mw.util.bar(a,42),'[1.40] Use mw.util.bar instead.');
Or usemw.log.makeDeprecated instead:
/** * @deprecated since 1.40 Use mw.util.bar instead. */mw.util.foo=function(){mw.log.makeDeprecated(null,'[1.40] mw.util.foo is deprecated. Use mw.util.bar instead.')();mw.util.bar();};
Deprecated methodsMUST NOT be removed until they have been logging deprecation warnings in at least one stable release and for at least one month in the Wikimedia production environment.MediaWiki developersMUST follow guidelines forcommunicating changes to gadget developers.
When deprecating a hook, producersMUST call thedeprecate() method on the Hook object before firing.For example:
/** * Fired when indicators are being added to the DOM * * @event foo * @deprecated since 1.40 Use X instead. * @member mw.hook * @param {jQuery} $content jQuery object with the elements of the indicators */mw.hook('foo').deprecate('[1.40] Use X instead').fire(param1);
Code that was never part of a public MediaWiki release, and never consumed according toCodesearch andGlobal SearchMAY be changed or removed without deprecation, since the code has never become part of the stable interface or used.
Before removing a module, the moduleMUST be deprecated so that using the module logs hard-deprecation warnings for at least one MediaWiki release prior to removal using the deprecated key in its ResourceLoader definition.This is to support third party developers who need to be notified and respond to any upstream changes.
When deprecating a ResourceLoader module, set the deprecated key on the associated ResourceLoader.The developerMUST document the deprecation inRELEASE_NOTES and mention the release number in which the deprecation occurred.For example:
['wvui'=>['deprecated'=>'[1.40] Use @wikimedia/codex instead.','packageFiles'=>['resources/src/wvui/wvui.js','resources/lib/wvui/wvui.commonjs2.js',],],]
DevelopersMAY fix consumers of a module prior to deprecation, but doing so is not required as a precursor to deprecation.
When completing a deprecation, the removalMUST be documented inRELEASE_NOTES.Communicate the change to gadget developers percommunication guidelines.
When making breaking changes, despite good intentions it is inevitable even with good communication that some on-wiki scripts will not be updated by their maintainers and the change will lead to production errors and/or disruption to editor workflows.
Client side errors occurring in wiki-hosted code are tracked alongside errors in MediaWiki code onGrafana and can be explored further inside our logstash instance.
When making breaking changes, MediaWiki developers have a responsibility to fix or disable certain gadgets in the following scenarios:
If any gadgets/scripts are impacted, then MediaWiki developersSHOULD notifyTech News. For changes that impactpopular gadgets in such a way that they break functionality or where stable interfaces have changed (regardless of whether they are used), MediaWiki developersMUST do so. If MediaWiki developers are confident that gadgets will not be severely impacted (for example if the gadget is still functional after the change but stylistically different) communication can be skipped.
When communication is required:
For all communications:
When learning about the breakage of gadgets on Wikimedia wikis that are not covered by the wiki-hosted code policy, e.g. using unstable interfaces due to unavailability, MediaWiki developersMUST assess the inclusion of a new stable interface to reduce future breakage.
If code running on Wikimedia projects is impacted by breaking changes, developersMUST open Phabricator ticket(s) tracking the issue for impacted skins and/or extensions. The Phabricator ticket(s)SHOULD tag the impacted project and detail the timeline for the removal and provide details on the required change.DevelopersMAY provide patches, and are encouraged to do so especially in the case where the fix is simple.
This policy is designed to make consumers more robust against changes in MediaWiki core, and provide more freedom for MediaWiki core code to evolve.
The motivation for the frontend stable interface policy is twofold:
Gadgets and user scripts (which will be referred to as wiki-hosted code) are key components of MediaWiki projects.
Before the introduction of this policy, there was no clearly defined API that such code could rely upon.This has caused misunderstandings and unexpected problems particularly for wiki-hosted code.
This situation has also made it difficult to improve MediaWiki code, since it was unclear how changes would impact wiki-hosted code and developers often did not feel empowered to make changes in an acceptable fashion.
In addition, it has not been clear who is responsible for fixing issues in wiki-hosted code.
This document aims to build agreements between Wikimedia staff, third party extension developers, and developers of wiki-hosted code developers to create a better experience for all groups and to build trust between them.