Node.js源码解析----自己实现一个Node.js的难点与思路

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node.js源码解析----自己实现一个Node.js的难点与思路相关的知识,希望对你有一定的参考价值。

前言:

最近在看Node.js,看了一段时间后便想着自己实现一个Node.js现在已经实现了个大概(绝大部分是模仿人家,不过自己实现一遍基本上就理解Node.js的原理了)下面便说说这个过程中的坑,以及一些需要注意的地方;

      Node.js需要一定C++基础,建议看完C++Primer再看,否则V8的好多表达方式,指针,引用,模板之类的会看不懂;

      代码已上传GitHub地址:   https://github.com/sven36/cNode

 

编译:我用的win10的环境,具体编译请参考Node.js的编译说明:https://github.com/nodejs/node/blob/master/BUILDING.md

        其中的坑:Python应该是2.6或2.7,不要装3.0或以上的,因为node.js有的py文件3.0编译出错Visual C++ Build Tools必须是2015,安装官方的链接就是,因为Node.js在Windows平台的编译用的是vs2015的v140平台工具集,用低版本的或者vs2017的v141平台工具集都会报错;

 

        编译流程:安装完python和Visual C++ Build Tools2015之后,下载node.js的源码  node-v6.10.0.tar.gz  然后用Visual C++ Build Tools2015的命令行运行解压目录下的vcbuild.bat处理文件就会开始编译了;编译成功后解压目录下就会出现.sln文件就可以使用vs打开了(vs也需要是2015或2017,并且项目的平台工具集也需要是v140否则编译报错);如图:

 技术分享

 

 

自己实现一个Node.js的难点与思路:

V8引擎:

          因为node.js其实就是嵌入V8的一个C++程序;首先要对v8的Isolate,LocalHandle,Scope等概念有一个了解,此处不展开了,请参考这个文档:

           https://github.com/Chunlin-Li/Chunlin-Li.github.io/blob/master/blogs/javascript/V8_Embedder‘s_Guide_CHS.md

          在我的代码里面我也加了一些注释,在src目录下的node.cpp文件内,可以参考;

 

C++编译与平常的面向对象编译方式的不同

          在.NET或Java之类的语言中,可以不必关注方法的声明顺序,比如:

          private void a(){

               b();

         }

         private void b(){

               console.log(1);

         }

         不过在C++中这样是不行的,调用b之前,必须完全声明b;也就是把b放在方法a之前(这也是node.cpp文件中为什么把开始方法Start放在最下端);

     

为什么Node.js的头文件要用namespace node包起来:

                 是为了更好的解耦node.js的各个模块;在C++中命名空间相同而内部成员名字不同,它们会自动合并为同一个命名空间,可以理解为追加;

 

Node.js里面比较复杂的宏定义:

    Node.js和V8用了很多复杂的宏定义,如果不理解它们看起来会很费力;在C++中,宏定义里面的##符号是连接字符串的意思;

    比如:env-inl.h文件下的宏定义:

#define VP(PropertyName, StringValue) V(v8::Private, PropertyName, StringValue)
#define VS(PropertyName, StringValue) V(v8::String, PropertyName, StringValue)
#define V(TypeName, PropertyName, StringValue)                                \\
  inline                                                                      \\
  v8::Local<TypeName> Environment::IsolateData::PropertyName() const {        \\
    /* Strings are immutable so casting away const-ness here is okay. */      \\
    return const_cast<IsolateData*>(this)->PropertyName ## _.Get(isolate());  \\
  }
    PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
        PER_ISOLATE_STRING_PROPERTIES(VS)
#undef V
#undef VS
#undef VP

它最后的编译形式是:

    inline v8::Local<v8::String> Environment::IsolateData::async_queue_string() const {
        return const_cast<IsolateData*>(this)->async_queue_string_.Get(isolate());
    }

这种地方多一些耐心仔细分析一下就会懂了;我写的代码里面基本上这种宏定义第一个字符串我都是这种手写的,其余的是按照原先的宏定义的方式声明,可以参考;

 

使用VS编译需要注意的地方

      node.js项目文件其实是用google的GYP工具生产的,所以VS项目编译的过程也在各个项目下的.gyp文件内。

      了解gyp工具请参考:http://www.cnblogs.com/nanvann/p/3913880.html#conditions

 

当然还有很多具体的C++问题就需要靠自己多思考,勤搜索了;

 

 

 

        

 

 

 

 

















以上是关于Node.js源码解析----自己实现一个Node.js的难点与思路的主要内容,如果未能解决你的问题,请参考以下文章

Node.js Koa源码解析co@4.6版本源码解析

Node.js-Events 模块总结与源码解析

深入解析Node.js setTimeout方法的执行过程

Node.js如何解析Form上传?

nodejs原理&源码赏析深度剖析cluster模块源码与node.js多进程(上)

利用Vue.js+Node.js+MongoDB实现一个博客系统(附源码)