深入浅出nodejs -- node基础

node 基础

本文摘要了深入浅出 nodejs 的第一,二章

Why node?

因为 Ryan 想找一个事件驱动,并且非阻塞的 IO,而且 chrome 的 V8 引擎非常强大。

node 与 chrome 很像,node 基于 V8 引擎运行 js,通过引擎控制一些中间件来控制网卡,硬盘等等的底层。

chrome 也是通过通过 V8 运行 js,通过引擎控制中间件来控制底层的网卡,硬盘。当然 chrome 还有布局引擎 webkit 来处理 html,也是由布局引擎来通过中间件控制底层的网卡,硬盘。

node 的底层 api 大都被设计为了异步的 io,这样在编程模型上可以极大的提高效率。

单线程

node 保持了 javascript 在浏览器单线程的特点,所以不会有死锁,不会有线程上下文交换带来的性能上的开销。

但是问题在于:

  • 无法利用多核 CPU
  • 一旦挂了,程序退出
  • 计算太多,导致 CPU 无法继续调用异步 IO

node 的解决办法是 child_process

通过子进程可以应对健壮性和多核 CPU 的问题,通过将计算分解到各个子进程,然后通过进程间的事件消息来传递结果。

Node 应用场景

毫无疑问,IO 密集型 node 非常强,因为 Node 面向网络并且擅长执行并行 IO,能够有效的组织起更多的硬件资源。

对于 CPU 密集型的应用,其实 v8 的深度优化导致计算能力实际上很强,只不过 js 为单线程应用,长时间计算会阻塞而已,但是通过拆分分解还是不错的。可以使用一些 c++的扩展方式,或者通过子进程将一部分的 node 进程当做常驻服务进行计算。

所以 CPU 密集型不可怕,合理的调度才是诀窍。

模块机制

模块化的出现,改变了 js 杂乱无章的现状。CommonJS 规范是为了 Javascript 能够在任何地方运行。

Node 借鉴 Commonjs 的 Modules 规范实现了一套非常易用的模块系统。

Commonjs 的模块规范

  • 模块引用

很简单,require 方法,将模块的 api 引入到上下文中

  • 模块定义

上下文提供了一个 exports 对象来导出当前模块的方法或者变量。还有一个 module 对象代表模块自身。还有一个 exports 是 module 的属性,通过将方法挂载到 exports 对象上作为属性即可定义导出。

这里应该这么理解。exports = module.exports ;module.exports 是真实的要输出的东西,所以如果改变 exports 对象的执行,exports 对象就没用了。

  • 模块标识

就是传递给 require 的参数,必须是小驼峰命名的字符串,或者.,..开头的相对或者绝对路径。

Node 的模块实现

引入模块的 3 个步骤:

  • 路径分析
  • 文件定位
  • 编译执行

Node 模块分为核心模块和用户编写的文件模块。

核心模块在编译过程中直接编译为了二进制文件,直接在 node 运行时被加入内存,所以他没有文件定位和编译执行两步,而且路径分析优先判断。加载最快。

而文件模块则需要完整的 3 个步骤,所以加载速度比较慢。

注意加载是缓存优先,require 方法对相同模块的二次加载都一律采用缓存优先,是第一优先级。当然核心模块缓存检查先于文件模块的缓存检查。

路径分析

首先优先核心模块,直接加载,然后是路径形式和文件模块,由于给出了路径,也是最方便的查找过程,其次是自定义的模块,不是核心,也没有路径,他会从当前路径一层层向外查找,直到根目录为止,所以加载速度最慢。

文件定位

分析标识符的时候,可能会不带文件扩展名,这种情况下,node 会以 js,json,node 为次序依次尝试。

所以小诀窍是,如果是.node和.json文件,最后带上扩展名,会加快速度。

然后如果是目录分析和包的话,会找他的 package.json,然后根据 man 属性的文件名进行定位,找不到则以 index.js,index.json,index.node 的顺序来找,再找不到,就找下一层,到根目录都找不到,就抛出异常。

模块编译

其实是分文件的,.node就直接通过 process.dlopen 来加载,底层通过 libuv 兼容层来进行了封装,json 文件就被 JSON.parse 了,其他的 js 文件其实就是进行了头尾包装,变成一种类似匿名函数的方式来保证作用域的隔离。

包装之后的代码通过 runInThisContext 方法执行(类似于 eval,不过有自己的上下文,不会污染全局)。

这里倒是解决了那个问什么会存在 exports 和 module.exports 两个东西,并且直接调用exports=a;会出错的问题了。

因为包装过的东西类似于

(function(exports, require, module, __filename, __dirname) {
  exports.add = function() {};
});

而 exports 是个形参,直接赋值会改变形参的引用,但是无法改变作用域外的值,所以要赋值的话给 module.exports,这个迂回的方案不改变形参的引用。

核心模块

核心模块也分为 C/C++编写和 javascript 编写的两部分,c 的放在 Node 项目的 src,js 的放在 lib 中。

核心模块编译过程

在编译所有 c/c++之前,先得把 js 编译成 c/c++。

这里介绍了不少编写 c 语言模块的,只是不是很懂,将来找机会再看吧。

基本上就是 c 负责了一些底层的模块来给上层的 js 调用。js 核心模块也分为调用 c 的和只提供纯粹的功能,不与底层打交道的模块。

包与 Npm

包的结构规范:

  • package.json:包描述文件
  • bin:用于存放可执行二进制文件的目录
  • lib:放 js 代码的目录
  • doc:放文档的目录
  • test:存放单元测试用例的代码

包描述文件

  • name:小写字母和数字
  • descripton
  • version
  • keywords:用来帮助别人搜索的
  • maintainers:维护者列表,npm 根据该属性进行权限认证[{“name”:”panyifei”,”email”:”91@qq.com“,”web”:”cc.com”}]
  • contributors:贡献者列表,格式同上
  • bugs:提交 bug 的邮件地址或者网页地址
  • licenses:许可证列表
  • repositories:源代码的位置
  • dependences:依赖列表,这个比较关键
  • homepage
  • os:操作系统支持列表
  • cpu:CPU 架构的支持列表
  • engine:支持的 js 的引擎列表
  • builtin:是否是内建在底层系统的标准组件
  • directories:包目录说明
  • implements:实现的规范列表,标识实现了 commonjs 的那些规范
  • scripts:脚本说明对象,包含了 install,uninstall,test 等等,这其实是个钩子命令,在执行 install 的时候,preinstall 指向的会被先触发

NPM 实际实现多了 4 个:

  • author:作者
  • bin:这个字段设置了之后就可以作为命令行工具使用了
  • main:模块引入方法 require 的时候,会优先检查这个字段,没有的话就去找 index.js,index.node,index.json 作为默认入口
  • devDependencies:开发时需要的依赖

NPM 实际上是 CommonJS 包规范的一种实践。

全局模式安装

npm install express -g其实全局模式只是把包安装成为一个全局可用的可执行命令。

npm install 后面可以放一个包含了 package.json 的本地文件或 url 地址。

从非官方源下载

npm install underscore –registry=http://registry.url

如果以后都采用镜像的话,就

npm config set registry http://registry.url

注册包仓库账号

npm adduser

注册完了之后就可以上传发布包了

发布包

npm publish .

管理包的权限

列出包的所有的拥有者

  • npm owner ls refuseuse

添加拥有者(删除自然是 remove)

  • npm owner add

分析当前路径能够拿到某个包

直接 npm ls 可以分析路径

前后端共用

虽然执行环境很类似,但是前后端期望的东西不同,前端的瓶颈是带宽,后端的瓶颈是性能,如果后端页通过同步的形式加载的话,会问题比较严重,于是才有了 AMD 规范以及玉伯的 CMD 规范。

AMD 规范

AMD 需要 define 方法来申明一个模块,并且在申明的时候得将依赖都写进去。

CMD 的话就更类似 Conmonjs 了,使用的时候再进行 require 就行了。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 981909093@qq.com

文章标题:深入浅出nodejs -- node基础

文章字数:2.2k

本文作者:泽鹿

发布时间:2019-08-28, 16:45:23

最后更新:2019-08-28, 16:45:23

原始链接:http://panyifei.github.io/2019/08/28/读书笔记/深入浅出nodejs/node基础/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏