We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
模块化开发可以提高代码复用率,方便代码管理。一般来说一个文件就是一个模块,得外暴露变量或者函数。目前比较流行的模块化的规范有:AMD、CMD和CommonJs以及ES6 的 module。
commonjs主要由node推广使用。
关键命令:module.exports = 、require()
module.exports =
require()
例子:
// 定义模块math.js function add(a, b) { return a + b; } module.exports = { //对外暴露的函数、变量 add: add }
// main.js // 引用自定义的模块时,参数包含路径,可省略.js var math = require('./math'); math.add(2, 5);
// sever.js // 引用核心模块时,不需要带路径 var http = require("http"), PORT = 8000; http.createServer(function(req, res){ res.end("Hello World"); }).listen(PORT); console.log("listenning to " + PORT);
下面的例子可以体现[同步/阻塞式加载]的特性
// timeout.js var EXE_TIME = 2; (function(second){ var start = +new Date(); while(start + second*1000 > new Date()){} })(EXE_TIME) console.log("2000ms executed")
// main.js require('./timeout'); // sync load console.log('done!');
如果commonjs require方法是异步的话,下面这么写就会报错
//CommonJS Syntax var Employee = require("types/Employee"); function Programmer (){ //do something } Programmer.prototype = new Employee(); //如果 require call 是异步的,那么肯定 error //因为在执行这句前 Employee 模块根本来不及加载进来
从下图可以看出,同步加载对服务器/本地环境并不是问题。-> 浏览器环境会有问题!!
CommonJS是同步加载的,因此更适合服务器端。只有加载完成之后才能进行下面的操作。因为在服务器端模块文件一般存放在本地,再加上有缓存,加载速度十分快。 因此这种就不适合用在浏览器端,浏览器端的各个 script 标签中的文件来自各个服务器,如果上个模块加载的时间很长,就会导致浏览器“假死”,因此浏览器端我们采用另外一种异步的加载方式AMD。
关键命令:define()、require()
define()
AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,才会运行这个回调函数。这里介绍用require.js实现AMD规范的模块化:用require.config()指定引用路径等,用define()定义模块,用require()加载模块。
require.config()
//AMD Wrapper define( ["types/Employee"], //依赖 function(Employee){ //这个回调会在所有依赖都被加载后才执行 function Programmer(){ //do something }; Programmer.prototype = new Employee(); return Programmer; //return Constructor } )
Require.js使用例子:
/** 网页中引入require.js及main.js **/ <script src="js/require.js" data-main="js/main"></script> /** main.js 入口文件/主模块 **/ // 首先用config()指定各模块路径和引用名 require.config({ baseUrl: "js/lib", paths: { "jquery": "jquery.min", //实际路径为js/lib/jquery.min.js "underscore": "underscore.min", } }); // 定义方式一:定义math.js模块 define(function () { var basicNum = 0; var add = function (x, y) { return x + y; }; return { add: add, basicNum :basicNum }; }); // 定义方式二:定义一个依赖underscore.js的模块 define(['underscore'],function(_){ var classify = function(list){ _.countBy(list,function(num){ return num > 30 ? 'old' : 'young'; }) }; return { classify :classify }; }) // 引用模块,将模块放在[]内 require(['jquery', 'math'],function($, math){ var sum = math.add(10,20); $("#sum").html(sum); });
引用模块的时候,我们将模块名放在[]中作为reqiure()的第一参数; 如果我们定义的模块本身也依赖其他模块,那就需要将它们放在[]中作为define()的第一参数。
[]
reqiure()
require([ 'React', // 尽量使用 ModuleID 'IScroll', 'FastClick' 'navBar', // 和同目录下的 js 文件 'tabBar', ], function( React, // Export IScroll FastClick NavBar, TabBar, ){});
config
require.config({ // 查找根路径,当加载包含协议或以/开头、.js结尾的文件时不启用 baseUrl: "./js", // 配置 ModuleID 与 路径 的映射 paths: { React: "lib/react-with-addons", FastClick: "http://cdn.bootcss.com/fastclick/1.0.3/fastclick.min", IScroll: "lib/iscroll", }, // 为那些“全局变量注入”型脚本做依赖和导出配置 shim: { 'IScroll': { exports: "IScroll" }, }, // 从 CommonJS 包中加载模块 packages: [ { name: "ReactChart", location: "lib/react-chart", main: "index" } ] })
优化打包
node r.js -o build.js
// build.js // 简单的说,要把所有配置 repeat 一遍 ({ appDir: './src', baseUrl: './js', dir: './dist', modules: [ { name: 'app' } ], fileExclusionRegExp: /^(r|build)\.js$/, optimizeCss: 'standard', removeCombined: true, paths: { React : "lib/react-with-addons", FastClick: "http://cdn.bootcss.com/fastclick/1.0.3/fastclick.min", IScroll: "lib/iscroll" }, shim: { 'IScroll': { exports: "IScroll" }, }, packages: [ { name: "ReactChart", location: "lib/react-chart", main: "index" } ] })
CMD与AMD很类似,不同点在于:AMD 推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行。
/** AMD写法 **/ define(["a", "b", "c"], function(a, b, c) { // 等于在最前面声明并初始化了要用到的所有模块 a.doSomething(); if (false) { // 即便没用到某个模块 b,但 b 还是提前执行了 b.doSomething() } }); /** CMD写法 **/ define(function(require, exports, module) { var a = require('./a'); //在需要时申明 a.doSomething(); if (false) { var b = require('./b'); b.doSomething(); } });
sea.js的小例子🌰:
/** sea.js **/ // 定义模块 math.js define(function(require, exports, module) { var $ = require('jquery.js'); var add = function(a,b){ return a+b; } exports.add = add; }); // 加载模块 seajs.use(['math.js'], function(math){ var sum = math.add(1+2); });
关键命令:export、export detault、import
export
export detault
import
ES6 在语言标准的层面上,实现了模块功能,浏览器和服务器通用的模块解决方案。
export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
/** 定义模块 math.js **/ var basicNum = 0; var add = function (a, b) { return a + b; }; export { basicNum, add }; /** 引用模块 **/ import { basicNum, add } from './math'; function test(ele) { ele.textContent = add(99 + basicNum); }
ES6的模块不是对象,import命令会被 JavaScript 引擎静态分析,在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。也正因为这个,使得静态分析成为可能。
备注: 以上只是一个总结,详细的可看下面参考资料
前端模块化:CommonJS,AMD,CMD,ES6
JavaScript 模块化七日谈 推荐👍
前端模块化开发那点历史
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前端模块化
模块化开发可以提高代码复用率,方便代码管理。一般来说一个文件就是一个模块,得外暴露变量或者函数。目前比较流行的模块化的规范有:AMD、CMD和CommonJs以及ES6 的 module。
CommonJS
commonjs主要由node推广使用。
关键命令:
module.exports =
、require()
例子:
下面的例子可以体现[同步/阻塞式加载]的特性
如果commonjs require方法是异步的话,下面这么写就会报错
从下图可以看出,同步加载对服务器/本地环境并不是问题。-> 浏览器环境会有问题!!
CommonJS是同步加载的,因此更适合服务器端。只有加载完成之后才能进行下面的操作。因为在服务器端模块文件一般存放在本地,再加上有缓存,加载速度十分快。
因此这种就不适合用在浏览器端,浏览器端的各个 script 标签中的文件来自各个服务器,如果上个模块加载的时间很长,就会导致浏览器“假死”,因此浏览器端我们采用另外一种异步的加载方式AMD。
AMD(require.js)
关键命令:
define()
、require()
AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,才会运行这个回调函数。这里介绍用require.js实现AMD规范的模块化:用
require.config()
指定引用路径等,用define()
定义模块,用require()
加载模块。Require.js使用例子:
引用模块的时候,我们将模块名放在
[]
中作为reqiure()
的第一参数;如果我们定义的模块本身也依赖其他模块,那就需要将它们放在
[]
中作为define()
的第一参数。requirejs最佳实践
config
优化打包
node r.js -o build.js
CMD(sea.js)
CMD与AMD很类似,不同点在于:AMD 推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行。
sea.js的小例子🌰:
es6 module
关键命令:
export
、export detault
、import
ES6 在语言标准的层面上,实现了模块功能,浏览器和服务器通用的模块解决方案。
export
命令用于规定模块的对外接口,import
命令用于输入其他模块提供的功能。ES6的模块不是对象,
import
命令会被 JavaScript 引擎静态分析,在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。也正因为这个,使得静态分析成为可能。备注: 以上只是一个总结,详细的可看下面参考资料
参考
前端模块化:CommonJS,AMD,CMD,ES6
JavaScript 模块化七日谈 推荐👍
前端模块化开发那点历史
The text was updated successfully, but these errors were encountered: