ResourceLoader/Foreign resources
ResourceLoader |
---|
Reference |
Tutorials |
MediaWiki version: | ≥ 1.41 Gerrit change 911307 |
Foreign resources are upstream frontend libraries registered in MediaWiki as ResourceLoader modules. They are defined in a file called foreign-resources.yaml
. This file declares the version and source of upstream projects currently installed.
In MediaWiki core, foreign resources are stored in the resources/lib/
directory. Extensions and skins can use the ForeignResourcesDir
attribute in their extension.json
/skin.json
file to manage a similar directory.[1] That directory needs to contain a foreign-resources.yaml
file. The manageForeignResources.php maintenance script can be used to install, update, or verify these resources.
The metadata about foreign resources is also integrated with Special:Version, where it powers the "Installed client-side libraries" section.
How to install a foreign resource
[edit]- Add or update the url(s) for the upstream module in
foreign-resources.yaml
. Look at other modules for examples. To install a module from npm, we use the tarball distribution from npmjs.org. This is the same as what the npm CLI uses. For example, to installjquery-client@9.2.0
, usehttps://registry.npmjs.org/jquery-client/-/jquery-client-9.2.0.tgz
. - If the upstream maintainers publish an integrity hash, set that as well. Otherwise, use
manageForeignResources.php
to compute the integrity hash. Runphp manageForeignResources.php --extension <my extension name> make-sri <my module name>
- this will download the specified file(s) and print their integrity hashes, already formatted in YAML, ready for copying to this file. - Last but not least, decide where files go. If you specified a direct url to JavaScript or CSS file, this step is optional. See the corresponding documentation section below for more information and examples for
dest
keys. Once you've set anydest
keys, runphp manageForeignResources.php --extension <my extension name> update <my module name>
.
foreign-resources.yaml format
[edit]- See resources/lib/foreign-resources.yaml for up-to-date documentation
Each top-level key must use one of these types:
file
: For a plain file.multi-file
: For multiple plain files.tar
: For a tarball archive (file may be compressed).doc-only
: For documenting that a package is used, without managing it
Shared fields
[edit]The following fields are shared by all package types:
license
: SPDX license identifierhomepage
: [optional] Homepage URL of library shown on Special:Versionversion
: [optional] Version string of library shown on Special:Version
The "file" type
[edit]Besides the shared ones, the following fields are used:
src
: Full URL to the remote resource.integrity
: SRI cryptographic hash.dest
: [optional] The file name to use in the module directory. Default: Basename of URL.
For example, the following would produce resources/lib/mymodule/x.js
:
mymodule:
type: file
src: https://mymodule.example/1.2.3/x.js
integrity: sha384-Je+NE+saisQuoi
The "multi-file" type
[edit]Besides the shared ones, the following fields are used:
files
: An object mapping destination paths tosrc
andintegrity
keys.
For example:
mymodule:
type: multi-file
files:
x.js:
src: https://mymodule.example/1.2.3/x.js
integrity: sha384-Je+NE+saisQuoi
x.css:
src: https://mymodule.example/1.2.3/x.css
integrity: sha384-Je+NE+saisQuoi
The "tar" type
[edit]Besides the shared ones, the following fields are used:
src
: Full URL to the remote resource.integrity
: SRI cryptographic hash.dest
: [optional] The default is to extract all files from the package. To only extract some of the files or directories, usedest
to specify files, directories, and/or glob patterns. You can use a site like https://unpkg.com/ to easily inspect an npm package, likehttps://unpkg.com/jquery-client@2.0.2/
. This field can also be used to extract files to a subdirectory (by default the files and directories listed indest
are extracted to the module directory root).
For example:
mymodule:
type: tar
src: https://registry.npmjs.org/jquery-client/-/jquery-client-9.2.0.tgz
integrity: sha384-Je+NE+saisQuoi
dest:
package/dist/x.js:
package/dist/i18n:
package/dist/style/*.css: themes
The above would extract the x.js
file, the i18n
directory (recursive), and any *.css
files from the style
directory. They will end up in mymodule/x.js, mymodule/i18n and mymodule/themes, respectively.
The "doc-only" type
[edit]This type can be used for packages which are managed in some custom way (e.g. they require a manual build step). manageForeignResources.php will ignore these records, but they will still be shown on Special:Version. Only the shared fields are used.
Minified files
[edit]It is generally not recommended to commit minified code to a Git repository. Minified code hinders security audits, code reviews, and debugging; and removes ability for us to directly address security vulnerabilities in production (i.e. where untrusted third-party development packages may not be installed or executed). ResourceLoader automatically takes care of bundling, minification, and compression for you (ResourceLoader/Architecture).
If an upstream library distributes both a readable version and strongly minified/optimised version as part of its official releases, it could be worthwhile for performance to make use of that in production. In that case, you can install the minified distribution files provided by the upstream library, and define your module to use those instead.
If you bundle a pre-minified file, you must also install and commit the corresponding non-minified files, and they should be used when ResourceLoader debug mode is active. This ensures that we can fallback to the source files if needing to patch the module for security reasons, and improves the developer experience to ease auditing and debugging (given that ResourceLoader's source map would map to the already-minified version). Committing readable unminified source code is also required in order for MediaWiki to comply with Debian packages license requirements. (Related tasks: T217351, T257878. Example: T346075.)
Notes
[edit]- ↑ Note that
ForeignResourcesDir
is not a configuration variable but an extension attribute; setting$wgForeignResourcesDir
has no effect.