Monday, November 24, 2014

Fiddler 1 Minute Tip: Examine "ASAP" Serial Events

Two examples of common serial events that depend on server data are:
  • Redirect to a new page as soon as feedback to a server is done.
  • Ping a server once an answer from a different server was received.
How can you examine and validate that the events are indeed not only firing in serial order, but are happening ASAP, i.e. no accidental waiting between events is taking place?
Fiddler’s “timeline” tab can help soothe away your worries!
  1. Using CTRL+CLICK, select the two (or more) events you wish to inspect:
  2. Open the “timeline” tab and look at the graph:
If you’ll notice that the horizontal axis for this graph represents time, you’ll be able to see that the event sending data to the “redirect” URL started as soon as an answer from “report.json” was returned from the server. Joy!
Finally, remember that you can select more than two events if needed, so more complex debugging scenarios can also be examined this way.

Tuesday, November 4, 2014

Lazy Load RequireJS Modules from a Remote Server over HTTP OR HTTPS

The Need

General Problem


  • We need to "lazy load" a RequireJS module, stored in a file in a remote server. 
  • This server has a different domain than the site hosting our code, so using an absolute URL as a path to the module is needed.  
  • We need to support loading the file over HTTP or HTTPS, while still using an absolute full path URL.

Specific Example

We need to load the "target" function from the following file, which is stored in a different domain (URL) than our current site:

module.js, stored at: http://www.server.com/module.js
/*===Inner Module Dependencies===*/
define("text!module.html!strip", [],
  function () {
      return '<div></div>';
  });
define("text!module.css", [],
  function () {
      return 'div{color:blue}';
  });
/*===Module===*/
define("http://www.server.com/module.js",
  ["require", "text!module.html!strip", "text!module.css"],
  function (require) {
      /*Module Dependencies*/
      var html = require("text!module.html!strip");
      var css = require("text!module.css");
      /*Define function*/
      function target() {
          /*...*/
      }
      /*Return Module*/
      return target;
  }
);

The Problem

When attempting to load a specific module over HTTPS, the module's name doesn't match the URL given to the require function, and an empty module is returned:

Example


lazyLoader.js
require(["https://www.server.com/module.js"], // ERROR :(
  function (module) {
      /*Not Called*/
  },
  function (err) {
      /*Called since no module matching the
       required name was found in the loaded file*/
  }
);

The Solution

Create an alias module which is named like the HTTPS URL of the original module and only returns the original module.

Example


"Alias" Module inside module.js
/*This will be returned if module was requested via HTTPS*/
define("https://www.server.com/module.js", ["require", "http://www.server.com/module.js"], function (require) {
      return require("http://www.server.com/module.js");
  }
);

What Just Happened?


Inline Naming RequireJS Modules

RequireJS allows for optional inline naming of modules, done by passing in an optional 1st parameter to the define function when defining a module:

Example

define("OPTIONAL_NAME",
  [/*DEPENDENCIES*/],
  function (require) {
      /*CODE*/
  }
);

Why is Inline Naming Needed?

Inline naming allows for placing multiple modules inside the same file. In the given example, this would cause requiring "OPTIONAL_NAME" to return the module named as such instead of the module stored in the filepath named as such, which is RequireJS's default behavior.

This naming is usually done automatically by the RequireJS optimizer when combining multiple modules into a single file.

How has Inline Naming Helped Solve Our Specific Problem?

In our "lazy load" scenario, the file was stored in a remote URL and only the module named "http://www.server.com/module.js" was actually needed. To support HTTPS as well, an alias module, named like the HTTPS URL, was created. (It goes without saying that the file server must be configured itself to support HTTPS, but that is beyond the scope of this post).

A Final Word about Automation

Creating an alias module can be done manually, but we prefer using an automation tool such as Grunt for tasks like this.