Talk:Recommendations for gadget developers on Wikimedia wikis

From mediawiki.org
Latest comment: 8 months ago by The wub in topic Wiki-hosted vs Wiki-based

Cater for the situation where these elements do not exist[edit]

I actually consider the good.js more of an antipattern than bad.js. I encountered multiple times that someone reports that a gadget doesn’t do anything, and when I asked them for the stack trace, it turned out that there wasn’t any. These are often caused by such structures:

var cactions = document.getElementById( 'p-cactions' );
if ( cactions ) {
	cactions.insertBefore( node, cactions.firstChild );
} else {
	// do nothing
}

// or

$( '#p-cactions' ).prepend( node );

(jQuery is especially prone to such issues, as its signature doesn’t make it obvious that there’s a no-op when the selector doesn’t match).

There are three acceptable solutions IMO:

  • Provide an actual fallback if possible. For example, if there’s no #p-cactions, insert the node to the beginning of the content, or wherever it makes sense.
  • Replace the // do nothing with a console.warn() call if no actual fallback can be provided but the gadget is still useful without this part. The gadget functionality will be partial if #p-cactions goes away, but the cause will appear in the console, and other parts of the gadget will continue to work.
  • Don’t care, i.e. do what you put in bad.js. If the gadget cannot do anything useful without #p-cactions, fail fast and loud so that someone quickly notices it, and the gadget can be fixed or disabled.

Tacsipacsi (talk) 02:12, 11 January 2023 (UTC)Reply

@Jdlrobson: Thanks for adding the note about logging and the fallback call. However, I still think in cases when no fallback is possible and the gadget cannot provide any – not even degraded – functionality without a given element (e.g. MediaWiki:Gadget-purgetab.js can do nothing without #p-cactions), it is appropriate and desirable to error out – if not many users use the given gadget, the “log spam” (which is not really spam, since it’s about a real issue) won’t be that big; if many users use it, developers have just broken the wiki for many users. It may not be their task to fix it, but gadget maintainers have no way to notice the issue other than getting feedback either from people watching the logs, or from upset users. —Tacsipacsi (talk) 00:06, 13 January 2023 (UTC)Reply
Throwing an error adds it production logs. If those happen current practice is to follow this guideline. If the goal is to log an error to the JavaScript console you can use mw.log.warn or mw.log.error. would suggesting use of those be be better?
If gadget developers are not looking at those logs wouldn't it be better to find a way to make those more visible so they are handled by the gadgets themselves? For example perhaps there should be a reportGadgetError function local to the wiki that reports in a non spammy way that there's a gadget error so users can report these to the gadget developer? Jdlrobson (talk) 00:36, 13 January 2023 (UTC)Reply
The exact goal is to get these errors logged in some server-side logs gadget maintainers can routinely query (or someone else can routinely query and tell gadget maintainers if there’s some issue), so mw.log.warn or mw.log.error are of no use. A separate function that logs in server-side logs would suffice (although it still makes the code longer, which means more maintenance and more bandwidth need, but I suppose we can’t really do anything about it), but I’m not sure if it can be created locally without compromising user privacy, and I also think that functionality that’s used everywhere should be developed centrally (i.e. in MediaWiki core or an extension), otherwise smaller wikis miss out or keep running outdated code. So if a function that logs in server-side logs in a way respecting user privacy is introduced in MediaWiki or an extension, I’m happy to support its usage instead of leaving errors unhandled. —Tacsipacsi (talk) 20:31, 14 January 2023 (UTC)Reply
Would be nice to have an ear in error reporting (some pings maybe), but this would be a very bad recommendation:
Don’t care, i.e. do what you put in bad.js. If the gadget cannot do anything useful without #p-cactions, fail fast and loud so that someone quickly notices it, and the gadget can be fixed or disabled.
The scripts do not work alone. They can break other scripts with either NPE or (worse) syntax errors. Scripts should only break themselves and if you really want to be "loud" about it do an `alert`. On pl.wiki we actually have a recommendation back from 2007 for that [1]. The page is in Polish, but examples are rather universal.
You might also want to read why scripts don't work alone (my article). Which can partially be handled by doing try-catch over each script. But only partially. Nux (talk) 16:14, 21 January 2023 (UTC)Reply

What is the recommended way to load user CSS?[edit]

Seems like there is no recommendation to load CSS. For gadgets this is simple, but what about user scripts (from user namespace)?

I assume you don't want to support `importStylesheet` anymore (same as you don't want to support shorthand syntax for loading JS via `importScript`). Not a fun of that (short is good), but I understand that you want to move forward to RL.

So we are left with:

  • Loading from JS: mw.loader.load( '/w/index.php?&action=raw&ctype=text/css&title=User:Msz2001/sourcecode-links.css', 'text/css' );
  • Loading from CSS: @import url("/w/index.php?action=raw&ctype=text/css&title=User:Msz2001/sourcecode-links.css");

Which of these methods is considered better? Will any of these methods be somehow optimized (e.g. covered by CSS merging)? Are there any plans to simplify this syntax (e.g. make url parameters for ctype optional)? Maybe some mw.util for local wiki stuff? Nux (talk) 15:58, 21 January 2023 (UTC)Reply

The text is wrong and I've now fixed it. Thanks for pointing it out.
For context, there was some confusion around these methods. In 2015, they were un-deprecated but retained inside a deprecated file https://gerrit.wikimedia.org/r/c/mediawiki/core/+/206078
Last August (after this document was created) they got moved out to a more appropriate place:
https://gerrit.wikimedia.org/r/c/mediawiki/core/+/820828
I've updated the guidelines. I think which is better depends on the use case. Jdlrobson (talk) 16:10, 21 January 2023 (UTC)Reply
Good to know, thanks! 🙂 I was just re-writing our Polish recommendations. It's great that you are keeping the shorthand syntax and just make it work with mw.loader 🙂. Nux (talk) 16:26, 21 January 2023 (UTC)Reply

Blanking CSS[edit]

We currently propose unmaintained scripts are blanked. I'd like to expand this to recommend leaving an inline comment that points to alternative options.

I'd also like to expand this to explain the rationale - minimizing the possibility of users running unmaintained code.

Any objections? Jdlrobson (talk) 04:19, 20 May 2023 (UTC)Reply

Exceptions[edit]

Not sure if this is still the case but in the past jQuery had terrible exception handling - certain constructs that were supposed to decouple code (like $.Callbacks) didn't really do that and throwing an exception could prevent callback / event handler code in an unrelated component from running. I wonder if using mw.errorLogger.logError() would be the better advice. That would also let the gadget specify itself as a component, which is useful for filtering. Tgr (WMF) (talk) 23:00, 2 August 2023 (UTC)Reply

Named functions[edit]

Maybe worth mentioning named function expressions? Not sure how well-known they are , and they result in more concise code. (Technically they are an ES6 feature but I think everything has supported them for a long time.)

Also maybe worth mentioning that an anonymous function expression that is used in an assignment or as a field value de facto becomes named, so no need to explicitly name it if the variable name or field name is expressive.

(Although once we have source maps, maybe this whole section becomes obsolete anyway?) Tgr (WMF) (talk) 23:03, 2 August 2023 (UTC)Reply

Opting out of error tracking[edit]

The guide links to wikitech:Client errors#Opting out of errors as a way for a gadget to opt out of error tracking. That works per user (so it would prevent error logging in any other feature when user by that user), right? I don't think that should be encouraged. The opt-out is useful for privacy-conscious users who worry about inadvertent tracking; gadgets shouldn't make that decisions in the user's stead. Adding try-catch blocks is a better way of silencing errors. Tgr (WMF) (talk) 00:43, 3 August 2023 (UTC)Reply

Code on Cloud VPS[edit]

Wiki based code SHOULD be loaded from a Wikimedia owned domain e.g. hosted on a project OR a cloud VPS instance.

Code SHOULD NOT be loaded from Cloud VPS instances which have much more lax security and access control, and because there isn't any compelling use case to do so (you can always just host the code locally and load data instead). I hope this will get hard-banned via technical means eventually, but until then we should at least heavily discourage it Tgr (WMF) (talk) 01:05, 3 August 2023 (UTC)Reply

I think this is also contradictory to the proposed Third-party resources policy, where it was stated on the talk page that Cloud Services hosted content is considered "third-party". the wub "?!" 16:04, 12 August 2023 (UTC)Reply

CSS[edit]

Wiki-based code SHOULD provide their own CSS for styling their features and SHOULD NOT rely on MediaWiki HTML classes provided by the software to style their features, even if this results in duplicated CSS. In certain cases it might make sense for wiki-based code and MediaWiki developers to share code, but this MUST be documented in the source-controlled code using a @public keyword per the Stable interface policy. If the code is not documented wiki-based code developers MUST file a Phabricator ticket to make sure this is documented.

vs

MediaWiki developers and wiki-based code MUST NOT share CSS classes. Wiki-based code should therefore never create HTML which prefixes classes or IDs with "mw-".

These seem somewhat contradictory. The first is what I'd expect here: on-wiki code should not use MediaWiki classes unless those classes are specifically meant to be reused. The second seems unnecessary. Tgr (WMF) (talk) 01:13, 3 August 2023 (UTC)Reply

Wiki-hosted vs Wiki-based[edit]

User:Jdlrobson/Stable interface policy/frontend uses "Wiki-hosted code" while this document uses "Wiki-based code", both with the same definition. It would make sense to pick one term for both documents. the wub "?!" 13:46, 16 August 2023 (UTC)Reply