当前位置: 首页 > 后端技术 > Node.js

nodejs模块化_0

时间:2023-04-03 13:59:39 Node.js

nodejs模块化一、模块化发展历程传统开发常见问题:命名冲突和污染代码冗余、无效请求多文件依赖模块复杂:代码片段小而精,易于维护通用模块化规范CommonJS规范node.js(同步加载)AMD规范require.js(异步加载,前置依赖)CMD规范sea.js(异步加载,附近依赖)ES6modularnative(编译时,异步加载)Commonjs和ESM是目前常用的规范,参考文档:https://www.cnblogs.com/echoy...2.CommonJS规范的三种基本实现(语言层面的规范):模块定义模块识别模块参考node.js和CommonJS:任何文件都是一个模块,有一个独立作用域使用require导入其他模块将模块ID传入require实现目标模块定位nodejs中CommonJS实现:模块属性任何js文件都是模块,可以直接使用模块属性id:返回模块标识,一般,是一个绝对路径filename:返回文件的绝对路径moduleloaded:返回布尔值,表示模块是否已经加载parent:返回一个对象,存放调用当前模块的模块children:返回一个数组,存放其他当前模块调用的模块exports:返回当前模块需要暴露的内容paths:返回一个数组,存放不同目录下node_modules的位置。module.exports和exports的区别是指向同一个内存地址。当exports被重新赋值时,exports相当于一个局部变量require属性的基本作用是读取并执行一个模块文件,返回模块文件的module.exports对象resolve:返回模块文件扩展名的绝对路径:根据不同的后缀进行解析操作main:返回主模块对象中CommonJS规范的代码nodejs实现://mainmodule//1.模块的导入导出constm=require('./m');console.log(m)//2.module//console.log('no_module',module);//3.exports//console.log(m)//4.同步加载//判断当前模块是否是主模块控制台。log(require.main===module)//require.main指向自身//externalmodule://1.导入和导出模块constage=18;constaddFn=(x,y)=>{returnx+y;}//module.exports={//age,//addFn//}//2.module//console.log('no_module',module);//3.exportsexports.name='jiang';//四、同步加载letname='lg';//letiIime=Date.now();//while(Date.now()-iIime<4000){}//同步加载,阻塞当前线程exports.nickName=name;console.log('m.jsexecuted')//判断当前模块是否为主模块console.log(require.main===module)//require.mainparent3.模块加载缓存优先级原则模块分类:内置模块:Node源代码在编译时写入二进制文件,使用时加载速度更快。文件模块:代码运行时是动态加载的,需要经过一个完整的加载过程。模块加载过程:路径分析:根据标识符(路径和非路径)确定模块位置(module.paths返回模块加载策略)文件位置:确定目标模块中的具体文件和文件类型(完成扩展名顺序为.js-->.json-->.node)编译执行:根据文件类型,使用相应的方法完成文件的编译执行(.js编译:封装成一个立即执行函数,并传入exports、module、require等参数执行;.json编译:使用JSON.parse解析),返回exports的可用对象4.VM模块创建独立运行的沙箱环境类似到沙盒实现:constfs=require('fs');constpath=require('路径');constvm=require('vm');letcontent=fs.readFileSync(path.join(__dirname,'test.txt'),'utf-8');//eval//eval(content);content中的变量需要用var来访问这里//newFunction//letfn=newFunction('age','returnage+1');//console.log(fn(19))letage=88;vm.runInThisContext(内容);console.log(年龄);五、文件加载模拟核心逻辑:路径解析、缓存优先级、文件位置、编译执行代码实现:constfs=require('fs');constpath=require('路径');constvm=require('vm');函数模块(id){this.id=id;this.exports={};}Module.prototype.load=function(filename){letextname=path.extname(this.id);Module._extensions[extname](this);console.log('111')}Module.wrapper=['(function(exports,require,module,__filename,__dirname){','})']Module._extensions={'.js'(module){//读取letcontent=fs.readFileSync(module.id,'utf-8');//包装到函数中content=Module.wrapper[0]+content+Module.wrapper[1];让compileFn=vm.runInThisContext(content);//准备参数值letexports=module.exports;让目录名=path.dirname(module.id);让文件名=module.id;//执行compileFn.call(exports,exports,myRequire,module,filename,dirname);},'.json'(module){letcontent=JSON.parse(fs.readFileSync(module.id,'utf-8'));module.exports=内容;},}Module._resolveFilename=function(filename){//1绝对路径letabsPath=path.resolve(__dirname,filename);//2判断文件是否存在if(!fs.existsSync(absPath)){//文件位置letsuffix=Object.keys(Module._extensions);for(leti=0;i