浅谈js模块化:commons、AMD、CMD、ES6几种模块化的用法及各自的特点

js模块化是现在比较流行的一种用法,它能避免很多以前js的弊端,是前端工程化的所要涉及到的话题,今天我们来谈谈几种模块化的方法。

一个页面需要引入多个js文件引发的问题:

  1. 请求过多
  2. 依赖模糊
  3. 难以维护
    这些问题可以通过现代模块化编码和项目构建来解决

模块化的好处:

  • 避免命名冲突(减少命名空间污染)
  • 更好的分类,按需加载
  • 更高的复用性
  • 高可维护性

几种常用的模块化规范

1、 commonJs

commonjs特点: 每个文件都可当作一个模块;在服务器端: 模块的加载是运行时同步加载的;在浏览器: 模块需要提前编译打包处理
暴露模块module.exports = values export.xxx = value
引入 require(xxx)第三方模块

  • 一个简单的在服务端运行的例子:
    首先你的电脑里面要保证已经安装过nodejs,因为我要用到这环境。
    建立一个文件commons,然后在commonjs里面建一个app.js,建立一个modules文件夹,里面分别建三个js文件module1.js,module2.js,module3.js.
    执行下列命令
npm init //在根部生成一个package.json文件

在这里插入图片描述
module1.js

module.exports = {
  msg: 'module1',
  fn () {
    console.log(this.msg)
  }
}

module2.js

//module.exports 一个文件只能出现一次,要不容易被下面的覆盖
module.exports = function () {
  console.log('module2')
}

module3.js

exports.fn = function() {
  console.log('fn() module3')
}
exports.bar = function () {
  console.log('bar() module3')
}

app.js

let module1 = require('./modules/module1')
let module2 = require('./modules/module2')
let module3 = require('./modules/module3')

module1.fn()
module2();
module3.fn()
module3.bar()

用node运行app.js,效果如下图
在这里插入图片描述

  • commjs基于浏览器端的应用
    如果没有工具的编译解析,浏览器是无法识别commjs里面的require的,比如我们建立一个commonjs文件夹,里面内容如下图,dist文件是个建立的空文件,用来打包编译内容放在这里,app.js,module1.js,module2.js, module3.js都还跟上一个例子内容一样,复制过来就可以了。
    在这里插入图片描述
    index.html文件引入app.js
    在浏览器中打开index.html并没有想象的预览效果,报错如下图
    在这里插入图片描述
    我们需要借助于browserify工具,用命令行安装browserify
npm install browserify -g
npm install browserify -save-dev

然后打包执行

browserify src/app.js -o dist/build.js

index.html引入文件换成打包后的build.js文件,这样再运行,在浏览器就能正常运行了。
在这里插入图片描述

2、 AMD

异步模块定义,专门用于浏览器端模块的加载是异步
定义
AMD自定义规范举例,利用requirejs写一个简单的demo来说明。
首先建立一个requirejs文件,在子级建立一个js文件和index.html,js里面建立一个modules文件和main.js文件
modules文件里面分别是dataService.js 和alerter.js
dataService.js

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

alerter.js

//定义有依赖的模块
define([
  'dataService'
], function(dataService) {
  let msg = 'alert.js';
  function showMsg() {
    console.log(msg, dataService.getName())
  }
  return {showMsg}
});

main.js

(function() {
// requirejs配置文件配置
  requirejs.config({
    baseUrl: 'js/', //基本的路径,从根目录开始
    paths: {
      dataService: './modules/dataService',
      alerter: './modules/alerter'
    }
  })
//
  requirejs(['alerter'], function(alerter){
    alerter.showMsg()
  })
})()

index.html

<!DOCTYPE html>
<head>
  <meta charset="UTF-8"/>
  <title>测试</title>
</head>
<body>
  <script data-main="js/main.js" src="https://cdn.bootcss.com/require.js/2.1.18/require.js"></script>
</body>
</html>

3、 ES6

ES6模块化是目前比较流行的一种方式,也是以后发展的一种趋势。依赖模块需要编译打包处理,引入模块用import,导出模块的方法是export。
在这里插入图片描述
举例子来说明es6的导入和导出
首先建立一个文件夹es6test,初始化package.json文件,用npm init
安装所需要的插件


qiuqiu$ npm install babel-cli browserify -g
npm install babel-preset-es2015 --save-dev
//preset预设(将es6转换成es5的所有插件打包)

定义一个.babelrc文件,(rc其实是run control)

{
  "presets": ["es2015"]
}

在es6test中建立一个src文件和html.html文件
src下建立main.js,module1.js,module2.js
module.js

//暴露模块,分别暴露
export function foo () {
  console.log('foo() module1')
}
export function bar () {
  console.log('bar() module1')
}
export let arr = [1,2,3,4]

module2.js

function fun () {
  console.log('fun() module2')
}
function fun2 () {
  console.log('fun2() module2')
}
export {
  fun,
  fun2
}

main.js

// 引入其他模块
//语法: import xxx from 路径
import {foo, bar, arr} from './module1'
import {fun, fun2} from './module2'
console.log(foo())
console.log(bar())
console.log(arr)
console.log(fun())
console.log(fun2())

编译

  • 使用babel将es6编译为es5代码(但包含co m mmjs语法):
    babel src -d es6test/lib
    运行效果如下图:在这里插入图片描述
  • 使用Browserify编译js:
browserify es6test/lib/main.js -o dist/bundle.js 

最后在index.html中引入dist文件中的bundle.js运行可以看到效果。

4、CMD

CMD是SeaJS在推广过程中对模块定义的规范化产出,是一个同步模块定义,是SeaJS的一个标准,SeaJS是CMD概念的一个实现,SeaJS是支付宝团队提供的一个模块开发的js框架.

总结

今天主要通过自己视频学习分享了,js模块化的一些方法,上面的图有的借鉴于视频中的截图,如果想了解更多,请扫描二维码
在这里插入图片描述

发布了258 篇原创文章 · 获赞 177 · 访问量 45万+

猜你喜欢

转载自blog.csdn.net/yilanyoumeng3/article/details/104455185