Tuesday, June 7, 2011

Programming, it turns out, is hard.

Marijn Haverbeke

Thursday, May 26, 2011

Developing and building RequireJS apps with a central code repository

Most of the projects I develop at work are enterprise Microsoft apps, using Visual Studio and Team Foundation Server. Reusing JavaScript in VS projects typically involves either copying the code (violating the DRY principle) or creating pre-build events to copy the code at build time (a little better, but far from ideal)


I’ve been doing a lot of JavaScript application development lately, and really loving James Burkes RequireJS module loader. For a recent project I ended up copying a non-trivial amount of common utilities code, and decided it was time to figure out a better method to centralize common JavaScript code without requiring a script server and related overhead (HTTP requests) and maintenance.


After some experimentation, and discussion with RequireJS author James Burke, I figured out how to develop and build RequireJS apps using a central repository for common JavaScript code. The basic gist is that you specify a HTTP path to the repository code modules during development, (a localhost website) from which the files are dynamically loaded, and a filesystem path (to the source of the localhost website) in the build configuration file. The RequireJS optimizer consolidates the common modules via the filesystem path, along with the local modules, into a single file for deployment.


This allows me to maintain and version control common JavaScript code in a single project, and use that code in separate projects, much the way I do with dll/project references in compiled languages like C#.

main.js with HTTP path(s):
require(
        {
            paths: {
                //various application path aliases
                “core”: “//localhost/ipayment.core.javascript/scripts/core”
            }
        },
        [
            //direct dependencies
        ],
        function (<dependency>) {
            <dependency>.<method>();
        }
);


app.build.js with filesystem path(s):
({
    appDir: “../”,
    baseUrl: “Scripts”,
    dir: “../../Build”,
    paths: {
        //various application path aliases
        “core”: “../../../iPayment.Core/iPayment.Core.Javascript/Scripts/Core”
    },
    optimize: “none”, //”uglify”, “closure” (Java Only), “closure.keepLines” (Java Only), “none”
    modules: [
        {
            name: “main”
        }
    ]
})


Cool!
Tim


Monday, May 2, 2011

If you wish to make an apple pie from scratch, you must first invent the universe.

Carl Sagan

Friday, April 22, 2011

This kind of “I broke things, so now I will jiggle things randomly until they unbreak” is not acceptable.

Linus Torvalds

Wednesday, April 20, 2011

Using jQuery deferreds is a little like courting a woman: you have to be careful not to make promises you can’t keep.

Me

Friday, April 15, 2011

learning Javascript used to mean you weren’t a “serious software developer”. today, not learning Javascript means the same thing.

James Governor

Tuesday, April 12, 2011

Using QUnit with RequireJS

I have really been enjoying James Burke’s RequireJS library: http://blog.dohertycomputing.com/post/3466960658/requirejs and have recently applied it to a project at my day job. When it came to testing the application, I decided on QUnit for unit testing, and started poking into using it with RequireJS. 


I was able to successfully run tests using the RequireJS approach, i.e., define a test module, with the code to be tested as explicit dependencies, and waiting to start the tests until the module and all its dependencies are loaded. Async behavior is handled via QUnit.stop()/start() as described in the QUnit API: http://docs.jquery.com/QUnit

define(
        [
            “my/moduletotest1”,
            “my/moduletotest2”,
            “my/moduletotest3”,
        ],
        function (moduletotest1, moduletotest2, moduletotest3) {
            return {
                RunTests: function () {
                    test(“mod1test”, function () {
                        QUnit.stop();
                        moduletotest1.ajaxyMethod(arg, function(result) {
                              deepEqual(result, matchExpression);
                              QUnit.start();
                        });
                    });

                    test(“mod2test”, function () {
                        QUnit.stop();
                        moduletotest2.ajaxyMethod(arg, function(result) {
                              equal(result, matchExpression);
                              QUnit.start();
                        });
                    });
                    …
                }
            };
});

Then in the QUnit page script:

QUnit.config.autostart = false;
require(
          [
            “UnitTests/TestModule”,
          ],
          function (testModule) {
            QUnit.start();
            testModule.RunTests();
          }
);

Works like a charm!