Project

General

Profile

Actions

Feature #3005

open

Breaking up JS into smaller files

Added by Gregory Magarshak over 1 year ago. Updated over 1 year ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
-
Start date:
09/04/2023
Due date:
10/24/2023 (about 19 months late)
% Done:

0%

Estimated time:

Description

Objective

Typically, each Plugin in an App loads its Module file, which defines the various tools etc. that can be loaded on demand. Including:

Users.js
Streams.js
Websites.js
Assets.js
Places.js

and the proprietary plugins:

Travel.js
Calendars.js
Communities.js
Media.js

However, the Module files have become bloated with various methods of which 99% are not used in a given app, especially on startup. That code can be loaded later, on demand when needed.

We will leave the synchronous methods in these modules as they are. However, almost all the asynchronous methods can be migrated to other files, using the mechanism described below. Asynchronous methods are the ones which return a Promise, or have a callback (you can literally search for the word callback in function signatures), or perhaps take functions or options objects with possible names like onSuccess, onCancel etc.

Mechanism to use

The Q.Method class defined in Q.js is designed to help you refactor such asynchronous methods into methods that first may load an some external JS code, and only then call the method. (Obviously, synchronous methods have no time to do that, since they must return the result in the same thread.)

The procedure is simple: when you find an object with asynchronous methods in a file named MyPlugin/js/MyPlugin.js, like so:

/**
 * @class Q.SomeObject for example
 */

SomeObject = {

  /**
   * Some YUIDoc description
   * @method someMethod
   * @static
   */
  someMethod: function _someMethod (foo, bar, callback) {
     someClosureVariable.a = 5;
  },

  someOtherMethod: function _someOtherMethod (foo, bar, callback) {
     someOtherClosureVariable.b = 5;
  },

  SubObject: {
     anotherMethod: function _anotherMethod () {
        Q.use(someClosureVariable.a);
     }
  }
};
SomeObject.someMethod.options = { ... };
SomeObject.SubObject.anotherMethod.options = { ... };

So you would refactor it like this:

SomeObject = Q.Method.define({

  someMethod: Q.Method.stub,

  someOtherMethod: Q.Method.stub,

  SubObject: Q.Method.define({

     anotherMethod: Q.Method.stub

  }, '{{MyPlugin}}/js/methods/SomeObject/SubObject')

}, '{{MyPlugin}}/js/methods/SomeObject');

// options will be moved to the individual JS files

you would move these methods to a file named MyPlugin/js/methods/SomeObject/someMethod.js like so:

Q.exports(function (someClosureVariable, someOtherClosureVariable) {

  /**
   * @class @.Users // make sure YUIDoc categorizes it correctly
   */

  /** 
   * simply copy the whole method and its body here,
   * including its YUIDoc comments 
   * including the closure references
   * @static
   * @method
   */
  function _someMethod () {
    someClosureVariable.a = 5;
  }
  _someMethod.options = { ... };
  return _someMethod;

});

Notice that there is even an elegant way to port over the closure variables! However, this only works if the closure variables are basically const which means they never change after they are assigned. That is pretty much the case with nearly all the closure variables in these modules, because they are actually Object which are not reassigned to a different value, but inside, the object's properties can be dynamically changed and that's fine. In other words if you had const Foo = {} you can do Foo.bar = 'baz' with no problem, because the const in Javascript refers to the reference not being reassigned, but the Foo object itself is not "sealed" (which is a different concept in JS).

One object at a time

So, carefully go method by method, and commit each time you have migrated one object, such as Q.Users.Web3 or Q.Assets.Web3. Do inner objects and commit before doing outer objects, e.g. (Q.Assets.NFT.Web3 before Q.Assets.NFT)

So, carefully use this mechanism and change one object at a time. Before you commit, you have to make sure everything still works as intended!

Actions

Also available in: Atom PDF