美文网首页
模块加载与运行原理

模块加载与运行原理

作者: 励志摆脱懒癌的少女酱 | 来源:发表于2018-07-14 14:54 被阅读5次


1.CommonJS规范

Node与浏览器以及W3C组织、CommonJS组织、ES之间的关系

(1)导出:exports和module.exports

    * exports:将要导出的对象作为其属性即可,只能导出实例化对象,若为特定的类型则会切断和module.exports的联系,因为exports是指向module.exports的一个引用

    * module.exportsrequire()返回的是module.exports导出的结果

若x是require该文件的结果变量,则x.a的结果是2

:exports -> {} <- module.exports,初始值是一个空对象;

(2)导入:require()

* 优先级:缓存加载(node缓存的是编译和执行后的对象,浏览器缓存的是文件) —》核心模块加载—》文件模块加载;

* 导入步骤:路径分析—》文件定位—》编译执行

2.Node运行原理

(1)当输入node xx.js执行.js文件时干了什么?

* 调用node项目的src/node_main.cc入口文件:区分运行环境是windows环境和*nix环境,调用node::start()方法进入src/node.cc文件中;

以UNIX环境为例的main()函数

* 进入src/node.cc文件中:Start() —》StartNodeInstance() —》LoadEnvironment():将bootstrap_node.js文件封装在一个function中,通过f->call()进入bootstrap_node.js文件实现xx.js的加载、编译和执行;

引入并调用bootStrap_node.js文件 process.arg[1]取出文件名xx.js->path.resolve()解析文件路径->run(Module.runMain)编译执行xx.js

综上:node xx.js启动一个文件就是require(xx.js)

3.模块加载原理

(1)模块实例:文本模块核心模块的模块实例区别:

文本模块实例的构造函数 js核心模块实例的构造函数

(1)require()源码在lib/module.js中:

Module的原型链上,每个模块实例都有一个require()方法,其内部调用Module._load()方法

(2)Module._load():require()实现的原理:确定绝对路径(Module._resolveFilename())+加载(根据返回的模块标识符:优先缓存->NativeModule.require()/tryModuleLoad())

Module._cache()将new的模块实例缓存

* Module._resolveFilename():确定模块的绝对路径,以它作为模块的标识符;

举例说明Module._findPath()过程如下:

 * 模块加载:分核心模块和文本模块:

1)核心模块:NativeModule.require()加载;

    js核心模块process.binding('natives')从内存中读取,再编译执行;

    c/c++核心模块:process.binding(内建模块名)通过get_builtin_module()从内存中读取直接执行;

 2)文件模块:module.load():node会新建一个模块对象,然后根据绝对路径载入并编译执行,将结果缓存;

针对不同文件模块有不同的载入方法 js文件模块:通过fs.readFileSync()载入 JSON文件模块:通过JSON.parse()载入 .node文件模块:通过process.dlopen()得到编译后的可执行文件

4.模块的编译执行:调用具体的编译方式将文件执行后返回给调用者

(1)核心模块:在node项目创建时通过node.gyp将所有的c/c++文件编译为二进制文件存储在node内存中(这不属于require()时的操作了);js核心模块在require()时还需要编译一次,而c/c++核心模块就不需要了;

* js核心模块

1)node项目创建时的编译—转为c/c++代码:采用V8的js2c.py库将所有的js模块文件代码以字符串形式存储在c++的数组中,生成node.natives.h头文件;启动node进程时,js模块文件代码以字符串形式直接加载进内存中

2)NativeModule.require():通过模块id做索引从natives数组中取出js核心模块的源码,再通过wrapper()头尾包装(),执行和导出exports对象,将其编译结果缓存到NativeModule._cache对象上;

* c/c++核心模块:编译过程在node项目创建时(生成node.exe),通过node_module_struct结构体定义到node命名空间(就知道了有哪些内建模块了),在.h头文件里将内建模块统一放进node_module_list的数组中,然后被编译进二进制文件加载进node内存中;

(2)文本模块:只有.js文件需要编译;

      .js文件:其过程和js核心模块第二次编译几乎一样;

      .node文件:是c/c++扩展文件编译后的结果:与c/c++核心模块编译类似(通过node-gyp),只是不需要写入node命名空间,在require()前都已经编译好了,加载之后不需要编译了,直接执行之后就可以被外部调用了;

相关文章

  • 模块加载与运行原理

    1.CommonJS规范 (1)导出:exports和module.exports * exports:将要导...

  • Node.js 核心模块概述

    模块加载原理与加载方式 Node 中的模块:核心模块/原生模块:Node提供的模块。文件模块:用户编写的模块。 N...

  • es6的模块化和commonjs的模块有何不同点?

    区别commonjses6加载原理第一次加载模块就会执行整个模块, 再次用到时到缓存中读取不缓存运行结果, 动态的...

  • webpack打包代码实现

    webpack模块加载 异步模块加载 通过 import()实现指定模块的懒加载操作 懒加载的核心原理就是创建js...

  • common.js

    概述 所有代码都运行在模块作用域,不会污染全局作用域。模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结...

  • Node模块原理0926

    Node模块原理 1.node模块原理分析 js代码 2.node模块加载分析(多看几遍视频) 3.自己实现一下(...

  • es6的模块系统

    js引擎运行模块时: 语法解析: 阅读模块源代码,检查语法错误; 加载: 递归的加载所有被导入的模块(深度优先遍历...

  • 结合源码分析 Node.js 模块加载与运行原理

    作者:马龄阳efe.baidu.com/blog/nodejs-module-analyze/ Node.js 的...

  • NodeJS:模块加载原理

    模块的工作原理 实现“模块”功能的奥妙就在于JavaScript是一种函数式编程语言,它支持闭包。如果我们把一段J...

  • 送给2018 年Android程序猿的面试必备大纲

    阿里巴巴 ● LRUCache原理● 图片加载原理● 模块化实现(好处,原因)● JVM● 视频加密传输● 统计启...

网友评论

      本文标题:模块加载与运行原理

      本文链接:https://www.haomeiwen.com/subject/udgepftx.html