HowItWorks:MediaWiki: Difference between revisions

From Wikibase
Jump to navigation Jump to search
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.  


== The parts ==
== Components and interactions ==


{| class="wikitable"
<uml>
|-
@startuml
! Part !! Role
!theme bluegray
|-
title MediaWiki Core Code Modules & Infrastructure Interactions
| wikitext || the content format: plain text plus light markup — <syntaxhighlight lang="wikitext" inline>'''bold'''</syntaxhighlight>, <syntaxhighlight lang="wikitext" inline>[[links]]</syntaxhighlight>, <syntaxhighlight lang="wikitext" inline>{{templates}}</syntaxhighlight>
 
|-
' ============= INFRASTRUCTURE NODES =============
| database (MySQL / MariaDB) || the single source of truth: page wikitext, every revision, users, permissions, categories, queued jobs
node "Infrastructure" {
|-
  database "MySQL / MariaDB\n(Revision, Page, User,\nCategory, etc.)" as DB
| preprocessor || front stage of parsing: expands templates, parser functions and magic words into expanded wikitext
  database "Redis / Memcached\n(Object Cache, Sessions,\nParser Cache)" as CACHE
|-
  node "Swift / Local FS\n(Images, Thumbnails, CSS/JS)" as FS
| parser || converts wikitext into HTML; since MediaWiki 1.44 a second parser (Parsoid, bundled as a PHP library) handles visual editing and the REST API
}
|-
 
| Sanitizer || scrubs raw HTML for unsafe content before it reaches the page
' ============= STORAGE SERVICES (Abstracted Layers) =============
|-
package "Storage Services" {
| skins || wrap the content HTML in the site's chrome: sidebar, header, footer, personal tools
  component "LoadBalancer\n(DB connection manager)" as LB
|-
  component "RevisionStore\n(includes/RevisionStore.php)" as RS
| extensions || PHP plugins that hook into core events to add features without forking the core
  component "PageStore\n(includes/Storage/PageStore.php)" as PS
|-
  component "BagOStuff\n(Object cache interface)" as BO
| web server + PHP-FPM || receive HTTP requests and run the MediaWiki application
  component "FileRepo\n(File repository abstraction)" as FR
|-
}
| cache layers || skip re-parsing and re-rendering on repeat views
 
|}
' ============= 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

Languages: English · français · Esperanto

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:

  1. The request arrives. The browser asks for /wiki/Main_Page. The web server hands it to PHP-FPM, which boots MediaWiki through index.php: security checks, default settings, then the site's own LocalSettings.php.
  2. The title is resolved. MediaWiki works out which page is meant (namespace, redirects, aliases) and checks the reader's permissions.
  3. The wikitext is loaded from the database — always the stored source, never a pre-rendered copy.
  4. 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:…}}.
  5. The parser converts to HTML. Wikitext syntax becomes HTML elements; the Sanitizer class scrubs any raw HTML for unsafe content.
  6. 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.
  7. 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

The wikitext → HTML pipeline
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 run raw 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

The reference layer for this site's own data lives in the SPARQL cheatsheet: the sheet is the syntax, this page is the machinery.