前端模块分类

前端模块化概述

模块作为现代化编程的基础复用单元,在"搬砖"的日常工作中可以起到明显的加速作用。随着前端工程化的不断完善,模块将在前端扮演越来越重要的角色。
当前的模块系统大体分为iifecjsamdumdesmsystem

iife(Immediately Invoked Function Expression)

即立即执行函数,是最早的模块编写方式,格式如下

(function () { 
    var name = "Soda";
})();
// 无法从外部访问变量 name
name // 抛出错误:"Uncaught ReferenceError: name is not defined"

表达式中的变量无法从外部访问。如果模块需要向外暴露变量,则可通过返回值直接返回。

var result = (function() {
	var name = "Soda";
	return name;
})();
//通过外部的变量接收iife的返回值
result // "Soda"

这便是最简单的模块,通过iife将代码与全局"割裂",仅通过返回值来定制外部可访问的内容。在全局环境中用户可自定义模块的名称,避免了全局变量的污染。

cjs(CommonJS)

node.js所参照的模块化标准,CommonJS模块以文件为单位定义模块,其内部的变量、函数、类都是私有的,对其他文件不可见。在模块内部,module变量代表当前模块,module.exports代表对外的接口,exports表示对module.exports的引用,使用exports.<name>也可以实现向外暴露属性或方法的目的。通过全局的require()加载某个模块实际上是加载该模块的module.exports属性。

模块的导出:

function func1(name) {
	console.log(`Hello ${name}`);
}

function func2() {
	console.log('function 2');
}
// 使用exports.<functionName>向外导出方法
exports.func1 = func1;
// 使用module.exports向外导出方法
module.exports = { func2 }
// 注:当两种导出方法同时存在时 由于module.exports所指向的对象地址发生了改变,会导致 exports 导出的方法失效

模块的导入

const lib = require('./lib');
lib.func2();// function 2
// 当仅有exports存在时
lib.func1('world') // Hello world

CommonJS模块的特点如下:

优点:
所有代码都运行在模块作用域,不会污染全局作用域
模块可以多次加载,但只会在第一次加载时运行一次,运行的结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清楚缓存
模块加载的顺序,按照其在代码中出现的顺序。

缺点
在服务端由于所有代码都存放在本地磁盘,读取模块的时间几乎可以忽略。但浏览器端运行由于网络和模块大小的因素,可能会有加载时间过长的问题,可能会导致浏览器处于"假死"状态,因此CommonJS更适用于服务器端

amd(Asynchronous Module Definition)

异步模块定义

define(id?, dependencies?, function($) {
	return function() {}
})

AMD的模块引入由define方法定义,在define API中

id: 模块名称,或者模块加载器请求的指定脚本的名字
dependencies: 模块所依赖的模块组
function: 为模块初始化所要执行的函数或对象,如果为函数,它应该只被执行一次,如果是对象,此对象应该为模块的输出值

AMD模块的特点如下

优点
依赖异步加载,不会造成浏览器加载卡顿,适用于浏览器
缺点
编写复杂

umd(Universal Module Definition)

通用模块规范
其本质是cmjamd以及iife的综合体。使其可以在任何开发环境中都可以以最优方式运行。

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        //AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        //Node, CommonJS之类的
        module.exports = factory(require('jquery'));
    } else {
        //浏览器全局变量(root 即 window)
        root.returnExports = factory(root.jQuery);
    }
}(this, function ($) {
    //方法
    function myFunc(){};
    //暴露公共方法
    return myFunc;
}));

其流程如下

先判断是否支持 AMD(define 是否存在),存在则使用 AMD 方式加载模块;
再判断是否支持 Node.js 模块格式(exports 是否存在),存在则使用 Node.js 模块格式;
前两个都不存在,则将模块公开到全局(window 或 global);

esm(ECMA Script Modules)

iifecjsamdumd均为社区提供的模块化方案,历史上,JavaScript一直没有模块系统,直到ES6在语言标准的层面上实现了模块化标准。其设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
CommonjsAMD模块,都只能在运行时确定这些东西。
ECMA Script 模块是打包JavaScript代码的官方标准。使用importexport语句定义模块。配合现代化的打包工具,esm将会有更多有趣的特性

默认导出

import React from 'react';
export default class test extends React.Component {
	render() {
		return (<div>Hello</div>)
	}
}

导入

import Component from './lib';

参考文档

MDN术语表(iife)
Snandy Blog中关于UMD的描述
hijiangtao的githubpage

猜你喜欢

转载自blog.csdn.net/u010464354/article/details/104744404