当前位置: 首页 > 科技观察

No.js为大家带来的一个模块加载器实现

时间:2023-03-17 11:43:05 科技观察

前言:最近在No.js中实现了一个简单的模块加载器。本文简单介绍一下loader的实现。因为JS本身没有模块加载的概念,所以随着前端的发展,各种加载技术也随之发展起来。早期的seajs,requirejs,现在的webpack,Node.js等等,moduleloader的后台都是代码的模块化,因为我们不可能把所有的代码都写到同一个文件里,所以moduleloader主要解决了模块中加载其他模块的问题,不仅是前端语言,还有c语言、python、php。No.js指的是Node.js的实现。例如,我们有以下两个模块。module1.jsconstfunc=require("module2");func();module2.jsmodule.exports=()=>{//somecode}下面看看如何实现模块加载功能。首先看第一个模块在运行时是如何加载的。No.js在初始化的时候会通过V8执行No.js文件。const{loader,process,}=No;functionloaderNativeModule(){//原生JS模块列表constmodules=[{module:'libs/module/index.js',name:'module'},];No.libs={};//初始化for(leti=0;i());intfd=open(*filename,0,O_RDONLY);std::stringcontent;charbuffer[4096];while(1){memset(buffer,0,4096);intret=read(fd,buffer,4096);if(ret==-1){returnargs.GetReturnValue().Set(newStringToLcal(isolate,"readfileerror"));}if(ret==0){break;}content.append(buffer,ret);}close(fd);ScriptCompiler::Sourcescript_source(newStringToLcal(isolate,content.c_str()));本地params[]={newStringToLcal(isolate,"require"),newStringToLcal(isolate,"exports"),newStringToLcal(isolate,"module"),};MaybeLocalfun=ScriptCompiler::CompileFunctionInContext(上下文,&script_source,3,params,0,nullptr);if(fun.IsEmpty()){args.GetReturnValue().Set(Undefined(isolate));}else{args.GetReturnValue().Set(fun.ToLocalChecked());}}Compile首先读取模块的内容,然后调用CompileFunctionInContext函数。CompileFunctionInContext函数的原理如下。假设文件内容为1+1,执行完如下代码constret=CompileFunctionInContext("1+1",["require","exports","module"])ret变为function(require,exports,module){1+1;}所以CompileFunctionInContext的作用是将代码封装成一个函数,可以设置函数的形参列表。回到原生JS的加载过程。for(leti=0;i