Jump to content

Talk:ResourceLoader/Package files

About this board

Cavila (talkcontribs)

Sometimes an external js library used in an extension can be extended with many optional plugins, which may or may not use require() functions. I would imagine that (a) the library can be added to the "packageFiles" of the main module (so it can be imported/required in the main entry file) and that (b) a list of plugins would be added, under "scripts", to a separate 'plugin module'. If you then want to add the plugin module to packageFiles, which approach would be best/recommended if at all possible?

  • the config option, pointing to the module within extension.json (if self-referentiality is at all possible), or
  • the PHP callback option, pointing to a function that somehow returns the RL module.

Or is there a better and more straightforward approach I'm overlooking?

Tacsipacsi (talkcontribs)
Cavila (talkcontribs)

Thanks, it works. The idea is, theoretically at first, to concatenate multiple plugins in a single module and then to require that module within the main file of the base module - rather than list and require each plugin file separately. The second option you've given there is interesting, but it looks like I can import the plugins module directly in the main file (of the base module) as long as (a) the plugins module has a dependency on the library module, which is declared in skin/extension.json, and (b) the mw.loader.using pattern illustrated here is used to require the module.

There are other conditions to be satisified but they are more specific to library/plugin conventions I guess - for instance, plugins may expect the library module to be named a particular way (so no custom naming for libraries in skin/extension.json), but that's just noise for now.

Jeroen De Dauw (talkcontribs)

Which version of MediaWiki introduced packageFiles? In particular, is it available in 1.31?

Krinkle (talkcontribs)

Package files was introduced in MediaWiki 1.33. I've added this to the documentation page now!


I've also patched the API docs to mention this on doc.wikimedia.org.

Reply to "MediaWiki support"

What about debugging?

4
Vedmaka (talkcontribs)

Before we could use `?debug=true` to disable files concatenation and thus be able to debug JS code, now with packages there seems to be no way of doing this since all the packages are being jammed into single piece. Do we have a workaround (sourcemaps?) ?

Roan Kattouw (WMF) (talkcontribs)

?debug=true still disables minification, and disables concatenation of different modules (every module is a separate request), but it doesn't load individual files separately. Unfortunately I don't believe there's a way to do that without breaking require(). Debugging has worked pretty well for me despite that though.

cc @Krinkle for the source maps question, I don't know what the status of that is (if anything).

Vedmaka (talkcontribs)

It looks like concatenation is still there, modules being loaded in a bulk as a single item, either way - that's true that in that form it's possible to debug it using browser tools, but make it impossible to attach any external debuggers like PHPStorm since there is no file mappings and no sourcemaps.


added: actually debugging in browse is quite buggy too - it can't retain link to a script in most cases

Roan Kattouw (WMF) (talkcontribs)

For in-browser debugging, I've mostly used debugger; statements in the code, or used the console to access functions/methods by name and navigate to them. There's also a debugging trick specific to package modules that I'll add to this page. You're right that source maps would be a good thing to add though.

Reply to "What about debugging?"

Can I use files AND packageFiles

3
Summary by Roan Kattouw (WMF)

It's now explicitly documented that you can't do this.

Jdlrobson (talkcontribs)

Is it possible to have a RL module that defines both files and packageFiles. e.g. are they additive ?

Roan Kattouw (WMF) (talkcontribs)

No. I should document this more clearly: if you use packageFiles, you cannot use scripts, languageScripts, or any of the other *scripts properties. You can define CSS files of course (in the *styles properties).

Roan Kattouw (WMF) (talkcontribs)

...I should also add that if you do try to do this, you will get an exception at definition time, telling you that the two properties are mutually exclusive

What happens with conflicting definitions?

2
Jdlrobson (talkcontribs)

[ 'foo/bar.js', 'blah.js' => 'foo/bar.js' ]

Is this supported? Does code get loaded twice? I'm curious as I'm not 100% sure why aliasing is needed (some more context on that would be useful).

Roan Kattouw (WMF) (talkcontribs)

Technically this is not a conflicting definition :P . Yes, the code would get loaded twice under two different names, and it's not recommended that you use aliasing this way.

The main reasons aliasing exists is because it's sort of already there for dynamic files, and because it lets you simplify file paths (this ended up being done with localBasePath instead, but an alternative that I was using previously was writing definitions like [ 'foo.js' => 'resources/src/blah/foo.js', 'bar.js' => 'resources/src/blah/bar.js', ... ]

In practice, I don't expect aliasing of real files to be used much, but I'd like it to be possible.

I should also point out that I wrote this documentation (at least initially) as a complete list of everything you can do, without necessarily indicating what's meant to be commonly used and what's meant to be exceptional.

Reply to "What happens with conflicting definitions?"
Jdlrobson (talkcontribs)

What is the advantage of using main=>true rather than just making it the first file. What sort of problems does that solve?

I'm curious as this complicates the rules/definitions and I'm not sure why it's necessary.

Similarly, I've not worked out why callback is useful, so would be useful to have some illustrative examples showing use cases I haven't thought of yet.

Roan Kattouw (WMF) (talkcontribs)

I'll add some more real-life examples to the list Kosta started. I do have a real-life example or two where the callback feature came in handy, for exporting things that are known server-side. For example, the list of all language names in the current language is a config-like thing that's not technically a config, but is instead the return value of Language::fetchLanguageNames().

Roan Kattouw (WMF) (talkcontribs)

As for main=>true, yeah it's redundant, and it might be clearer to either force the main file to always be first, or force the main file to be explicitly flagged with main=>true even if it is the first file.

Reply to "Real Examples"
Jdlrobson (talkcontribs)

If I define config inside a ResourceLoader module, e.g. 'config.json' => [ 'callback' => 'method' ]

but need to access this inside another RL module, what is the proposed way of doing that? Should I not use it at all or should I call mw.config.set inside my JS ?

Roan Kattouw (WMF) (talkcontribs)

I suppose this documentation neglects to mention that module.exports and require() also work at the module level. So ideally, module A would include the config blob (or a relevant subset thereof) in its module.exports, and then module B would call require('A').

As for mw.config, I think we should start slowly weaning ourselves off of that, or at least resist adding new things to it. So for backwards compatibility you would probably end up doing mw.config.set() sometimes, but I don't think it should be the preferred way of doing things.

Reply to "Sharing config"
There are no older topics