Dev Chat Summary: January 31st (4.9.3 week 3)

This post summarizes the dev chat meeting from January 31st (agenda, Slack archive).

4.9.3 update

Updates from focus leads and component maintainers

Servehappy

  • Question from @azaozz in latest meeting: What if the PHP education page (codename "servehappy") was not on any .org-related website, but inside of core?
  • We'd like to ask for feedback on this, what are all your initial feelings on that? Note that this is separate from the prompt for the user to switch the PHP version in their hosting account.
  • Some considerations:
    • The main condition for this to happen is to have the entire content powered by the .org API. The content will be highly dynamic and may need adjustments regularly, so we must not be dependent on core releases to change it.
    • A new API endpoint would need to be built for that purpose that should send the content of all sections of the page, to some degree targeted to the current request. Parameters like the PHP version active, plugin slug (in case the user is sent to the page because a plugin requires a higher PHP version), data about the host (if available), would be part of the request. This would allow the content to target the user's problem as well as possible.
    • All content that endpoint returns should not be hard-coded, but easily manageable through a backend (maybe a special section in make.wordpress.org/core/?).
    • How is it possible to change the .org API? Who has access? We'd need to figure out how the process of working on that could be streamlined.
    • Summary of thoughts from PHP meeting recap
  • Next step is for the Servehappy team (including @azaozz) to discuss this during the next PHP meeting (on Monday 16:00 UTC) and come back with a recommendation

General announcements

  • @afercia uncertain about what can go in a minor release, specifically about fixes or small enhancements that require a dev note given that minor releases auto-update
    • Changes that require a dev note in a minor release, with such a short notice, don’t give plugin and theme authors the time to update.
    • As further changes to the minor release policy, best to have recommendation prepared for upcoming devchat

Next meeting

The next meeting will take place on February 7, 2018 at 21:00 UTC / February 7, 2018 at 21:00 UTC in the #core Slack channel. Please feel free to drop in with any updates or questions. If you have items to discuss but cannot make the meeting, please leave a comment on this post so that we can take them into account.

#4-9-3, #core, #core-editor, #core-php, #dev-chat, #documentation, #js, #minor-releases, #servehappy, #summary

Dev Chat Summary: January 24th (4.9.3 week 2)

This post summarizes the dev chat meeting from January 24th (agenda, Slack archive).

4.9.3 planning

  • 4.9.3 beta was supposed to be built on Tuesday, but some tickets were still actively being worked on, so it will be done after dev chat
  • @sergey to post on Make/Core with notable fixes, things to test, and link to JSHint dev note
  • RC and release are still planned for 29th and 30th, respectively
  • Note: 4.9.3-beta1 is out, post is still pending

JSDoc initiative

  • @atimmer prepared a Make/Core post to announce the JSDoc initiative
  • Feedback on the draft is welcomed, send Slack DM to @atimmer with updates
  • It looks a lot like the inline hook documentation and the setup is the same: file by file, everyone can claim a file, at the end all files will be documented
  • @kadamwhite to publish post when its ready

General announcements

Next meeting

The next meeting will take place on January 31, 2018 at 21:00 UTC / January 31, 2018 at 21:00 UTC in the #core Slack channel. Please feel free to drop in with any updates or questions. If you have items to discuss but cannot make the meeting, please leave a comment on this post so that we can take them into account.

#4-9-3, #core, #dev-chat, #documentation, #js, #jshint, #summary

The Case for JS Modules

I originally posted some of this content here: Split javascript files in media into modules

The patch on that ticket breaks up the Backbone classes in media-models.js, media-views.js, media-audiovideo.js, and media-grid.js into modules and injects them via Browserify on build/watch into a built file. Let’s start at the beginning.

Brain overload

Files that are 1000s of lines long are hard to consume. We try to alleviate this by adding copious amounts of docs. Still, it’s a lot to look at. Ideally, we would break our files into smaller modules and then somehow join them together in a build process.

It is common practice to serve (sometimes very large) minified files for JS and CSS that have concatenated many smaller files together and uglify’d (minified/obfuscated) them. It is no longer common or best practice to develop with huge files. We can learn a lot from emerging front end development trends, especially those from the Node/NPM community. In some cases, we can even share code.

We’ll use Media as the main culprit, but this could apply to any “manifest” – a term I use to describe files that contain the entire public API for a feature. Something like media-views.js, it might be nice to bounce from view to view in the same file, provided you know exactly what you are looking at, what depends on what, etc.

I have found, it is completely overwhelming for almost everyone. It would be great if each discreet piece could be viewed in isolation with its dependencies clearly stated.

There are many ways to accomplish the splitting of large files. I want to focus on 2 of the most common.

Vocabulary

Backbone is one of a growing number of MV* frameworks for JavaScript. A large majority of the code related to media either belongs to a handful of Models or to the increasingly large library of Views and View Templates.

Views are the building blocks for the presentation of Media (you know, “the Media Modal” or 4.0’s “Media Grid”).

The main canvas on which these Views are stitched together are called Frames, which are themselves Views – tilting our use of Backbone more towards MVP, P standing for Presenter.

We have Controllers, which are called States, but they belong to a Frame (Presenter! also a View!), so anyways…. for now….

When we create new UIs, we are more than likely adding new Views/Templates, or updating existing Views.

If we wanted to move from one large file to many files that each contain a class, we would create Modules.

Grunt is a task runner. We use Grunt to build our src directory into our build directory.

Require

Require is a great tool for converting AMD modules into built files. Require leans on Dependency Injection in its syntax:

define([
    'models/taco',
    'models/burrito',
    'controllers/meal'
], function (Taco, Burrito, Meal) {
    var Dinner = Meal.extend({
        // taco-related code
    });
    return Dinner;
});

This syntax works great, unless you have way more dependencies. Refactoring code could unwind a module that has a lot of dependencies, but if you are just trying to convert legacy classes into a module, Require starts to get a little weird. Concrete example: Frames have a TON of dependencies.

Require becomes a Grunt task to make one big file by recursing the dependency tree in an initial manifest. Require, by default, loads JS asynchronously, which can cause race conditions with plugins or themes that expect code to be registered on $(document).ready() or window.onload.

Require works even if you don’t build via Grunt.

Browserify

Browserify is a tool that allows you to use Node-style modules and run them in a browser without changing from the Node syntax. Browserify requires a build for this to work.

Using our example from above, this is the syntax for Browserify:

var Taco = require( './models/taco.js' ),
    Burrito = require( './models/burrito.js' ),
    Meal = require( './controllers/meal.js' ),
    Dinner;

Dinner = Meal.extend({
    // taco-related code
});

module.exports = Dinner;

Browserify leans more towards the Service Locator pattern.

Browserify scans the abstract syntax tree (AST) of your JS code to compile dependencies. Your modules themselves get wrapped in their own scope like so:

(function (require, module, exports) { 
    .....YOUR_MODULE..... 
})

After spending a lot of time messing around with both: I think we should use Browserify.

Converting “Legacy” Code

The media JS code is some of the most “modern” code in WordPress, but it still clunkily lives in huge files. To convert the code into modules, we need to make a lot of individual files (one for each Backbone class).

We also need to make sure we maintain the existing wp.media namespaces for backwards compatibility. We don’t want any existing functionality to change, we just want to build the files differently.

Even though the code is defined differently, wrapped in a new scope, and looks different when “built”, we can still maintain our current API design: what is publicly accessible now will remain publicly accessible.

In the patch

Disclaimer: this patch is for experimentation only. It will go stale probably before this post is published. It works, but it is only a playground for now. If this moves forward, it will be a laborious Subversion process to create a bunch of new files.

I have added a folder to wp-includes/js, media, that contains the modules and the built manifests. My patch adjusts script-loader.php to use these new paths.

media contains the following files/folders:

controllers/
models/
routers/
utils/
views/ (with another round of subfolders)
audio-video.manifest.js
grid.manifest.js
models.manifest.js
views.manifest.js

The build pipeline

If you are following along with that patch and want to see this in action, run in the project root:

npm install

Afterwards, run:

grunt watch

*.manifest.js files get built into *.js files when you change a file in media/*, provided you are running the grunt watch task. The watcher will automatically call browserify:media and uglify:media when those files change. This allows you to run your site from src or build, and you will still get Browserify’d files. SCRIPT_DEBUG will either run *.js or *.min.js, just like any other minified JS in core.

This is a proposal

I would like to hear feedback from the overall community and certainly from our fair share of JS-trained ninjas. A common reason to *not* do something like this is the barrier to entry for new developers. I would argue in this case that the code becomes MORE readable and understandable. I was shocked myself to see how much simpler it was to absorb one piece at a time once the code was laid out in modules.

#backbone, #js, #media

Working on wp-lists, colors, fades

Working on wp-lists, colors, fades

#js