Modular JS

liuyicheng@meituan.com

Modular


When we say an application is modular, we generally mean it's composed of a set of highly decoupled, distinct pieces of functionality stored in modules.

当我们说一个程序是模块化的,通常我们指它是由一组存放在模块中的高度解耦的独立功能片段所组成。

http://addyosmani.com/writing-modular-js/

http://www.tuicool.com/articles/UZnq6j

优缺点


可维护性
- 方便组合,分解
- 方便单个模块调试,升级
- 多人协作,互不干扰


可测试性

- 单元测试


性能损耗

发展


内容样式交互混用
⬇︎
分离成独立文件
⬇︎
动态加载
⬇︎
模块化
⬇︎
服务器端 - CommonJS
浏览器端 - AMD

CommonJS


The official JavaScript specification defines APIs for some objects that are useful for building browser-based applications. However, the spec does not define a standard library that is useful for building a broader range of applications.


http://www.commonjs.org/
http://arstechnica.com/business/2009/12/commonjs-effort-sets-javascript-on-path-for-world-domination/
The CommonJS API will fill that gap by defining APIs that handle many common application needs, ultimately providing a standard library as rich as those of Python, Ruby and Java.

With CommonJS-compliant systems, you can use JavaScript to write:

  • Server-side JavaScript applications
  • Command line tools
  • Desktop GUI-based applications
  • Hybrid applications (Titanium, Adobe AIR)

CommonJS Standards


  • Modules
  • Binary strings and buffers
  • Charset encodings
  • Binary, buffered, and textual input and output (io) streams
  • System process arguments, environment, and streams
  • File system interface
  • Socket streams
  • Unit test assertions, running, and reporting
  • Web server gateway interface, JSGI
  • Local and remote packages and package management


CommonJS Implementations


CouchDB ( npm )
RequireJS
RingoJS
SeaJS
curl.js
node.js
when.js



http://www.commonjs.org/impl/

Modules/1.1


Modules/1.1

Sample Code
// math.js
exports.add = function() {
    var sum = 0, i = 0, args = arguments, l = args.length;
    while (i < l) {
        sum += args[i++];
    }
    return sum;
};
// increment.js
var add = require('math').add;
exports.increment = function(val) {
    return add(val, 1);
};
// program.js
var inc = require('increment').increment;
var a = 1;
inc(a); // 2

module.id == "program";

Node.js

Implementations


Modules/1.0 (yes)
Promises/B
Promises/D
Unit Testing/1.0 (yes)

Node.js

modules api


AMD

Asynchronous Module Definition

The Asynchronous Module Definition (AMD) API specifies a mechanism for defining modules such that the module and its dependencies can be asynchronously loaded. This is particularly well suited for the browser environment where synchronous loading of modules incurs performance, usability, debugging, and cross-domain access problems.





It is unrelated to the technology company AMD and the processors it makes.





https://github.com/amdjs/amdjs-api

AMD api



define

require


Loader Plugins

Common Config

define

Sets up the module with ID of "alpha", that uses require, exports and the module with ID of "beta":

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
    exports.verb = function() {
        return beta.verb();
        //Or:
        return require("beta").verb();
    }
});

An anonymous module that returns an object literal:

define(["alpha"], function (alpha) {
    return {
      verb: function(){
        return alpha.verb() + 2;
      }
    };
});

require

define(['require'], function (require) {
    //the require in here is a local require.
});

define(function (require, exports, module) {
    //the require in here is a local require.
});

define(function (require) {
    var a = require('a');
});

 define(function (require) {
    require(['a', 'b'], function (a, b) {
        //modules a and b are now available for use.
    });
});

Loader Plugins


define(['text!../templates/start.html'], function (template) {
    //do something with the template text string.
});

Common Config

{
  baseUrl: './foo/bar'
}

{
  shim: {
    'some/thing': {
      deps: ['a', 'b'],
      exports: 'some.thing',
      init: function (a, b) {
        return some.thing + 'another';
      }
    }
  }
}

{
  paths: {
    "some": "some/v1.0"
  }
}

AMD Implementations


RequireJS


curlJS


Dojo Loader

YUI Modules


Sandbox
+
Namspace

add

// name.js
YUI.add('name', function(Y) {
    Y.namespace('mt').name = 'lyc';
});

use

// index.js
YUI({
  modules: {
    'name': './name.js'
  }
}).use('name', function(Y) {
  Y.log(Y.mt.name);
});




Namespace Are Old School






http://blog.millermedeiros.com/namespaces-are-old-school/




ES6 Modules is comming

ES6 Modules



ES6实现了模块功能,试图解决JavaScript代码的依赖和部署上的问题,取代现有的CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方案。





http://es6.ruanyifeng.com/#docs/class
export & import

// profile.js
export var firstName = 'David';
export var lastName = 'Belle';
export var year = 1973;

import {firstName, lastName, year} from './profile';

function setHeader(element) {
  element.textContent = firstName + ' ' + lastName;
}

Using ES6 modules with YUI




After transpiling






Q & A