前端模块化总结

1:CommonJs

CommonJs 是一种 JavaScript 语言的模块化规范,它通常会在服务端的 Nodejs 上使用。CommonJS规范规定,每个模块内部,module 变量代表当前模块。这个变量是一个对象,它的 exports 属性(module.exports)是对外的接口。加载某个模块,其实是加载该模块的 module.exports 属性。require 方法用于加载模块。

CommonJS主要用于服务端的模块化,不适用于前端模块化:
服务端加载一个模块,直接就从硬盘或者内存中读取了,消耗时间可以忽略不计
浏览器需要从服务端下载这个文件,所以说如果用CommonJS的require方式加载模块,需要等代码模块下载完毕,并运行之后才能得到所需要的API。
如果我们在某个代码模块里使用CommonJS的方法require了一个模块,而这个模块需要通过http请求从服务器去取,如果网速很慢,而CommonJS又是同步的,所以将阻塞后面代码的执行,从而阻塞浏览器渲染页面,使得页面出现假死状态。

浏览器中使用步骤

  1. 创建项目结构目录:
    在这里插入图片描述

  2. 下载browserify
    全局: npm install browserify -g
    局部: npm install browserify --save-dev

  3. 定义模块代码(同服务器端)
    注意:index.html文件要运行在浏览器上,需要借助browserify将app.js文件打包编译,如果直接在index.html引入app.js就会报错!

  4. 打包处理js
    根目录下运行browserify js/src/app.js -o js/dist/bundle.js

  5. 页面使用引入
    在index.html文件中引入

<script type="text/javascript" src="js/dist/bundle.js"></script>

2:AMD

异步模块定义,所谓异步是指模块和模块的依赖可以被异步加载,他们的加载不会影响它后面语句的运行。有效避免了采用同步加载方式中导致的页面假死现象。AMD代表:RequireJS。
AMD一开始是CommonJS规范中的一个草案,全称是Asynchronous Module Definition,即异步模块加载机制。后来由该草案的作者以RequireJS实现了AMD规范,所以一般说AMD也是指RequireJS。

RequireJS是一个工具库,主要用于客户端的模块管理。它的模块管理遵守AMD规范,RequireJS的基本思想是,通过define方法,将代码定义为模块;通过require方法,实现代码的模块加载。

它主要有两个接口:define 和 require。define 是模块开发者关注的方法,而 require 则是模块使用者关注的方法。

AMD的优缺点
AMD 运行时核心思想是「Early Executing」,也就是提前执行依赖 AMD 的这个特性有好有坏:

首先,尽早执行依赖可以尽早发现错误。

另外,尽早执行依赖通常可以带来更好的用户体验,也容易产生浪费。

引用AMD的JavaScript库: 目前,主要有两个JavaScript库实现了AMD规范:require.js和curl.js

在浏览器环境中异步加载模块;并行加载多个模块;

开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅;不符合通用的模块化思维方式,是一种妥协的实现。

AMD在浏览器端的实现步骤

1:下载require.js, 并引入

官网: http://www.requirejs.cn/
github : https://github.com/requirejs/requirejs
然后将require.js导入项目: js/libs/require.js

2:创建文件目录
在这里插入图片描述
3. 定义require.js的模块

//定义没有依赖的模块 dataService.js
define(function(){
  let name = 'dataService'
  function getName(){
    return name
  }
  //暴露
  return{getName}
})

//定义有依赖的模块 alerter.js
define(['dataService','jquery'],function(dataService,$) {
  let msg = 'alerter'
  function showMessage(){
    console.log(msg,dataService.getName())
    $('body').css('backgroundColor', '#ccc')
  }
  //暴露模块
  return {showMessage}
})

//main.js
(function(){
    requirejs.config({
      baseUrl: 'js/',
      paths: {
        dataService:'./modules/dataService',
        alerter:'./modules/alerter',
        //第三方库
        jquery:'./libs/jquery'
      }
    });
    requirejs(['alerter'],function(alerter){
      alerter.showMessage()
    })
  }
)()

//test.html
 <!-- 引入require.js并指定js主文件的入口 -->
<script data-main="js/main.js" src="js/libs/require.js"></script>

3:CMD

CMD是SeaJS在推广过程中生产的对模块定义的规范,在Web浏览器端的模块加载器中,SeaJS与RequireJS并称,SeaJS作者为阿里的玉伯。

CMD规范专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。CMD规范整合了CommonJS和AMD规范的特点。在 Sea.js 中,所有 JavaScript 模块都遵循 CMD模块定义规范。

CMD语法

//定义没有依赖的模块
define(function(require, exports, module){
  exports.xxx = value
  module.exports = value
})

//定义有依赖的模块
define(function(require, exports, module){
  //引入依赖模块(同步)
  var module2 = require('./module2')
  //引入依赖模块(异步)
    require.async('./module3', function (m3) {
    })
  //暴露模块
  exports.xxx = value
})

引入模块

define(function (require) {
  var m1 = require('./module1')
  var m4 = require('./module4')
  m1.show()
  m4.show()
})

CMD的优缺点
优点:依赖就近,延迟执行 可以很容易在 Node.js 中运行;
缺点:依赖 SPM 打包,模块的加载逻辑偏重;

sea.js使用步骤
1. 下载sea.js, 并引入
官网: seajs.org/
github : github.com/seajs/seajs
然后将sea.js导入项目: js/libs/sea.js
2:创建结构目录

|-js
  |-libs
    |-sea.js
  |-modules
    |-module1.js
    |-module2.js
    |-module3.js
    |-module4.js
    |-main.js
|-index.html

3. 定义sea.js的模块代码

// module1.js文件
define(function (require, exports, module) {
  //内部变量数据
  var data = 'atguigu.com'
  //内部函数
  function show() {
    console.log('module1 show() ' + data)
  }
  //向外暴露
  exports.show = show
});

// module2.js文件
define(function (require, exports, module) {
  module.exports = {
    msg: 'I Will Back'
  }
});

// module3.js文件
define(function(require, exports, module) {
  const API_KEY = 'abc123'
  exports.API_KEY = API_KEY
});

// module4.js文件
define(function (require, exports, module) {
  //引入依赖模块(同步)
  var module2 = require('./module2')
  function show() {
    console.log('module4 show() ' + module2.msg)
  }
  exports.show = show
  //引入依赖模块(异步)
  require.async('./module3', function (m3) {
    console.log('异步引入依赖模块3  ' + m3.API_KEY)
  })
});

// main.js文件
define(function (require) {
  var m1 = require('./module1')
  var m4 = require('./module4')
  m1.show()
  m4.show()
})

4. 在index.html中引入

<script type="text/javascript" src="js/libs/sea.js"></script>
<script type="text/javascript">
  seajs.use('./js/modules/main')
</script>

4:ES6模块化(重点介绍)

ES6模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。所以说ES6是编译时加载,不同于CommonJS的运行时加载(实际加载的是一整个对象),ES6模块不是对象,而是通过export命令显式指定输出的代码,输入时也采用静态命令的形式。

ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。

语法
模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

export
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。下面是一个 JS 文件,里面使用export命令输出变量。
import
使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。

ES6 模块与 CommonJS 模块的差异
它们有两个重大差异:
1. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。

2. CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

ES6模块化使用步骤
1:创建文件目录
在这里插入图片描述
2:安装babel(将ES6语法转换为ES5)
官网:https://www.babeljs.cn/
npm install --save-dev @babel/core @babel/cli @babel/preset-env
3:安装browserify
全局: npm install browserify -g
局部: npm install browserify --save-dev
4:添加模块语法

//module1.js 分别暴露
export function foo(){
  console.log('foo module1');
}
export function bar(){
  console.log('bar module1');
}

//module2.js 统一暴露
function foo(){
  console.log('fun module2');
}
function fun2(){
  console.log('fun2 module2');
}
export {
  foo, fun2
}

//module3.js 默认暴露
let price = 19
function foo(){
  console.log('foo module3');
}
export default {
  price,foo
}

//main.js
//引入
//分别暴露和统一暴露要使用解构赋值的引用方式
import {foo,bar} from './module1'  
import {foo as foo2,fun2} from './module2'
import module3 from './module3' //只针对默认暴露的引入方式
//第三方模块使用
import $ from 'jquery'

foo() //foo module1
bar() //bar module1
foo2() //fun module2
fun2() //fun2 module2
module3.foo() //foo module3
console.log(module3.price); //19
$('body').css('backgroundColor', 'pink')

5:使用babel命令进行语法转化

npx babel js/src --out-dir js/lib

6:使用browserify命令进行打包
browserify js/lib/main.js -o js/lib/bundle.js

7:index.html中引入

<script src="./js/lib/bundle.js"></script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值