René's URL Explorer Experiment


Title: Node模块加载原理 · Issue #12 · wython/wython.github.io · GitHub

Open Graph Title: Node模块加载原理 · Issue #12 · wython/wython.github.io

X Title: Node模块加载原理 · Issue #12 · wython/wython.github.io

Description: 导读 文章不介绍commonjs细节。会分两部分去介绍node模块加载的原理,第一部分是抽象模型,这部分是希望用最简单的语言去概括node模块运行状态。第二部分是对第一部分的补充,需要结合源码去分析其中的细节。 术语约定 Node编译时:指node安装时候编译的过程 Node启动时:指通过node命令开启一个node进程的过程 Node运行时:指node启动后,node脚本运行的过程 1. 抽象模型 模块边界划分 Node内部的模块加载过程一般会分为两种:核心模块和外部...

Open Graph Description: 导读 文章不介绍commonjs细节。会分两部分去介绍node模块加载的原理,第一部分是抽象模型,这部分是希望用最简单的语言去概括node模块运行状态。第二部分是对第一部分的补充,需要结合源码去分析其中的细节。 术语约定 Node编译时:指node安装时候编译的过程 Node启动时:指通过node命令开启一个node进程的过程 Node运行时:指node启动后,node脚本运行的过程 1. ...

X Description: 导读 文章不介绍commonjs细节。会分两部分去介绍node模块加载的原理,第一部分是抽象模型,这部分是希望用最简单的语言去概括node模块运行状态。第二部分是对第一部分的补充,需要结合源码去分析其中的细节。 术语约定 Node编译时:指node安装时候编译的过程 Node启动时:指通过node命令开启一个node进程的过程 Node运行时:指node启动后,node脚本运行的过程 1. ...

Opengraph URL: https://github.com/wython/wython.github.io/issues/12

X: @github

direct link

Domain: patch-diff.githubusercontent.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Node模块加载原理","articleBody":"### 导读\r\n文章不介绍commonjs细节。会分两部分去介绍node模块加载的原理,第一部分是抽象模型,这部分是希望用最简单的语言去概括node模块运行状态。第二部分是对第一部分的补充,需要结合源码去分析其中的细节。\r\n\r\n### 术语约定\r\nNode编译时:指node安装时候编译的过程\r\nNode启动时:指通过node命令开启一个node进程的过程\r\nNode运行时:指node启动后,node脚本运行的过程\r\n\r\n## 1. 抽象模型\r\n### 模块边界划分\r\n![模块边界划分](https://user-images.githubusercontent.com/15258919/82280073-a1782e80-99c0-11ea-9320-4be8d67182bb.png)\r\nNode内部的模块加载过程一般会分为两种:**核心模块**和**外部模块**。\r\n核心模块:指的是系统内部的,由c/c++或者js编写。\r\n外部模块:指的是运行时非node原生定义的模块,一般支持.node, .js , .json三种后缀。其中.node后缀是由自建c++编译得到的模块文件。\r\n\r\n### c/c++内建核心模块\r\n如前面所说,这部分是由c/c++编写的原生的代码,放源码的src文件夹下。在**Node编译时**会将内建的c/c++代码提取编译成二进制代码,通过一个数组关联。在**启动Node代码时**,这部分二进制代码会随着Node启动一起运行。在**Node脚本运行时**,如果引入相关的模块,会直接提取使用和缓存。\r\n其过程可以如下抽象:\r\n![内建模块](https://user-images.githubusercontent.com/15258919/82282308-169a3280-99c6-11ea-92ac-f3109c71843c.png)\r\n\r\n### js核心模块\r\n这部分是由js编写的原生模块代码,放在源码的lib文件夹下。在**Node编译时**,这部分代码会被v8提供的js2c.py脚本提取到c++的一个头文件node_natives.h中。提取内容为模块和**js源码字符串**的对应关系。源码字符串指的是,不像c++,js代码并不会提前解释,所以存储在内存的是js的字符串。**启动时**,和c++相关部分模块一起关联在核心模块中,平时我们在使用node模块时候,并不会去注意其本身是c++还是js编写。**运行时**如果使用相关模块,会获取js源码字符串,这个和前面的c++相关模块对比,获取时候会判断是c++内置模块还是js核心模块,如果是c++的直接通过binding函数获取运行,如果是js则由compile方法通过v8解释运行。同时使用过核心模块会添加到NativeModule对象的_cache缓存一个模块id。\r\n其过程可以如下抽象:\r\n![js核心模块](https://user-images.githubusercontent.com/15258919/82282920-80ffa280-99c7-11ea-9723-cdf3687e2890.png)\r\n\r\n### 外部模块\r\nNode能解析三种后缀的模块 .js、.node、.json。Node在解析外部模块过程中,先要解析模块的路径,尝试获取文件,如果没有或尝试在node_module中获取。\r\n1. .js类型\r\njs模块的加载过程,首先通过fs解析路径,获取文件代码,然后包装,最后通过v8进行编译解释运行,对于解释过的外部模块,会添加的Module对象的_cache缓存。\r\n\r\n2. .json类型\r\njson模块实际上只是加载json数据的过程,解析完文件,将json文件用JSON.parse运行转换成js数据\r\n格式。\r\n\r\n3. .node类型\r\n.node类型模块是c/c++代码通过node-gyp程序将代码编译成二进制的node文件,node中通过dlopen方法可以加载.node模块进行运行。在写c/c++模块时候,需要先编译成.node类型才能被node程序识别,node无法直接识别c++模块\r\n\r\n4. 其他\r\n其他后缀会被node当成js程序执行。\r\n\r\n## 2. 具体过程细节\r\n上面有个大体的流程,node新版和旧版本的代码必然是不一样的。\r\n### v6版本node\r\n### 启动过程\r\nnode启动代码在src的node_main.cc的c++文件下。[node_main.cc](https://github.com/nodejs/node/blob/v6.x/src/node_main.cc)\r\n``` c++\r\nint main(int argc, char *argv[]) {\r\n  // Disable stdio buffering, it interacts poorly with printf()\r\n  // calls elsewhere in the program (e.g., any logging from V8.)\r\n  setvbuf(stdout, nullptr, _IONBF, 0);\r\n  setvbuf(stderr, nullptr, _IONBF, 0);\r\n  return node::Start(argc, argv);\r\n}\r\n```\r\n调用了[node.cc](https://github.com/nodejs/node/blob/v6.x/src/node.cc)文件的Start方法, Start方法中调用了StartNodeInstance,然后调用了LoadEnvironment, 在LoadEnvironment中,拿到bootstrap_node.js运行。\r\n``` c++\r\nLocal\u003cString\u003e script_name = FIXED_ONE_BYTE_STRING(env-\u003eisolate(),\r\n                                                    \"bootstrap_node.js\");\r\n```\r\n\r\n### 使用require加载\r\n平时使用node,都是像下面这样用require加载模块,可能是http这样的模块,也可能是相对路径的文件模块。\r\n``` node\r\nrequire('http')\r\nrequire('./utils.js')\r\n```\r\nrequire的方法定义在Module.js对象上。[module.js](https://github.com/nodejs/node/blob/v6.x/lib/module.js)文件在lib对于文件夹下。关于require的流程细节就像代码展示的一样:\r\n```\r\nModule.prototype.require = function(path) {\r\n  assert(path, 'missing path');\r\n  assert(typeof path === 'string', 'path must be a string');\r\n  return Module._load(path, this, /* isMain */ false);\r\n};\r\n...\r\nModule._load = function(request, parent, isMain) {\r\n  if (parent) {\r\n    debug('Module._load REQUEST %s parent: %s', request, parent.id);\r\n  }\r\n\r\n  var filename = Module._resolveFilename(request, parent, isMain);\r\n\r\n  var cachedModule = Module._cache[filename];\r\n  if (cachedModule) {\r\n    return cachedModule.exports;\r\n  }\r\n\r\n  if (NativeModule.nonInternalExists(filename)) {\r\n    debug('load native module %s', request);\r\n    return NativeModule.require(filename);\r\n  }\r\n\r\n  var module = new Module(filename, parent);\r\n\r\n  if (isMain) {\r\n    process.mainModule = module;\r\n    module.id = '.';\r\n  }\r\n\r\n  Module._cache[filename] = module;\r\n\r\n  tryModuleLoad(module, filename);\r\n\r\n  return module.exports;\r\n};\r\n```\r\n可以看到,所有核心的模块是用NativeModule.require(filename)获取,外部模块通过tryModuleLoad(module, filename)方法获取。\r\n\r\n### 外部模块的获取细节\r\n在上面的代码中,可以看到,通过tryModuleLoad(module, filename)获取了外部模块,而在tryModuleLoad中,其实还是调用了Module._extensions对象来按文件后缀引入外部模块。平时在我们在写模块文件中,可以拿到module,exports, require等对象,可以通过console.log(require.extensions)打印extensions的结构。下面看看tryModuleLoad的流程代码是怎么走:\r\n``` node\r\nfunction tryModuleLoad(module, filename) {\r\n  var threw = true;\r\n  try {\r\n    module.load(filename);\r\n    threw = false;\r\n  } finally {\r\n    if (threw) {\r\n      delete Module._cache[filename];\r\n    }\r\n  }\r\n}\r\n\r\nModule.prototype.load = function(filename) {\r\n  debug('load %j for module %j', filename, this.id);\r\n\r\n  assert(!this.loaded);\r\n  this.filename = filename;\r\n  this.paths = Module._nodeModulePaths(path.dirname(filename));\r\n\r\n  var extension = path.extname(filename) || '.js';\r\n  if (!Module._extensions[extension]) extension = '.js';\r\n  Module._extensions[extension](this, filename);\r\n  this.loaded = true;\r\n};\r\n```\r\n\r\n_extensions定义了三个方法分别是.js,.json,.node:\r\n```\r\nModule._extensions['.js'] = function(module, filename) {\r\n  var content = fs.readFileSync(filename, 'utf8');\r\n  module._compile(internalModule.stripBOM(content), filename);\r\n};\r\n\r\n\r\n// Native extension for .json\r\nModule._extensions['.json'] = function(module, filename) {\r\n  var content = fs.readFileSync(filename, 'utf8');\r\n  try {\r\n    module.exports = JSON.parse(internalModule.stripBOM(content));\r\n  } catch (err) {\r\n    err.message = filename + ': ' + err.message;\r\n    throw err;\r\n  }\r\n};\r\n\r\n\r\n//Native extension for .node\r\nModule._extensions['.node'] = function(module, filename) {\r\n  return process.dlopen(module, path._makeLong(filename));\r\n};\r\n```\r\n#### 1. js文件\r\n正如前面的抽象模型所表示的,js文件会调用_compile方法编译,_compile会调用vm对象通过v8解释代码,关于vm接口可以在node文档中查阅。\r\n``` node\r\nvar compiledWrapper = vm.runInThisContext(wrapper, {\r\n    filename: filename,\r\n    lineOffset: 0,\r\n    displayErrors: true\r\n  });\r\n```\r\n#### 2. json\r\n这个没什么好说的。\r\nmodule.exports = JSON.parse(internalModule.stripBOM(content));\r\n\r\n#### 3. node\r\n也没什么好说的: process.dlopen(module, path._makeLong(filename));\r\n\r\n### 核心模块\r\n核心模块的流程走的是NativeModule的require方法。\r\n\r\n#### js核心模块\r\n前面说到,**在编译时候**,js核心模块会被js2c.py脚本转换成一个c++头文件。生成位置是在out/release/obj/gen目录下。结构如:\r\n``` c++\r\nnamespace node {\r\n  const char node_native[] = { 47, 47, ..};\r\n  const char dgram_native[] = { 47, 47, ..}; \r\n  const char console_native[] = { 47, 47, ..}; \r\n  const char buffer_native[] = { 47, 47, ..};\r\n  const char querystring_native[] = { 47, 47, ..}; \r\n  const char punycode_native[] = { 47, 42, ..}; \r\n  ...\r\n  struct _native { \r\n    const char* name; \r\n    const char* source; \r\n    size_t source_len;\r\n  };\r\n  static const struct _native natives[] = {\r\n    {  \"node\",  node_native, sizeof(node_native)-1 },\r\n    { \"dgram\", dgram_native, sizeof(dgram_native)-1 },\r\n     ...\r\n  };\r\n}\r\n```\r\n其中,source对应的是js源码字符串。编译完成后,这个头文件会被编译进node二进制执行文件中(node命令)。\r\n**Node启动时候**,所有核心模块(js和c++的)都是通过NativeModule对象维护。文件对象定义在bootstrap_node,顾名思义,这个脚本会在启动时执行。\r\n[bootstrap_node源码文件](https://github.com/nodejs/node/blob/v6.x/lib/internal/bootstrap_node.js)\r\n其中跟着脚本一起执行的有:\r\n``` node\r\n NativeModule._source = process.binding('natives');\r\n NativeModule._cache = {};\r\n ...\r\n startup();\r\n```\r\nbinding方法是定义在c++中的方法。实际上就是将上面c++头文件的关系挂载到_source对象下。\r\n\r\n#### c/c++核心模块\r\nc++的模块在安装node时候以及编译成了可执行代码。所以平时使用如果涉及到c++的模块,通过上面NativeModule调用vm对象运行c++的模块,是不需要定位和编译过程,相对js的代码来说效率会更高。\r\n\r\nc++的模块,通过NODE_MODULE宏挂载在Node的命名空间里。\r\n``` c++\r\n#define NODE_MODULE(modname, regfunc)\r\n  extern \"C\" {\r\n    NODE_MODULE_EXPORT node::node_module_struct modname ## _module =\r\n    {\r\n      NODE_STANDARD_MODULE_STUFF,\r\n      regfunc,\r\n      NODE_STRINGIFY(modname)\r\n     };\r\n}\r\n```\r\nc++模块的结构体是:\r\n``` c++\r\nstruct node_module_struct {\r\n  int version;\r\n  void *dso_handle;\r\n  const char *filename;\r\n  void (*register_func) (v8::Handle\u003cv8::Object\u003e target); const char *modname;\r\n};\r\n```\r\n在node底层,可以通过Binding方法直接获取到c++的核心模块(正常都是通过调用js模块,间接调用),Binding方法定义在node.cc中:\r\n``` c++\r\nstatic void Binding(const FunctionCallbackInfo\u003cValue\u003e\u0026 args) {\r\n  Environment* env = Environment::GetCurrent(args);\r\n\r\n  Local\u003cString\u003e module = args[0]-\u003eToString(env-\u003eisolate());\r\n  node::Utf8Value module_v(env-\u003eisolate(), module);\r\n\r\n  Local\u003cObject\u003e cache = env-\u003ebinding_cache_object();\r\n  Local\u003cObject\u003e exports;\r\n\r\n  if (cache-\u003eHas(env-\u003econtext(), module).FromJust()) {\r\n    exports = cache-\u003eGet(module)-\u003eToObject(env-\u003eisolate());\r\n    args.GetReturnValue().Set(exports);\r\n    return;\r\n  }\r\n\r\n  // Append a string to process.moduleLoadList\r\n  char buf[1024];\r\n  snprintf(buf, sizeof(buf), \"Binding %s\", *module_v);\r\n\r\n  Local\u003cArray\u003e modules = env-\u003emodule_load_list_array();\r\n  uint32_t l = modules-\u003eLength();\r\n  modules-\u003eSet(l, OneByteString(env-\u003eisolate(), buf));\r\n\r\n  node_module* mod = get_builtin_module(*module_v);\r\n  if (mod != nullptr) {\r\n    exports = Object::New(env-\u003eisolate());\r\n    // Internal bindings don't have a \"module\" object, only exports.\r\n    CHECK_EQ(mod-\u003enm_register_func, nullptr);\r\n    CHECK_NE(mod-\u003enm_context_register_func, nullptr);\r\n    Local\u003cValue\u003e unused = Undefined(env-\u003eisolate());\r\n    mod-\u003enm_context_register_func(exports, unused,\r\n      env-\u003econtext(), mod-\u003enm_priv);\r\n    cache-\u003eSet(module, exports);\r\n  } else if (!strcmp(*module_v, \"constants\")) {\r\n    exports = Object::New(env-\u003eisolate());\r\n    DefineConstants(env-\u003eisolate(), exports);\r\n    cache-\u003eSet(module, exports);\r\n  } else if (!strcmp(*module_v, \"natives\")) {\r\n    exports = Object::New(env-\u003eisolate());\r\n    DefineJavaScript(env, exports);\r\n    cache-\u003eSet(module, exports);\r\n  } else {\r\n    char errmsg[1024];\r\n    snprintf(errmsg,\r\n             sizeof(errmsg),\r\n             \"No such module: %s\",\r\n             *module_v);\r\n    return env-\u003eThrowError(errmsg);\r\n  }\r\n\r\n  args.GetReturnValue().Set(exports);\r\n}\r\n```\r\n如代码所示,c++内建的模块通过`node_module* mod = get_builtin_module(*module_v);`调用,从node_module_list数组中拿出,然后通过register_func注册给exports对象,而前面的js模块则是由'native'统一挂载在NativeModule._source下。\r\n\r\n### 新版本node\r\n\r\n参考资料:\r\n[深入浅出nodejs.pdf](https://read.douban.com/ebook/12053349/)\r\n[node github源码](https://github.com/nodejs/node/tree/v6.x)\r\n[结合源码分析 Node.js 模块加载与运行原理](https://efe.baidu.com/blog/nodejs-module-analyze/)\r\n\r\n","author":{"url":"https://github.com/wython","@type":"Person","name":"wython"},"datePublished":"2020-05-19T03:55:03.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/12/wython.github.io/issues/12"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:93b7a663-02db-49c9-6c75-6df60c665c1b
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-idA96A:242157:654C47F:8402C5A:6975624D
html-safe-nonce4bfda56d3acaae3f57c5678b75d7c5e1ab82db85e5af76b20a88ead0bb406e87
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBOTZBOjI0MjE1Nzo2NTRDNDdGOjg0MDJDNUE6Njk3NTYyNEQiLCJ2aXNpdG9yX2lkIjoiNjIyMDE2MzcyMzY1ODg3OTU2NSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9
visitor-hmac73698b47044ac0e5f4257d01913761ea0b7cff15382cb7d5204863223d7f3cb0
hovercard-subject-tagissue:620656974
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/wython/wython.github.io/12/issue_layout
twitter:imagehttps://opengraph.githubassets.com/993e1f5668f219f66cf51ec25886a6fd3a9437550aac8bdd1da91f434b0af307/wython/wython.github.io/issues/12
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/993e1f5668f219f66cf51ec25886a6fd3a9437550aac8bdd1da91f434b0af307/wython/wython.github.io/issues/12
og:image:alt导读 文章不介绍commonjs细节。会分两部分去介绍node模块加载的原理,第一部分是抽象模型,这部分是希望用最简单的语言去概括node模块运行状态。第二部分是对第一部分的补充,需要结合源码去分析其中的细节。 术语约定 Node编译时:指node安装时候编译的过程 Node启动时:指通过node命令开启一个node进程的过程 Node运行时:指node启动后,node脚本运行的过程 1. ...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernamewython
hostnamegithub.com
expected-hostnamegithub.com
None4a4bf5f4e28041a9d2e5c107d7d20b78b4294ba261cab243b28167c16a623a1f
turbo-cache-controlno-preview
go-importgithub.com/wython/wython.github.io git https://github.com/wython/wython.github.io.git
octolytics-dimension-user_id15258919
octolytics-dimension-user_loginwython
octolytics-dimension-repository_id142893945
octolytics-dimension-repository_nwowython/wython.github.io
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id142893945
octolytics-dimension-repository_network_root_nwowython/wython.github.io
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release488b30e96dfd057fbbe44c6665ccbc030b729dde
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://patch-diff.githubusercontent.com/wython/wython.github.io/issues/12#start-of-content
https://patch-diff.githubusercontent.com/
Sign in https://patch-diff.githubusercontent.com/login?return_to=https%3A%2F%2Fgithub.com%2Fwython%2Fwython.github.io%2Fissues%2F12
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub SparkBuild and deploy intelligent appshttps://github.com/features/spark
GitHub ModelsManage and compare promptshttps://github.com/features/models
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
GitHub SponsorsFund open source developershttps://github.com/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/accelerator
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://patch-diff.githubusercontent.com/login?return_to=https%3A%2F%2Fgithub.com%2Fwython%2Fwython.github.io%2Fissues%2F12
Sign up https://patch-diff.githubusercontent.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=wython%2Fwython.github.io
Reloadhttps://patch-diff.githubusercontent.com/wython/wython.github.io/issues/12
Reloadhttps://patch-diff.githubusercontent.com/wython/wython.github.io/issues/12
Reloadhttps://patch-diff.githubusercontent.com/wython/wython.github.io/issues/12
wython https://patch-diff.githubusercontent.com/wython
wython.github.iohttps://patch-diff.githubusercontent.com/wython/wython.github.io
Notifications https://patch-diff.githubusercontent.com/login?return_to=%2Fwython%2Fwython.github.io
Fork 0 https://patch-diff.githubusercontent.com/login?return_to=%2Fwython%2Fwython.github.io
Star 10 https://patch-diff.githubusercontent.com/login?return_to=%2Fwython%2Fwython.github.io
Code https://patch-diff.githubusercontent.com/wython/wython.github.io
Issues 14 https://patch-diff.githubusercontent.com/wython/wython.github.io/issues
Pull requests 0 https://patch-diff.githubusercontent.com/wython/wython.github.io/pulls
Actions https://patch-diff.githubusercontent.com/wython/wython.github.io/actions
Projects 0 https://patch-diff.githubusercontent.com/wython/wython.github.io/projects
Security 0 https://patch-diff.githubusercontent.com/wython/wython.github.io/security
Insights https://patch-diff.githubusercontent.com/wython/wython.github.io/pulse
Code https://patch-diff.githubusercontent.com/wython/wython.github.io
Issues https://patch-diff.githubusercontent.com/wython/wython.github.io/issues
Pull requests https://patch-diff.githubusercontent.com/wython/wython.github.io/pulls
Actions https://patch-diff.githubusercontent.com/wython/wython.github.io/actions
Projects https://patch-diff.githubusercontent.com/wython/wython.github.io/projects
Security https://patch-diff.githubusercontent.com/wython/wython.github.io/security
Insights https://patch-diff.githubusercontent.com/wython/wython.github.io/pulse
New issuehttps://patch-diff.githubusercontent.com/login?return_to=https://github.com/wython/wython.github.io/issues/12
New issuehttps://patch-diff.githubusercontent.com/login?return_to=https://github.com/wython/wython.github.io/issues/12
Node模块加载原理https://patch-diff.githubusercontent.com/wython/wython.github.io/issues/12#top
node.jshttps://github.com/wython/wython.github.io/issues?q=state%3Aopen%20label%3A%22node.js%22
https://github.com/wython
https://github.com/wython
wythonhttps://github.com/wython
on May 19, 2020https://github.com/wython/wython.github.io/issues/12#issue-620656974
https://user-images.githubusercontent.com/15258919/82280073-a1782e80-99c0-11ea-9320-4be8d67182bb.png
https://user-images.githubusercontent.com/15258919/82282308-169a3280-99c6-11ea-92ac-f3109c71843c.png
https://user-images.githubusercontent.com/15258919/82282920-80ffa280-99c7-11ea-9723-cdf3687e2890.png
node_main.cchttps://github.com/nodejs/node/blob/v6.x/src/node_main.cc
node.cchttps://github.com/nodejs/node/blob/v6.x/src/node.cc
module.jshttps://github.com/nodejs/node/blob/v6.x/lib/module.js
bootstrap_node源码文件https://github.com/nodejs/node/blob/v6.x/lib/internal/bootstrap_node.js
深入浅出nodejs.pdfhttps://read.douban.com/ebook/12053349/
node github源码https://github.com/nodejs/node/tree/v6.x
结合源码分析 Node.js 模块加载与运行原理https://efe.baidu.com/blog/nodejs-module-analyze/
node.jshttps://github.com/wython/wython.github.io/issues?q=state%3Aopen%20label%3A%22node.js%22
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.