HowItWorks:MediaWiki: Difference between revisions
mNo edit summary |
|||
| Line 3: | Line 3: | ||
'''MediaWiki''' is the free, open-source wiki engine behind Wikipedia, Wikidata — and this very site. | '''MediaWiki''' is the free, open-source wiki engine behind Wikipedia, Wikidata — and this very site. | ||
== | == Components and interactions == | ||
{ | <uml> | ||
@startuml | |||
!theme bluegray | |||
title MediaWiki Core Code Modules & Infrastructure Interactions | |||
' ============= INFRASTRUCTURE NODES ============= | |||
node "Infrastructure" { | |||
database "MySQL / MariaDB\n(Revision, Page, User,\nCategory, etc.)" as DB | |||
database "Redis / Memcached\n(Object Cache, Sessions,\nParser Cache)" as CACHE | |||
node "Swift / Local FS\n(Images, Thumbnails, CSS/JS)" as FS | |||
} | |||
' ============= STORAGE SERVICES (Abstracted Layers) ============= | |||
package "Storage Services" { | |||
component "LoadBalancer\n(DB connection manager)" as LB | |||
component "RevisionStore\n(includes/RevisionStore.php)" as RS | |||
component "PageStore\n(includes/Storage/PageStore.php)" as PS | |||
component "BagOStuff\n(Object cache interface)" as BO | |||
component "FileRepo\n(File repository abstraction)" as FR | |||
} | |||
' ============= CORE DISPATCH & HANDLING ============= | |||
package "Entry Points & Dispatchers" { | |||
component "index.php" as INDEX | |||
component "api.php" as API | |||
component "load.php" as LOAD | |||
component "MediaWiki\n(includes/MediaWiki.php)" as MW | |||
component "ApiMain\n(includes/api/ApiMain.php)" as APIM | |||
component "ResourceLoader\n(includes/ResourceLoader.php)" as RL | |||
} | |||
' ============= PAGE, CONTENT & PARSING ============= | |||
package "Page & Content" { | |||
component "Title\n(includes/Title.php)" as TITLE | |||
component "WikiPage / Article\n(includes/page/WikiPage.php)" as WP | |||
component "ContentHandler\n(includes/content/ContentHandler.php)" as CH | |||
component "Parser\n(includes/parser/Parser.php)" as PARSER | |||
component "OutputPage\n(includes/OutputPage.php)" as OUT | |||
component "HookContainer\n(includes/HookContainer.php)" as HOOK | |||
} | |||
' ============= CLIENT ============= | |||
node "Client" { | |||
[Browser / HTTP Client] as CLIENT | |||
} | |||
' ============= FLOWS ============= | |||
' Client to Entry Points | |||
CLIENT --> INDEX : GET /wiki/Title | |||
CLIENT --> API : GET /api.php?action=query | |||
CLIENT --> LOAD : GET /load.php?modules=skins | |||
' Entry Points to Dispatchers | |||
INDEX --> MW : require + MediaWiki::main() | |||
API --> APIM : ApiMain::execute() | |||
LOAD --> RL : ResourceLoader::respond() | |||
' Dispatcher to Page/Title resolution | |||
MW --> TITLE : Title::newFromRequest() | |||
MW --> WP : WikiPage::factory( Title ) | |||
APIM --> TITLE : Title::newFromText() | |||
APIM --> WP : WikiPage::factory() | |||
' Page retrieval from storage | |||
WP --> PS : getPage() / loadPageData() | |||
PS --> LB : getConnection( DB_REPLICA ) | |||
LB --> DB : SQL SELECT | |||
WP --> RS : getRevisionById() | |||
RS --> LB : getConnection( DB_REPLICA ) | |||
LB --> DB : SQL SELECT | |||
' Content parsing (view action) | |||
WP --> CH : getContentHandler() | |||
CH --> PARSER : parse( Content ) | |||
PARSER --> LB : getConnection( DB_REPLICA )\n(for template transclusion) | |||
PARSER --> BO : get() / set()\n(parser cache) | |||
PARSER --> HOOK : run( 'ParserBeforeStrip' ) etc. | |||
' Output assembly | |||
MW --> WP : view() / action=view | |||
WP --> OUT : addHTML( parsed content ) | |||
OUT --> BO : get() / set()\n(output cache / HTML cache) | |||
MW --> OUT : output() (send to client) | |||
' API-specific storage | |||
APIM --> RS : getRevisionInfo() | |||
APIM --> LB : getConnection( DB_REPLICA ) | |||
' ResourceLoader storage | |||
RL --> FR : getFileContents( style, script ) | |||
FR --> FS : read from filesystem / Swift | |||
RL --> BO : get() / set()\n(module cache) | |||
' Infrastructure connections | |||
LB --> DB : (read/write) queries | |||
BO --> CACHE : set/get/delete | |||
FR --> FS : read/write images & assets | |||
' Extension hooks (optional cross-cut) | |||
HOOK --> LB : (extensions may query) | |||
HOOK --> BO : (extensions may cache) | |||
HOOK --> FR : (extensions may serve files) | |||
' Notes with actual file paths | |||
note right of INDEX | |||
Actual entry point | |||
Handles all web requests | |||
end note | |||
note right of MW | |||
Core dispatcher; handles | |||
actions, permissions, and | |||
main request lifecycle | |||
end note | |||
note right of RS | |||
Manages Revision metadata | |||
and blobs (text storage) | |||
end note | |||
note right of PARSER | |||
Transforms wikitext to HTML; | |||
uses cache and DB for templates | |||
end note | |||
note right of BO | |||
Interface to object cache; | |||
used by ParserCache, MessageCache, | |||
SessionManager, etc. | |||
end note | |||
@enduml | |||
</uml> | |||
== How it works == | == How it works == | ||
Revision as of 17:58, 27 August 2026
Explains how things actually work — part of our technology dissections collection.
MediaWiki is the free, open-source wiki engine behind Wikipedia, Wikidata — and this very site.
Components and interactions
How it works
A page view passes through these stages:
- The request arrives. The browser asks for
/wiki/Main_Page. The web server hands it to PHP-FPM, which boots MediaWiki throughindex.php: security checks, default settings, then the site's ownLocalSettings.php. - The title is resolved. MediaWiki works out which page is meant (namespace, redirects, aliases) and checks the reader's permissions.
- The wikitext is loaded from the database — always the stored source, never a pre-rendered copy.
- The preprocessor expands. Template calls (
{{...}}), parser functions and magic words are resolved into expanded wikitext. This stage walks a tree and can skip dead branches, such as the unused cases of a{{#switch:…}}. - The parser converts to HTML. Wikitext syntax becomes HTML elements; the Sanitizer class scrubs any raw HTML for unsafe content.
- The skin frames the page. The content HTML is wrapped in the skin's chrome (sidebar, header, footer) together with CSS and JavaScript delivered by ResourceLoader.
- The page is served. A repeat view can skip stages 4–6 entirely if the rendered output is still in a cache.
Editing runs the pipeline the other way: the editor posts wikitext → MediaWiki stores a new revision (old ones stay, giving every page a full history) → the page is re-parsed → link tables, recent changes and the search index are updated. Heavy follow-up work (search indexing, notification e-mails) is queued into the job queue so the save itself stays fast.
Why it works that way
- Content stays in wikitext, not HTML. Diffs, history and collaborative editing fall out naturally — and when the software changes its HTML output, no content has to be rewritten.
- The parser is a stability contract. Hundreds of millions of pages depend on its output, so it changes slowly and conservatively. The price: wikitext grew organically, is complex, and cannot be described by a formal grammar.
- Templates are DRY for wikis. One source of truth for repeated boilerplate (navigation boxes, banners, infoboxes), expanded at read time. The preprocessor rewrite (MediaWiki 1.12, 2009) exists precisely because template-heavy pages had become a parsing bottleneck.
- Skins separate content from presentation. The same content HTML renders under any skin without re-parsing.
- Extensions plug in; the core stays stable. Hooks let third-party code run before, after or instead of core behaviour — the citation and embed systems on this very site are extensions, not forks.
- Caching is the price of PHP. Every request boots PHP, so MediaWiki layers caches: reverse proxies serve whole pages, an object cache avoids re-parsing, an opcode cache skips recompiling PHP. The tradeoff is cache invalidation (next section).
Diagram
| Stage | What happens |
|---|---|
| preprocessor | {{templates}}, {{#if:…}}, magic words → expanded wikitext
|
| parser | expanded wikitext → HTML (via Sanitizer) |
| skin | content HTML + chrome + ResourceLoader CSS/JS → complete page |
| cache | the complete page is stored; repeat views skip the stages above |
Gotchas & myths
"MediaWiki is a CMS like WordPress."
Myth Reality publication workflows, per-namespace access control, WYSIWYG-first editing a wiki engine: open editing, per-action permissions, a stable text markup. The visual editor is an extension, and access control beyond "everyone can edit" is not the default.
"Editing wikitext is editing HTML."
Myth Reality <script>alert(1)</script>would runraw HTML is only allowed in limited forms; the Sanitizer strips anything unsafe — a <script>tag never survives into the page.
"A template change instantly updates every page using it."
Myth Reality save the template → all pages render the new output immediately transclusion happens at parse time; already-cached pages keep the old rendering until their cache is invalidated. A widespread template change can need a purge or a cache clear.
"Every page view runs PHP and re-parses the page."
Myth Reality PHP boots and the full pipeline runs for every hit cached pages short-circuit before the application; only uncached requests run the full pipeline.
Try it yourself
All commands below were run live against this wiki (MediaWiki 1.46.0) while writing this page.
# Which version is this wiki running?
curl -s "https://wikibase.ronzz.org/api.php?action=query&meta=siteinfo&siprop=general&format=json" | grep -o '"generator":"[^"]*"'
Verified output:
"generator":"MediaWiki 1.46.0"
# See the parser's HTML output for a page (the raw pipeline result, before the skin)
curl -s "https://wikibase.ronzz.org/api.php?action=parse&page=Main_Page&format=json" | grep -o "<p><strong>[^<]*"
Verified output:
<p><strong>Hi, welcome to Ronzz.org's own wikibase.
# See the preprocessor stage directly: Special:ExpandTemplates
# https://wikibase.ronzz.org/wiki/Special:ExpandTemplates
# paste {{HowItWorks}} into the input box and click "Expand" —
# you see the expanded wikitext before the parser turns it into HTML.
# The database schema updater — any maintenance script runs the same way
php maintenance/update.php --help
Verified output:
MediaWiki database updater
And in the browser: edit any page on a wiki where you can edit, save it, then open View history — you will see every revision kept, one per save.
Further reading
- Manual:MediaWiki architecture — the canonical architecture deep-dive (also a chapter of the Architecture of Open Source Applications book)
- Manual:Contents — the technical manual of the software
- MediaWiki — the software project page
The reference layer for this site's own data lives in the SPARQL cheatsheet: the sheet is the syntax, this page is the machinery.