小菜
小菜
> 这篇文章从`console.log`入手,对流的写入进行层层剖析。 ## console.log浅析 `console.log`的实现浅析很容易,直接转到[console.js](https://github.com/nodejs/node/blob/master/lib/console.js#L194-L200)中: ```js // ./lib/console.js // ... Console.prototype.log = function log(...args) { write(this._ignoreErrors, this._stdout, this[kFormatForStdout](args), this._stdoutErrorHandler, this[kGroupIndent]); }; ``` 其中`write`函数定义如下: ```js function write(ignoreErrors, stream, string, errorhandler, groupIndent)...
> 这篇文章主要从`fs.write`入手,简单讲述node中写文件同步与异步的实现以及详细解释异步I/O的回调如何通过`AsyncWrap`串起来`nextTick`和`MicroTasks` 昨天有个朋友问我: > 读源码什么都不懂,无从入手该怎么办? 我感觉透过现象来看本质是一个很好的入手方向。这篇文章就从我们熟悉的`fs.write`和`fs.writeSync`入手,透过这些简单的API,来看看node究竟在里面做了什么。 ## fs.write和fs.writeSync 相信有一些node基础的开发者或者之前读过我的文章的读者都会知道`console.log`是基于`process.stdout.write`实现的,意即`console.log`是异步操作(可能有人会提出疑问:既然是异步,如何保证输出是正确的?请自己移步[./lib/console.js](https://github.com/nodejs/node/blob/master/lib/console.js)查看)。所以如果我们想要调试node源码异步回调的时候,如果使用`console.log`会造成递归,这种情况下一般都会使用`fs.writeSync`。在js层面的源码中,`fs.write`和`fs.writeSync`在调用的时候其实只差了一个参数: ```js // ./lib/fs.js fs.write = function(fd, buffer, offset, length, position, callback) { function wrapper(err, written) { // Retain a reference to...
> 这篇文章主要从node源码的./lib/timers.js 入手,历经./lib/internal/timers.js、./src/timer_wrap.cc,并最终下沉到./deps/uv/src/unix/timer.c来叙述整体timers的实现流程。 ### 前言 在阅读 [./lib/timers.js](https://github.com/nodejs/node/blob/master/lib/timers.js)代码的时候,首先映入眼帘的便是如下这几行注释: ```js // ╔════ > Object Map // ║ // ╠══ // ║ refedLists: { '40': { }, '320': { etc } } (keys...
> 本文主要介绍nextTick、timers API、MicroTasks几类任务是在什么时候注册和执行的,也会从node 的bootstrap到evnet-loop过程做一个简单的介绍 ### 整体流程 在这里以下面这段代码为例子,画一下整体的运行流程: ```js setTimeout(() => console.log('timers API'), 10) new Promise((resolve, reject) => resolve('microtask run')).then(arg => console.log(arg)) process.nextTick(() => console.log('run next tick')) setImmediate(() => console.log('setImmediate API'))...
> 这篇文章主要对process对象底层的实现进行解读,所读的源码为9.2版本的代码,博文之中相关代码链接为博文发布之日的node主干分支的代码。 ### process的诞生 process的实现代码应该还是很容易看懂的,我们直接切到`node.cc`中寻找定义process的方法,用不了很长时间,你会发现[SetupProcessObject](https://github.com/nodejs/node/blob/master/src/node.cc#L2973-L3357)方法,通过函数名就能很直观的发现这是定义process的地方,我们直接走到逻辑中去一窥究竟。 这段代码里重复最多的有两个地方,一个是宏[READONLY_PROPERTY](https://github.com/nodejs/node/blob/master/src/node.cc#L2953-L2959),另一个则是函数env->SetMethod([Environment::SetMethod](https://github.com/nodejs/node/blob/master/src/env-inl.h#L583-L594))。其中不难发现,宏定义中调用的是`obj->DefineOwnProperty`,是用来给process定义方法的,而函数SetMethod调用的是: ```c++ v8::Local function = NewFunctionTemplate(callback)->GetFunction(); const v8::NewStringType type = v8::NewStringType::kInternalized; v8::Local name_string = v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked(); that->Set(name_string, function); function->SetName(name_string); ``` 相信如果做过读者addon的话,对这段代码应该是比较熟悉了,可以看到,SetMethod是用来给process定义方法用的。 ### process在c++中的初始化 process在c++中的初始化操作则是在[env.cc](https://github.com/nodejs/node/blob/master/src/env.cc#L135),大家可以注意一下它的外层函数为`...
> 最近做了一个“横屏“H5视频+暂停交互类的项目,遇到了一些小问题,在这里与大家分享一下 - 如果视频需要手机横屏展示,请不要提示用户旋转手机。因为如果用户开启旋转锁变成横屏在安卓下毫无兼容性。解决方案:竖屏手机横屏视频,用`rotate`把视频旋转。 - 视频在小屏幕浏览器中适配问题。解决方案:通过检测屏幕大小来动态修改viewport ```js // 代码来源已无从考究,如果有人认领请在博主下面回复 function adaptVP(a) { function c() { var c, d; return b.uWidth = a.uWidth ? a.uWidth : 750, b.dWidth = a.dWidth ?...
> 本篇文章主要介绍setImmediate底层的实现,主要涉及部分node和libuv源码。 ## 前言 相信稍微对node感兴趣的同学都知道setImmediate触发是在event-loop的check阶段,那么这个setImmediate到底是在哪里实现的注册到uv_check中以及如何触发其中的回调呢? ## js入口 如果要想撕开setImmediate的口子,那么最简单粗暴的方式就是直接从[./lib/timers](https://github.com/nodejs/node/blob/master/lib/timers.js#L56)这里入手。闲话少说,直接撸代码: ```js // lib/timers.js setImmediate回调追踪 // ... const Immediate = class Immediate { constructor(callback, args) { this._idleNext = null; this._idlePrev = null; //...
> nextjs是一个react服务端渲染框架,主要的优势在于所有的有关babel、wepack一系列配置都是自动生成,无需额外配置,对用户来说降低了入门门槛。这篇文章主要从nextjs的cli入手,剖析一下nextjs中有关于node部分的源码。 ### cli的主体实现 nextjs主体cli的实现方式是通过`cross-spawn`和`minimist`实现的。首先看一下nextjs cli 部分的整体结构:  入口文件和相应的bin文件很清晰,结合上面所说的两个package,基本可以猜想到nextjs是通过`cross-spawn`唤起子线程,进而吊起相应的bin文件,然后通过`minimist`实现参数的辨识。接下来我们直接单刀直入next文件来证实一下自己的猜想 ### next文件剖析 翻开next文件,目标直接锁定cli相关的command参数,可以发现如下定义: ```js const defaultCommand = 'dev' const commands = new Set([ 'init', 'build', 'start', 'export', defaultCommand ]) ``` 通过Set实现对command的统一管理,之后只需要通过Set的has方法便可以匹配到用户`process.argv`的输入了。而单独定义出来的`defaultCommand`则可以做argv无参数时候的兼容:...
> 最近试着把自己写的node服务用docker包裹起来。只是对docker的简单入门,docker熟练工可以直接撤了,日志有待改进,虽然网上有很多方案,但是感觉多了一层docker后,日志总是没有很好的解决方案 ### 1.简介 之前做过一个[代理转发](https://github.com/xtx1130/personal-proxy)的项目,同时试水过简单的[docker test case](https://github.com/xtx1130/node-docker),利用闲暇时间,整合了一下第一个项目和docker,这里主要讲其中踩到的坑和遇到过的问题。 ### 2.dockerfile和程序设计 整体设计如下所示:  + docker 的-p参数通过端口映射可以确保外部能访问到docker内部端口,而docker的默认启动方式中,会产生一块虚拟网卡,也可以和外界进行网络交互,具体细节这里不再深究请自行查证资料。这样,网络交互的问题就完美解决了。 + 在设计docker和node的时候,决定中间加一层forever,因为日志没有实现很好,所以如果有问题的话,没有进程守护还是很麻烦的。 + 日志主要是存在docker container中,通过forever 的日志系统实现的存储,所以这个弊端很明显,就是必须用docker exec来翻日志,还好我是本地用,对日志没有强烈的需求。日志的种类有很多,在这里我只列出来了error的日志,在测试docker的时候方便我查找问题。 ```js forever start -a -e /usr/src/personal-proxy/logs/error_log.log /usr/src/personal-proxy/index.js $port ```...
> 今天我们主要介绍一个比较核心的gyp构建项目:node_js2c ## 前言 我相信了解node的人,应该对node_js2c不陌生,如果您感到陌生的话,那么不知道下面这几个词组会不会让您感到亲切点:js2c.py、node_javascript.cc、bootstrap_node.js。如果您能想到什么,那么估计node_js2c离您也会很近,因为是gyp的这个target--node_js2c,串起来了这些文件。 ## node_js2c的前世 node_js2c是什么呢,大家可以翻看一下[node.gyp](http://https://github.com/nodejs/node/blob/master/node.gyp)中,对它的定义: ```code { 'target_name': 'node_js2c', 'type': 'none', 'toolsets': ['host'], 'actions': [ { 'action_name': 'node_js2c', 'process_outputs_as_sources': 1, 'inputs': [ 'Dispose(); return Utils::ToLocal(i_isolate->factory()->empty_string()); } }...