演变过程
-
通过script标签引入文件<无模块化>
缺点:容易造成代码污染,命名冲突等问题
-
服务端的node中引入了CommonJS的模块化规范
特点:被加载的时候运行,输出的是值的浅拷贝,具有缓存,下载加载时从内存中读取
其导入采用同步加载方式,而文件存于服务器中,因此适用于服务端使用。而浏览器端需要从服务端请求,因此不浏览器端请求不适用这种方式
通过module.exports对外暴露接口,使用require('文件路径')引入模块
前端webpack打包时对CommonJS是支持的
-
异步加载AMD规范
特点:需要加载全部依赖之后再执行,适用于浏览器端的异步加载规范
定义了两个API:
导入:require([module],callback) ; 定义模块:define(id,[depends],callback)
AMD规范的实现是require.js
-
按需加载CMD规范
特点:使用rquire,进行按需加载,CMD规范的实现sea.js
define(function(require, exports, module) {
var $ = require('文件路径');
exports.doSomething = ...
module.exports = ...
})
//AMD和CMD的比较
// AMD
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
});
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b')
// 依赖可以就近书写
b.doSomething()
// ...
});
复制代码
-
ES6模块化
特点:异步加载,加载的为值的引用,重复导入文件不会存在覆盖,编译时运行
静态导入模块:import mydefault, * as mydefault, {foo,bar} from '模块路径' 返回函数或对象
动态导入模块:import(路径)返回promise
//导入js文件
import('/modules/myModules.js')
.then(module=>{
//操作
})
//导入vue文件
myComponent = ()=>import('/modules/myModules.vue')
//都可以使用require来实现同样的操作,但属于同步加载,需要提前加载完成后运行
require('/modules/myModules.js').default
require('/modules/myModules.vue').default
复制代码
工程自动化:require.context
是webpack的api,主要用来实现自动读取模块,实现工程自动化
require.context(directory,useSubdirectories,regExp)
参数如下
- directory:String类型,扫描的文件夹的根路径
- useSubdirectories: Boolean类型,是否变量文件的子目录
- regExp:RegExp正则对象,匹配文件的正则
返回值是个函数,函数的属性如下
- resolve:Function类型,接收一个参数为文件相对路径;返回模块
- keys: Function类型,返回匹配成功的模块名称的数组
- id:String类型,应用于module.hot.accept
使用示例
读取correspondingFields文件夹下,所有子文件夹下,存在modules下的所有js文件,如图:
代码读取如下:
// 导出所有js
const modulesFiles = require.context('./', true, /.*\/modules\/\w+\.js$/)
// console.log('modulesFiles', modulesFiles.keys())
// 导出table列
const tableColumnsModuleFiles = require.context('./', true, /.*\/tableColumns\/modules\/\w+\.js$/)
// console.log('modulesFiles', modulesFiles.keys())
// 导出table列
const detailModuleFiles = require.context('./', true, /.*\/detail\/modules\/\w+\.js$/)
// console.log('modulesFiles', modulesFiles.keys())
/**
* 文件夹下的模块
* @param {*} ModuleFiles :读取的上下文
* 返回值是对象
* 例:{
* detail:{
* contract:模块
* },
* tableColumns:{
* contract:模块
* }
* }
*/
function getModules(ModuleFiles) {
const modules = ModuleFiles.keys().reduce((modules, modulePath) => {
// console.log('modulePath', modulePath)
const suffix = '\\.js$'
const regExp = new RegExp(`^.*\\/(\\w+)\\/modules\\/(\\w+)${suffix}`)
const result = regExp.exec(modulePath)// 匹配结果
if (result.length >= 3) {
const type = result[1]
const moduleName = result[2]
modules[type] ? Object.assign(modules[type], { [moduleName]: ModuleFiles(modulePath).default }) : modules[type] = { [moduleName]: ModuleFiles(modulePath).default }
}
return modules
}, {})
return modules
}
export const DetailModules = getModules(detailModuleFiles)
export const TableColumnsModules = getModules(tableColumnsModuleFiles)
export default getModules(modulesFiles)
复制代码