WordPress.org

Make WordPress Core

Opened 6 months ago

Last modified 4 months ago

#40834 new enhancement

Introduce a JS module pattern to WordPress

Reported by: omarreiss Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: General Keywords:
Focuses: Cc:

Description

This is a discussion ticket proposing an approach for implementing module pattern in WordPress core JavaScript.

Introduction to modules.

For anyone reading this and wanting to learn about JS modules, Preethi Kasireddy wrote an excellent two part introduction. You can find it here:

Goals

The higher level concerns that I based this on are:

  • The need to modularize our JS in order to make it more maintainable, robust and reusable.
  • (Backwards) compatibility with current state and wp_register_script / wp_enqueue_script.
  • Great developer experience.
  • Allowing core to take advantage of the rich npm ecosystem and current day ES standards.
  • Lowering the barrier for the greater JS community to participate in WordPress.
  • The benefit of aligning ourselves with Calypso as much as possible.

Module definition

Currently in core modules are only being used in the WP media library, which follows Common JS module definition, see modularization ticket. I would however prefer to switch to ES6 module definition as this is where the JS world is moving and most browsers seem to be working on adding support as well. Another thing to keep in mind is that Calypso is also using ES6 module imports.

I think it should be a priority for us to align with ES standards as much as possible, especially since transpilers like Babel and different available polyfills have already solved all major browser compatibility problems for us. Embracing the latest (widely adopted) practices will also help open up WordPress as a project to the greater JavaScript community.

Module bundler

The current bundler of choice is Browserify. The other options are Webpack and Rollup.

Webpack is currently the weapon of choice in most React projects. I think this is especially because the development experience is very enjoyable due to its hot reloading capabilities and its ability to only recompile the module that has been changed instead of rebuilding the entire build every time. This is especially great for developing single page apps. As developers we could take advantage of these features as well if we add some code that allows the scripts to come from a different server. This would also be very useful for production as I think it makes a lot of sense to serve our JS from a CDN in the future.

The React project itself has recently switched from Browserify to Rollup. By using a technique called tree shaking it's able to dramatically reduce file size of the bundle. It's also possible to include as a Webpack plugin or Browserify transform.

Here's a good article comparing Browserify and Webpack.

I would prefer to switch to Webpack, especially if we can make the developer experience as smooth as not having to reload pages anymore to see changes directly reflected in the browser. The fact that Calypso is also using Webpack is also a big plus.

How can we go about bundling the JavaScript in core?

Taking into account backwards compatibility, once a script has been registered in core, it can not be removed. Plugin and theme authors unregister / replace scripts or enqueue scripts that aren't enqueued by core on certain screens. Therefore I'd say we might have a bundled file for every script that is currently registered in core. Anything that is in a registered script can of course be extracted away into a separate module. This will give us a ton of freedom as modules can be rearranged without having to worry about bc.

What are the implications on current API's?

Anything that needs to be on the global wp object could still be assigned to it. However, using modules should eventually lead to better composition. Modules that don't need to know about global API's shouldn't depend on them or assign themselves to global objects. I believe it's possible to configure Webpack to do these assignments for us. Of course it's always possible to do it in a separate file.

Do we need to move everything into modules straight away?

No, modularizing code is typically something that can be gradually implemented. We just need to agree on the direction so we can build a roadmap and start implementing it. I do think we need to document our decisions well and make sure core is in sync with that. It will be highly beneficial to have good examples in the code itself of how things can be modularized. There might also be a few things which we simply don't want to modularize, like jQuery for instance, since jQuery needs to be globally available anyway for bc reasons. I am curious to see opinions about this since there could be architectural reasons to still do this.

Do all modules we for core need to reside in core?

I would very much like all general purpose modules to be extracted to a separate package on which core depends. We are an open source project. If we can organize our code in a way that makes it more reusable for the greater community of developers, we should do so. Anything core specific should of course reside in core.

Using modules in core will also expose endless new possibilities in terms of depending on third party libraries / modules. This is another great opportunity if you ask me to build stronger ties with the greater JS community.

Change History (7)

This ticket was mentioned in Slack in #core by omarreiss. View the logs.


6 months ago

This ticket was mentioned in Slack in #core by aduth. View the logs.


6 months ago

#3 @westonruter
6 months ago

See also #30277 for doing this in the customizer codebase.

#4 @jhabdas
5 months ago

My .02 is that WordPress already has a great module system whereby users can enqueue anything they want and define deps. It's extremely flexible.

I've personally worked on both enterprise React projects and have published React Native to iOS, both of which included extensive use of Webpack. My personal experience as a developer was not a happy one. Webpack is very complex IMO, and is a slippery slope WRT the involvement of Babel and friends. If the goal is to provide more modularity in the core to start moving towards ES6 I don't see why you'd need a bundler to do that when browsers will be able to support ES6 modules natively (whereas Node will not anytime soon, and the Node EPS will show the gory tale).

UMD already provides quite a bit of bloat. If you skip straight to ES6 you can use the browser as your REPL and leverage advanced loading techniques coming such as WHATWG Dynamic Imports to leapfrog beyond many emerging frameworks. Building on Node is not easy. Just ask the folks from Ghost Foundation.

Last edited 5 months ago by jhabdas (previous) (diff)

This ticket was mentioned in Slack in #core-js by pento. View the logs.


5 months ago

This ticket was mentioned in Slack in #core-js by adamsilverstein. View the logs.


5 months ago

This ticket was mentioned in Slack in #core-js by omarreiss. View the logs.


4 months ago

Note: See TracTickets for help on using tickets.