关于javascript:JavaScript模块化

30次阅读

共计 3180 个字符,预计需要花费 8 分钟才能阅读完成。

1 概述

1.1 前端为什么须要模块化

  • 解决命名抵触
  • 提供代码复用性和可维护性
  • 灵便架构,焦点拆散,不便模块间组合、合成
  • 多人合作互不烦扰

1.2 js 模块化倒退历程

1.2.1 script 标签

随着前端复杂度进步,为什么可能进步我的项目代码的复用性和可维护性等,就将一个性能封装成一个文件,把一个 js 文件当成一个模块,这样 js 文件也就多了起来。js 引入形式大略是上面这样:

<script src="jquery.js"></script>
<script src="jquery_scroller.js"></script>
<script src="main.js"></script>
<script src="other1.js"></script>
<script src="other2.js"></script>
<script src="other3.js"></script>

简略的将 js 文件放在一起,然而彼此的援用程序不能出错。比方必须先引入 jquery,能力应用 jquery_scroller,不然就会报错

长处:

绝对于所有逻辑都在同一个 js 文件,模块化思维是提高的。

毛病:

净化全局作用域。因为每一个都是裸露在全局的,会导致全局变量命名抵触,可通过命名空间解决
依赖关系不显著,不利于保护。比方 main.js 须要应用 jquery,然而,从下面的文件中,咱们是看不出来的,如果 jquery 遗记了,那么就会报错。

1.2.2 CommonJS 标准

CommonJS 标准是一个对 js 模块化的标准,最后用在服务端 node 上。webpack 是反对 CommonJS 标准的。

依据标准,每一个文件都是模块,其外部定义的变量属于这个模块,不会对外裸露,即不会净化全局变量。中心思想是通过 require 办法同步加载所依赖的模块,而后通过 exports 或者 module.exports 来导出须要裸露的接口。如下所示:

// a.js
var x = 5;
var addX = function (value) {return value + x;};
module.exports.x = x;
module.exports.addX = addX;

//b.js
var a = require('./a.js');
console.log(example.x); // 5
console.log(example.addX(1)); // 6

这里的 a.js 就是 CommonJS 标准的模块了。module 代表这个模块,exports 属性就是对外裸露的接口,能够对外导出可拜访的变量和办法,比方 x 和 addX

exports 是对 module.exports 的援用,所以咱们能够认为模块顶部有 exports = module.exports 这样一个定义,所以咱们不能间接给 exports 赋值

这样咱们在 b.js 中就能获取到 a.js 裸露的变量和办法

长处:

解决了依赖和全局变量净化的问题

毛病:

因为 CommonJS 是同步加载的,服务器端没有问题,然而在浏览器端须要将文件从服务器端申请过去,只有加载实现能力执行前面的操作,会阻塞渲染,所以不实用在浏览器端

1.2.3 AMD 标准

AMD 标准是非同步加载模块,容许指定回调函数。AMD 标准的实现就是 require.js
AMD 规范中定义了上面两个 api

   - require([module], callback)
   - define(id, [depends], callback)

即通过 define 定义一个模块,而后应用 require 来加载一个模块,并且 require 还反对 CommonJS 的导出形式

定义 alert 模块:

define(function () {var alertName = function (str) {alert("I am" + str);
    }
    var alertAge = function (num) {alert("I am" + num + "years old");
    }
    return {
      alertName: alertName,
      alertAge: alertAge
    };
  });

引入模块:

require(['alert'], function (alert) {alert.alertName('zhansan');
  alert.alertAge(18);
});
长处:

反对浏览器环境异步加载模块,能够并行加载多个模块

毛病:

进步了开发成本,并且不能按需加载,必须提前加载所有的依赖

1.2.4 CMD 标准

CMD 和 AMD 相似,即一个 js 文件就是一个模块,然而 CMD 是按需加载,不是在模块开始加载所有的依赖,如下所示:

define(function(require, exports, module) {var $ = require('jquery');
  var Spinning = require('./spinning');
  exports.doSomething = ...
  module.exports = ...
})

长处:

实现了浏览器端的模块话加载
按需加载,依赖就近

毛病:

依赖 SPM 打包,模块的加载逻辑并重。

这时咱们就能够看出 AMD 和 CMD 的区别了,前者是对于依赖的模块提前执行,而后者是提早执行。前者推崇依赖前置,而后者推崇依赖就近,即只在须要用到某个模块的时候再 require。如下:

// AMD
define(['./a', './b'], function(a, b) {  // 依赖必须一开始就引入  
   a.doSomething()      
   b.doSomething()    
   //...
});

// CMD
define(function(require, exports, module) {var a = require('./a')   
   a.doSomething()   
   var b = require('./b') 
   // 依赖能够就近引入
   b.doSomething()
   // ... 
});

1.2.5 ES6 模块化

ES6 模块化计划是真正的标准,下面的几种计划只是前段社区本人实现的。在 ES6 中,通过 import 关键字引入模块,export 关键字导出模块。ES6 模块化和 CommonJs 的一个区别就是前者导入导出都是援用,而后者导入的是值的拷贝。

/**
 * 首字母大写
 * @param str
 */
export const capitalize = (str: string) => {
  str = str || '';
  if (str.length > 0) {const first = str.substr(0, 1).toUpperCase();
    const spare = str.substr(1, str.length);
    return first + spare;
  }
};

2. 打包工具

2.1 Webpack

webpack 能够看做是模块打包机:它做的事件是,剖析你的我的项目构造,找到 JavaScript 模块以及其它的一些浏览器不能间接运行的拓展语言(Scss,TypeScript 等),并将其转换和打包为适合的格局供浏览器应用。

长处:

所有皆模块,能够模块化任何资源
反对各种模块化语法
开发便捷
扩展性强,插件机制欠缺

毛病:

配置简单,文档滞后
通过 babel 编译之后的 js 代码打包后体积过大

2.2 Parcel

超快的打包速度,多线程在多核上并发编译,不必任何配置。

长处:

能做到无配置实现以上我的项目构建要求;
内置了常见场景的构建计划及其依赖,无需再装置各种依赖;
能以 HTML 为入口,自动检测和打包依赖资源;
默认反对模块热替换,真正的开箱即用;

毛病:

不反对 SourceMap
不反对剔除有效代码 (TreeShaking)
一些依赖会 让 Parcel 出错:当你的我的项目依赖了一些 Npm 上的模块时,有些 Npm 模块会让 Parcel 运行谬误;
不灵便的配置,无奈自定义

如图:

参考如下:
https://zhuanlan.zhihu.com/p/…
https://blog.csdn.net/github_…
https://segmentfault.com/a/11…

正文完
 0