[wp-trac] [WordPress Trac] #28510: Split javascript files in media into modules

WordPress Trac noreply at wordpress.org
Thu Dec 11 23:19:14 UTC 2014


#28510: Split javascript files in media into modules
-------------------------+-----------------------------
 Reporter:  ericlewis    |       Owner:  wonderboymusic
     Type:  enhancement  |      Status:  assigned
 Priority:  normal       |   Milestone:  Future Release
Component:  Media        |     Version:  3.5
 Severity:  normal       |  Resolution:
 Keywords:  has-patch    |     Focuses:  javascript
-------------------------+-----------------------------
Changes (by wonderboymusic):

 * keywords:  needs-patch => has-patch
 * owner:   => wonderboymusic
 * status:  new => assigned


Comment:

 [attachment:browserify.diff] breaks up the Backbone classes in `media-
 models.js`, `media-views.js`, `media-audiovideo.js`, and `media-grid.js`
 into CommonJS 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.

 **Require vs Browserify**

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

 {{{
 define([
     'model/taco',
     'model/burrito',
     'controller/meal'
 ], function (Taco, Burrito, Meal) {
     var Dinner =  Backbone.View.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.

 Require becomes a Grunt task to makes 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 is a tool that allows you to use Node-style CommonJS 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( './controller/meal.js' ),
     Dinner;

 Dinner = Backbone.View.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 Common JS
 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.

 Since we are in experimentation phase, 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/
 router/
 utils/
 views/ (with another round of subfolders)
 audio-video.manifest.js
 grid.manifest.js
 models.manifest.js
 views.manifest.js
 }}}

 **The build pipeline**

 First things first, run `npm install`

 `*.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 with 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 an experiment**

 I would like us to do something like this. I got the idea yesterday to do
 this proof of concept and just ran with it. Consider this a request for
 comments.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/28510#comment:2>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list