Moving to modules

Preview:

DESCRIPTION

You believe in the power of JavaScript modules, but you have an existing app, stack or platform infrastructure to keep running. Between maintenance and new features, where do you carve out time to switch over? After a brief overview of modules and why they're great, we'll dig into how to actually migrate a code base, from plotting your approach to implementation tips. Video: http://youtu.be/FbdcdC8mqwE?t=50m51s (watch the entire video from the beginning for other great talks about shadow DOM and competing task runners) Talk from February 19, 2014 NYCHTML5 Meetup: http://www.meetup.com/nychtml5/events/160684962/

Citation preview

moving to modules@mize

hi!@mize

“moving to modules”?

modules: how do they work?

a unit of code…

…with an encapsulated definition

…that explicitly declares its dependencies

…whose instances can be mapped to different identifiers that expose its interface

benefits

• Clean(er) global namespace

• Eases dependency management

• Reusability

• Testability

should i wait for harmony?

—Sean Mize

“nope.”

goals of harmony• Obviate need for globals

• Orthogonality from existing features

• Smooth refactoring from global code to modular code

• Smooth interoperability with existing JS module systems like AMD, CommonJS, and Node.js

• Fast compilation

• Simplicity and usability

• Standardized protocol for sharing libraries

• Compatibility with browser and non-browser environments

• Easy asynchronous external loading

goals of harmony• Obviate need for globals

• Orthogonality from existing features

• Smooth refactoring from global code to modular code

• Smooth interoperability with existing JS module systems like AMD, CommonJS, and Node.js

• Fast compilation

• Simplicity and usability

• Standardized protocol for sharing libraries

• Compatibility with browser and non-browser environments

• Easy asynchronous external loading

no technical excuse not to migrate now

where do i start?

pick your poison

what do i need?format and loader

node.js/* makeItAwesome.js */!var multiplier = require('multiplier').awesome;!!function makeItAwesome(value) {! return value * multiplier;!}!!exports = module.exports = makeItAwesome;

node.js/* makeItAwesome.js */!var multiplier = require('multiplier').awesome;!!function makeItAwesome(value) {! return value * multiplier;!}!!exports = module.exports = makeItAwesome;!!!!/* app.js */!var makeItAwesome = require('makeItAwesome');!var everything = require('status').good;!!everything = makeItAwesome(everything);

exports = module.exports = ?/* makeItAwesome.js */!var multiplier = require('multiplier').awesome;!!function makeItAwesome(value) {! return value * multiplier;!}!!exports = module.exports = makeItAwesome;!!!!/* Imagine this require() implementation */!function (module, exports) {! exports = some_func;! // re-assigns exports, exports is no longer a shortcut,! // and nothing is exported.! module.exports = some_other_func;!} (module, module.exports);

AMD/* makeItAwesome.js */!define(['multiplier/awesome'], function (multiplier) {! function makeItAwesome(value) {! return value * multiplier;! };!! return makeItAwesome;!});

AMD/* makeItAwesome.js */!define(['multiplier/awesome'], function (multiplier) {! function makeItAwesome(value) {! return value * multiplier;! };!! return makeItAwesome;!});!!!!/* app.js */!define(['makeItAwesome', 'status/good'], function (makeItAwesome, everything) {! everything = makeItAwesome(everything);!});

which?Moving to Node?

☛ Node variant of CommonJS

Primarily in the browser? ☛ AMD + RequireJS, curl.js or similar

Need to share logic across both? ☛ You’ll need help.

ok, but what about…

1. shave fewer yaks 2. choose approach 3. apply consistently

& clearly

pick your battles

useful questions• What are your goals? What would be most

useful for your near-term needs?

• How quickly/completely can/do you need to convert?

• F/E benefits or code reuse across stack?

• Are there other consumers of your libs?

migrate!

migrate!1. Map your dependencies

migrate!1. Map your dependencies

2. Load all of your files via loader

RequireJS shimrequirejs.config({! baseUrl: '/src/js',! paths: {! 'foo': 'legacy/foo'! },! shim: {! 'foo': {! deps: ['bar'],! exports: 'Foo',! init: function (bar) {! return this.Foo.noConflict();! }! }! }!});

migrate!1. Map your dependencies

2. Load all of your files via loader

3. Walk your dependencies, wrapping or converting as you go

[ interlude ]possible sticking points

code sequence/* Old - app.js */!Foo.init();!Bar.init(); // Bar depends on globals created during Foo.init()

code sequence/* Old - app.js */!Foo.init();!Bar.init(); // Bar depends on globals created during Foo.init()!!!!/* Transitional - app.js */!define(['foo', 'bar'], function (Foo, Bar) {! Foo.init();! Bar.init();!});

code sequence/* Old - app.js */!Foo.init();!Bar.init(); // Bar depends on globals created during Foo.init()!!!!/* Transitional - app.js */!define(['foo', 'bar'], function (Foo, Bar) {! Foo.init();! Bar.init();!});!!!!/* Final form - bar.js */!define(['foo']), function (Foo) {! // Former Foo.init logic is now part of Foo's module definition! // so just do Bar stuff!}

globalsYou're using AMD, but others depending on your lib don't (yet).

globalsYou're using AMD, but others depending on your lib don't (yet). !!(function (root, factory) {! if (typeof define === 'function' && define.amd) {! // AMD. Register as an anonymous module.! define(['b'], factory);! } else {! // Browser globals! root.amdWeb = factory(root.b);! }!}(this, function (b) {! // use b in some fashion.! // ...! return amdWeb;!}));

migrate!1. Map your dependencies

2. Load all of your files via loader

3. Walk your dependencies, wrapping or converting as you go

4. Profit!

clean up

clean up• Package management

• Optimize

• Great time to incorporate grunt (or gulp!) w/ linting/validation into your workflow

• Add tests!

don’t wait for harmony.

!

write better code now.

thank you!@mize

Recommended