JavaScript Packages and Interoperability in 5.0 and Beyond

WordPress 5.0 adds a number of new bundled script handles, including many specific to the new editor, as well as a few vendor dependencies. Given that a plugin or theme may already have registered their own copies of these same dependencies, this post is meant to serve as a reference for maximum interoperability. These are tips which could apply for any new dependency added by WordPress in any version, but are more likely than usual to be encountered given the amount of new JavaScript included starting in 5.0.

WordPress-Specific Scripts

All new WordPress-specific JavaScript code is registered using wp- as a prefix for the script handle. These include the following script handles:

  • wp-a11y
  • wp-annotations
  • wp-api-fetch
  • wp-autop
  • wp-blob
  • wp-block-library
  • wp-block-serialization-default-parser
  • wp-blocks
  • wp-components
  • wp-compose
  • wp-core-data
  • wp-data
  • wp-date
  • wp-deprecated
  • wp-dom-ready
  • wp-dom
  • wp-edit-post
  • wp-editor
  • wp-element
  • wp-escape-html
  • wp-format-library
  • wp-hooks
  • wp-html-entities
  • wp-i18n
  • wp-is-shallow-equal
  • wp-keycodes
  • wp-list-reusable-blocks
  • wp-notices
  • wp-nux
  • wp-plugins
  • wp-polyfill-element-closest
  • wp-polyfill-fetch
  • wp-polyfill-formdata
  • wp-polyfill-node-contains
  • wp-polyfill
  • wp-redux-routine
  • wp-rich-text
  • wp-shortcode
  • wp-token-list
  • wp-url
  • wp-viewport
  • wp-wordcount

Documentation for these packages can be found in the Gutenberg Handbook. They are also available for consumption via npm under the @wordpress scope (excluding polyfills).

Each WordPress package above assigns itself to the global scope under the wp namespace. For example, if your theme or plugin enqueues wp-editor, it will be made available at window.wp.editor in your browser. Conversely, you should also make sure that, for any JavaScript in your plugin which references a wp-namespaced library, the associated script handle is defined as a dependency of your script using the third argument of wp_enqueue_script and wp_register_script.

Vendor Dependencies

The following vendor dependencies have been added in WordPress 5.0:

For vendor scripts in particular, there is a chance for conflict if a plugin or theme registers their own copy of the dependency with the same un-prefixed name. There is a greater likelihood if there is a large version mismatch between the registered scripts.

In general, a plugin should seek to avoid naming collisions by following the best practice of “Prefix Everything” as prescribed in the Plugin Handbook. While this can sometimes result in multiple copies of a script being present in a page, it reduces the chance for breakage and grants WordPress the option to use the unprefixed name in the future.

For dependencies which assign themselves to the global window scope, wp_add_inline_script can be used to ensure it is assigned to a global name unique to your plugin or theme. For example, the following snippet demonstrates including React on a page for a plugin without interfering with a core-enqueued copy of React, whether or not it exists:

wp_enqueue_script( 'myplugin-react', 'https://unpkg.com/react@16.6.0/umd/react.production.min.js' );
wp_add_inline_script( 'myplugin-react', 'window._originalReact = window.React;', 'before' );
wp_add_inline_script( 'myplugin-react', 'window.mypluginReact = window.React; window.React = window._originalReact;' );

With the above snippet, your intended copy of React will be guaranteed to be available at window.mypluginReact . This pattern can be applied to any vendor dependency to ensure compatibility with libraries added to WordPress in the future.

If your plugin or theme registers a script with using one of the above script handles as its registered name, consider taking one of the following steps:

Depending on whether you plan to continue support for versions of WordPress earlier than 5.0…

  • If you are only intending to target 5.0 and newer, verify compatibility between the versions of the library and simply remove your plugin or theme’s registration of the conflicting script handle.
  • If earlier version support is needed, and assuming your script registration occurs after the default scripts are registered (after wp_default_scripts), check for whether the script handle is already registered , then register or enqueue your copy of the script, optionally deregistering the core-registered script. Note that since core code targets a specific version of the vendor dependency, deregistering the script may have adverse effects on screens where it is used (notably the new editor screen).
    • Alternatively, follow the pattern as described above to assign your plugin’s copy of the library to a unique name.

Lodash Global

By default, Lodash will assign itself on the global scope using the _ name. Since WordPress will continue to bundle Underscore for the foreseeable future (see #43733), the core-registered Lodash adopts an approach similar to the enqueuing of jQuery to avoid naming conflicts. It does so using Lodash’s _.noConflict, assigning Lodash to the global scope as window.lodash

For this reason, if your plugin or theme uses Lodash as a dependency, you should make sure to not cause _.noConflict to be called multiple times in conflict with the core-registered script.

  • When using the copy of Lodash registered by core, your code should reference it by the window.lodash global.
  • When enqueuing your own copy of Lodash, you should only call Lodash’s _.noConflict under the condition that window.lodash is not already assigned and that the core-registered Lodash will not be included on the page.

In general, the _ global should be used only to reference Underscore.

React and wp-element

When extending the new editor interface, you should use the new wp-element script handle, rather than React directly. The element package is a thin abstraction over the React interface, and implements most all of the same functionality. Targeting wp-element will ensure the greatest compatibility for your plugin as new versions of WordPress are released.

Refer to the wp-element package documentation and React website for more information. 

#5-0, #dev-notes, #javascript

Javascript Chat Summary – December 4, 2018

Below is a summary of the discussion from this week’s JavaScript chat (agendaSlack Transcript)

Have a topic for discussion for the next meeting? Leave a suggested edit on next week’s agenda.

Agenda: Holiday / WCUS scheduling

Slack Conversation

We agreed to cancel the #core-js meetings for December 11th (post-WCUS travel), December 25th (Christmas), and January 1st (New year). @aduth posted a cancellation notice here: https://make.wordpress.org/core/2018/12/04/javascript-weekly-chats-wordcamp-us-holiday-scheduling/

Agenda: Linting

Slack Conversation

A PR which extracts Gutenberg’s ESlint config to its own package by @gziolo has been merged. It’s set to be published to NPM as @wordpress/eslint-config. Publication is currently blocked by the 5.0 RC freeze, but is expected to land around contributor day together with a post outlining revisions to the JavaScript coding standards prepared by @aduth

We also discussed how to manage custom eslint rules. Some linting rules might not be useful outside of the context of WordPress core or Gutenberg. We decided for now to go the same path as the Jest eslint package. For the time being we will have one package with multiple configs, which will allow consumers to select the configs they need. 

Agenda: 5.0 Script Changes

Slack Conversation

With WordPress 5.0, a few vendor scripts (like lodash) are being included in core. For these scripts in particular, there is a chance for conflict if a plugin or theme registers their own copy of the dependency with the same un-prefixed name. There is a greater likelihood if there is a large version mismatch between the registered scripts.

Different approaches to prevent this were discussed. @aduth is working on a devnote to help integrators prevent these kinds of conflicts from happening.

#javascript, #meeting-notes

JavaScript Weekly Chats – WordCamp US & Holiday Scheduling

As discussed in today’s chat, the following meeting dates for the JavaScript Weekly Chat will be cancelled due to WordCamp US travel and in observation of upcoming holidays:

  • December 11
  • December 25
  • January 1

#javascript

Javascript Chat Summary – November 27, 2018

Below is a summary of the discussion from this week’s JavaScript chat (agenda, Slack Transcript)

Have a topic for discussion for the next meeting? Leave a suggested edit on next week’s agenda.

Agenda: WordCamp US

Slack Conversation

The question was posed “Who is going to WordCamp US” followed up by some shared info about what folks from the js team are doing at contributor day:

  • @omarreiss along with @atimmer are working on docs parsing for devhub.
  • @gziolo is getting into e2e setup exposure for core (related: https://github.com/WordPress/gutenberg/issues/12313)
  • @aduth suggested it’d be nice if there could also be some work around automating as much as can around things like package/bumps dependency management (or at least talking that through).
  • @jorgefilipecosta mentioned there will be a table dedicated to Gutenberg and everyone is welcome.  Some “good first issues” will be prepped for first-time contributors and there will also be some higher level discussions around server-side awareness of blocks and the blocks options mechanism.
  • @adamsilverstein will be co-leading the Core group, with mention of Javascript work in the description.
  • There will also be a group focused on tests where the test discussions/work may fit or at least benefit from some cross collaboration between tables.

Lot’s of ways to get involved at WordCamp!

Open Floor: Consolidation of our ESLint configurations

Slack Conversation|Related Github Issue

Summary: Consolidating various eslint configurations and extracting them into their own package.

This was originally blocked by introducing the remaining standards changes as a proposal via Make/Core (see https://make.wordpress.org/core/2018/7/25/javascript-chat-summary-july-24th/)

Actions:

  • publish the new @wordpress/eslint-config package.
  • shortly after, or around the same time, publish a make/core post outlining proposed changes to the WordPress javascript standards and references the new published package as the codified representation of them.  
  • the post invites feedback/comments on the proposed changes and responses will help tailor how the package is iterated on and also what gets updated in the official javascript standards documentation for WordPress after a week of comments.

#javascript

JavaScript chat summary – November 20th

Below is a summary of the discussion from this week’s JavaScript chat (agendaSlack transcript).

Have a topic for discussion for the next meeting? Leave a suggested edit on next week’s agenda.

We tried to keep the meeting succinct as many people are pushing out a Gutenberg release.

Correcting Package Global Names

Relevant context in a previous Slack discussion. Question: Should we “deprecate” wp.escapeHtml to wp.escapeHTMLwp.tokenList to wp.TokenList?

There was a bit of a back and forth whether this should be something that is addressed now. At the end we concluded to add this to the list to address in a 5.0.x release.

Npm packages publishing workflow

From last week, we discussed this very briefly to keep it in our mind space. Link to the relevant issue on the Lerna repository.

#chats, #javascript, #meeting-notes

JavaScript Chat Summary – November 6th

Below is a summary of the discussion from this week’s JavaScript chat (agendaSlack transcript).

Have a topic for discussion for the next meeting? Leave a suggested edit on next week’s agenda.

Node LTS 10.13.0

With the tagging of a new Node LTS 10.13.0 last week (from 8.x), both Gutenberg and Core builds are now running the latest version.

Data Module Generic Store API

refactoring of the data module has been merged, and it now exposes a new optional lower-level API for non-Redux stores, or more personalized instances of a Redux store.

Refer to the documentation for more information.

JavaScript Future Backwards Compatibility (and React)

Discussion: How can WordPress continue its commitment to backwards-compatibility while also not perpetually lagging behind the current version of dependencies (specifically, but not exclusively React).

Considerations:

  • Explore what it could look like to version WordPress scripts
  • Targeting the abstraction (wp.element) an intentional point in ensuring consistent version use.
  • Provide and/or surface codemods if it comes to the point of being forced to introduce a breaking change (Facebook does similarly with React)
  • Gutenberg’s deprecation pattern is not something which would necessarily continue post-5.0, but could serve as precedent for a future deprecation model

Action Items:

  • Compile a document which outlines expectations for a plugin author to anticipate and account for future compatibility, how and when a breaking change would be introduced

Implementing End-to-End Tests in Core

Continuation of discussion from last week.

Problem: How can Gutenberg’s end-to-end test suite be brought into the core development workflow?

Considerations:

  • Not blocking for a 5.0 release
  • Tracked at #45165
  • Having an end-to-end testing solution is useful for more than just the editor, and useful for more than just core development

Solutions:

Make some core part of the end-to-end solution available in @wordpress/scripts.

i18n Core Merge Update

@omarreiss shared the following update:

WP-CLI: Make sure wp i18n CLI command includes JavaScript translations when generating potfiles. [Done] Relevant PRs: https://github.com/wp-cli/i18n-command/pulls?q=is%3Apr+is%3Aclosed+author%3Aherregroen .
Meta: generate translations on translate.wordpress.org for core, themes and plugins. [MVP Done] Ticket: https://meta.trac.wordpress.org/ticket/3748
Meta: generate and serve JS language packs from translate.wordpress.org for core, themes and plugins. [Has patch] Ticket: https://meta.trac.wordpress.org/ticket/3876.
Core: Logic to load JS translations. [Done] Ticket: https://core.trac.wordpress.org/ticket/45103
Core: API to register JS translations for a script. Needs meta side of things to be finished. [Has patch] Ticket: https://core.trac.wordpress.org/ticket/45161
Make: Publish an update and a devnote on how the JS translations work. [todo @omarreiss / @herregroen]

@herregroen shares that for most plugin authors who host their plugins through the plugin repository, the change in workflow should be a matter of using wp_set_script_translations in place of where traditionally one would use wp_localize_script.

Reflecting on @wordpress/hooks

Prompt: As a retrospective of how wp.hooks has been used in the development of core, what feedback do developers have to share?

Feedback:

  • @youknowriad : “In general I’m thinking JavaScript is not a good fit for our hooks because JavaScript is a real time UI not like PHP where the flow is linear. The UI has to be Reactive and it’s very hard to achieve with hooks without pitfalls.”
  • @omarreiss : “I think it might also not be the pattern we want to teach the WP community.”
  • @herregroen : “I would give some thought to deprecating before release to send a clear message going forward. I think it would be confusing to have this familiar API and then never expand it and soon after start deprecating it.”
  • @aduth : “My general experience with them is that they’re not completely avoidable, but in the majority of cases I’ve seen them proposed, it’s been the wrong way to go about a problem with some serious non-obvious consequences and I’ve thus looked to them as a “footgun” (a tempting tool too easy to use wrongly)”
  • @adamsilverstein : “i’ve mainly tried using the withFilters HOC which seemed to work well, i’m not really sure where else hooks have been used in Gutenberg. I agree they can easily be misused and better approaches are often available.”
  • @schlessera : “It’s a procedural pattern that quickly breaks down once you go past procedural code, even in PHP.”

Takeaways:

There’s some general consensus that the pattern is not a good fit for how Gutenberg has been architected, and it’s assumed that this will apply as generally true for core features written in a similarly JavaScript-oriented approach.

It’s also true that there is usage of JavaScript hooks within Gutenberg for which a better alternative has surfaced. Thus, they will likely remain a tool, albeit one we should consider to avoid as much as possible, and limit exposure and advocation.

Action Items:

Consider a communication plan for the role of hooks (future agenda item).

#javascript

JavaScript Chat Summary – October 30th

Below is a summary of the discussion from this week’s JavaScript chat (agendaSlack transcript).

Have a topic for discussion for the next meeting? Leave a suggested edit on next week’s agenda.

Meeting time adjustment

Due to DST and starting next week, the #core-js meeting time will be moved to 14h UTC.

Node 10.x LTS

A new LTS version of Node.JS has been released. As agreed upon on previous meetings, WordPress is going to follow the LTS schedule of Node.JS which means, we’re going to start using this new LTS version in local environments (Gutenberg and WordPress).

The systems team has been also notified to upgrade the WP.org servers to Node 10.13 LTS.

E2E Tests in Core

End 2 End tests are automatic tests simulating user interactions using a browser in a production environment. Gutenberg uses Google Puppeteer and a docker environment to run a suite of various e2e tests that include:

  • Creating and publish content,
  • Writing Flow,
  • Accessibility tests,
  • Extensibility tests.

We discussed during the meeting approaches to make the E2E Test setup and the test suite available for:

  • Plugin Authors:  to setup their own e2e tests,
  • Core: To validate that the Gutenberg integration is working properly and allow other parts of WordPress Core to be tested using this setup. 

Action items

  • Explore making the e2e test setup available as an npm package. cc @gziolo
  • Explore making a package containing the Gutenberg e2e test suite to be able to run it in Core.

Shorter-term, we discussed the possibility of duplicating the tests in Core to validate the Gutenberg integration and package updates. 

If you have some availability and would like to help with any of these items, please let us know in the comments.

#javascript

Javascript Chat Summary – October 23, 2018

Below is a summary of the discussion from this week’s JavaScript chat (agendaSlack Transcript)

Have a topic for discussion for the next meeting? Leave a suggested edit on next week’s agenda.

Agenda: Should wp.hooks support the special all hook?

Slack Conversation

In Gutenberg#8602 it is raised if we should add support for an all action in wp.hooks in order to match feature parity with the current PHP hooks system in WordPress core. While there were no real objections raised in the chat, pretty much everyone present agreed with this comment:

If it is primarily intended for debugging, then it might be worth exploring optimizations to avoid any impact in typical usage, e.g. monkey-patching runHooks when an all hook is added.

@aduth

Actions

  • No interest was expressed in the issue. If anyone wants to take it on, there wouldn’t be any objections either.

Agenda: Ways to optimize the package updating process

Slack Conversation

The process for updating packages needs to be optimized further. Right now any fix on a package has to follows the cumbersome flow of Gutenberg PR -> lerna release -> core ticket -> update package.json -> commit. We need to make this smoother.

This problem would probably not exist once everything is merged into a single monorepo hosted on git. But that doesn’t seem feasible just yet. Could we maybe mimic the advantage of having a monorepo a bit by getting more tooling into WordPress core and build straight from Github source? That would at least decouple publication of packages from being able to consume their changes in WordPress core development. 

It was raised by @gziolo that installing Gutenberg straight from Github with npm is not an option because Gutenberg consumes local packages which can’t be resolved by npm. The solution proposed is to take a similar approach to how Gutenberg packages are updated for Drupal.

This is done with an install script that simply clones Gutenberg into node_modules and builds the scripts in Gutenberg itself. While not a very elegant solution, this could work and drastically improve the process of keeping the packages updated.

Actions

  • @atimmer will work on a proof of concept.

Open floor: JS i18n

Slack Conversation

Good progress is being made on JavaScript language packs. 🎉 @herregroen is working together closely with @nerrad, @swissspidy and @ocean90 to land this. There seems to be a great deal of consensus and the work is nearing completion.

#corejs, #javascript

Javascript Chat Summary – October 16, 2018

Below is a summary of the discussion from this week’s JavaScript chat (agenda, Slack Transcript)

Have a topic for discussion for the next meeting? Leave a suggested edit on next week’s agenda.

Agenda: “Props” for Gutenberg Merge

Slack Conversation

How are props being handled for the merge of Gutenberg code?

  • consensus was mostly reached on Github profile attribution for any involved in a pull request.
  • There were not concrete plans for technical process implementation of props yet.

Actions

  • Discussion can continue in the meeting notes, or revisited in a future meeting.

Agenda: “Internationalization”

Slack Conversation

  • Proposal for language packs
  • for v1, utilize `wp_localize_script` for loading/queuing translations.
  • for v1, generate translation file (po,mo,json…) for every single JS file

Actions

  • split this out into a meta trac ticket and create tickets/issues on different projects as necessary. (owned by @herregroen)

Agenda: Plugin and Block Scaffolding

Slack Conversation

There are some recently released projects designed to aid developer experience around plugins and blocks for Gutenberg:

  • https://github.com/youknowriad/wp-js-plugin-starter
  • Work also started on a solution based on the above which is purely JS based.

Action:

  • continue feedback/evaluation on the pull request

Agenda: Pending bump of Node’s LTS version from 8.x to 10.x

Slack Conversation | Context

Action:

  • probably only request a bumping of the relevant files with node version in them.
  • possibly some docs updating needed.
  • revisit in a following meeting.

#javascript

JavaScript Chat Summary – October 9th

Below is a summary of the discussion from this week’s JavaScript chat (agendaSlack transcript).

Have a topic for discussion for the next meeting? Leave a suggested edit on next week’s agenda.

Preparing for WordPress 5.0

Action items

Annotations API in Gutenberg

  • The foundation work will be shipped in 4.0: The RichText package and the RichText structure.
  • A custom format API will be added. Likely for 4.1.
  • The annotations API should be built on top of this custom format API.

Action items

  • Continue the work on the custom format API targeted for 4.1: @iseulde
  • Coordinate with the Annotations API PR: @atimmer @iseulde

Generic Data Store API

The Data Module of Gutenberg is composed of two parts:

  • The Producer API: Registering stores, selectors, actions.
  • The Consumer API: Consuming selectors and actions in components and other scripts.

@coderkevin proposed to make the producer API less opinionated allowing custom stores implementations to leverage advanced use-cases for big applications/plugins like Calypso or WooCommerce while ensuring backward compatibility for the current implementation.

No blocker was raised on the Core side and the work should continue on the proposed PR.

Action items

#corejs, #javascript