前端模块化系统的几种方式

  1. <script>-tag的形式,主要问题有:

    • 全局的变量冲突
    • 按序加载的重要性
    • 解决不同模块、包之间的依赖性
    • 项目庞大的时候,需要写很多很多<script>标签
  2. CommonJS: 同步请求(synchronous):

    这种方式使用同步的require方法去加载依赖模块并返回依赖模块所暴露出的接口,一个模块可以
    通过增加属性到export的对象中或者设置module.exports的值来明确的指定暴露的接口。
    优点:

    1. 服务端模块可以使用
    2. npm上已经有好多使用这种方式的写法
    3. 使用简单
      缺点:
    4. 阻塞式的请求不适用于网络请求,网络请求是异步的
    5. 不能并发的请求多个模块
      实现者:
    • node.js- server-side
    • browserify
    • modules-webmake - compile to one bundle
    • wreq - client-side
      1
      2
      3
      require("../file.js");
      exports.doStuff = function() {};//方式一
      module.exports = someValue;//方式二

3.AMD: 异步(asynchronous)请求

对于浏览器来说同步请求有很多问题(CommonJS)所以引入了一个异步版本(一种定义模块与导出模块的方式)

1
2
3
4
require(["module", "../file"], function(module, file) { /* ... */ });
define("mymodule", ["dep1", "dep2"], function(d1, d2) {
return someExportedValue;
});

优点:

  1. 适用于异步的网络请求
  2. 并发加载模块
    缺点:
  3. 代码不易于维护
    实现者:
  • require.js - client-side
  • curl - client-side

4.ES6 Modules

ES6给javascript增加了一些语言特性,实现了另外的模块化系统
优点:

  1. 易于静态分析
  2. 未来的ES标准
    缺点:
  3. 浏览器原生支持需要时间
  4. 目前这种风格还很少
    1
    2
    3
    import "jquery";
    export function doStuff() {}
    module "localModule" {}

模块加载

模块可以执行在浏览器端,所以它必须从服务端加载到浏览器中去,有两种极端的加载方式:

  1. 一个模块一个请求
    优点:
  • 只有需要的才会被加载
    缺点:
  • 过多的模块会造成网络负载,程序响应过慢
  1. 所有的模块一个请求
    优点:
  • 只有一个请求
    缺点:
  • 不需要的模块也加载了

分块加载

编译模块时,将模块拆分成多个小块,拆分点由开发者定义
同样适用于img css webfont html模板等等