NPM
npm install -g
只做了一个事情:复制 bin 下面的文件到 xx 目录,因此需要自己配置运行环境或者提供可执行文件
因此网上的教程一般让我们加上:#!/usr/bin/env node
,这样我们在 shell 中直接运行这个文件的时候,会告诉 shell 使用 node 作为运行环境帮我们运行这个文件的内容。
npm install -g
只做了一个事情:复制 bin 下面的文件到 xx 目录,因此需要自己配置运行环境或者提供可执行文件
因此网上的教程一般让我们加上:#!/usr/bin/env node
,这样我们在 shell 中直接运行这个文件的时候,会告诉 shell 使用 node 作为运行环境帮我们运行这个文件的内容。
使用 webpack_dev_server
的 Vue
项目
假设有一种需求,想要对引入的 npm
包进行调试,找出它里面的问题或者了解其运行的原理,我们就会涉及到对引入的包进行调试的需求,要解决的思路也比较简单。
使用 Chrome Dev Tool
我们可以直接运行项目,然后到 Chrome
中按 F12 打开 Dev Tool
,切换到 Source
标签页。在这里面我们找到通过 Webpack
引入的包:
在找到后,以 iview
这个包为例,我们可以看到它的打包方式是将很多个模块打包成一个 js
文件的形式,我们可以通过搜索找到对应的模块,直接打上断点即可调试。
使用 IDE
我们需要知道的一点是,其实我们直接 import XXX from 'xxx'
进来的包,本质上是指向了 node_module
下对应的文件夹。在每个标准的 npm
包中,都会有一个 package.json
文件,其中的 main
属性指向了以上述方式引入直接指向的 js
文件,所以其实我们 import
进来的就是这个 js
文件。
因此我们可以直接杀到他家,在这个 js
文件中打上断点(debugger
),在运行过程中就可以直接通过 Dev Tool
看到调试界面啦~(虽然这样还是要用到 Chrome
的 Dev Tool
,但是在 IDE
中查看一些东西相对于 Chrome
还是更方便滴)
npm
是一个包管理器,npx
类似于一个运行需要全局安装的 npm
包的快捷指令,会在需要时下载对应的包,用完即删除。在 npm
的基础之上,npx
让 npm
包中的命令行工具和其他可执行文件在使用上变得更加简单。
确立需求
第一次迭代(基本功能)
快速迭代是一种不错的开发方式,在第一次迭代时先实现服务器的基本功能
第二次迭代(性能)
在第一次迭代之后,已经拥有了一个简单的、可工作的版本,满足了功能需求。一般第二次迭代需要从性能的角度出发,看看有什么改进余地。
第三次迭代(稳定性)
第二次迭代之后,服务器本身的功能和性能已经得到了初步满足。接下来我们要从稳定性的角度重新审视一下代码,看看还需要做些什么。
第四次迭代(代码部署,项目结构)
在解决了服务器本身的功能、性能和可靠性问题后,最后要考虑的是代码部署的问题,以及服务器控制的问题
后续迭代
在服务器程序正式上线后,将会从可改进的点出发,将上述问题放大审视,并逐步完善需求与修复 bug
问: 为什么通过headers
对象访问到的HTTP
请求头或响应头字段不是驼峰的?
答: 从规范上讲,HTTP请求
头和响应头字段都应该是驼峰的。但现实是残酷的,不是每个 HTTP服务
端或客户端程序都严格遵循规范,所以NodeJS
在处理从别的客户端或服务端收到的头字段时,都统一地转换为了小写字母格式,以便开发者能使用统一的方式来访问头字段,例如headers['content-length']
。
问: 为什么http
模块创建的HTTP
服务器返回的响应是chunked
传输方式的?
答: 因为默认情况下,使用.writeHead
方法写入响应头后,允许使用.write
方法写入任意长度的响应体数据,并使用.end 方法结束一个响应。由于响应体数据长度不确定,因此NodeJS
自动在响应头里添加了Transfer-Encoding: chunked
字段,并采用chunked
传输方式。但是当响应体数据长度确定时,可使用.writeHead
方法在响应头里加上Content-Length
字段,这样做之后NodeJS
就不会自动添加Transfer-Encoding
字段和使用chunked
传输方式。
问: 为什么使用http
模块发起HTTP
客户端请求时,有时候会发生socket hang up
错误?
答: 发起客户端HTTP
请求前需要先创建一个客户端。http
模块提供了一个全局客户端http.globalAgent
,可以让我们使用.request
或.get
方法时不用手动创建客户端。但是全局客户端默认只允许 5 个并发Socket
连接,当某一个时刻HTTP
客户端请求创建过多,超过这个数字时,就会发生socket hang up
错误。解决方法也很简单,通过http.globalAgent.maxSockets
属性把这个数字改大些即可。另外,https
模块遇到这个问题时也一样通过 https.globalAgent.maxSockets 属性来处理。
官方文档:http://nodejs.cn/api/url.html
完整的URL
的各组成部分:
我们可以使用.parse
方法来将一个URL
字符串转换为URL
对象,示例如下。
使用NodeJS
编写前端工具时,操作得最多的是文本文件,因此也就涉及到了文件编码的处理问题。我们常用的文本编码有UTF8
和GBK
两种,并且UTF8
文件还可能带有BOM
。在读取不同编码的文本文件时,需要将文件内容转换为JS
使用的UTF8
编码字符串后才能正常处理。
BOM
用于标记一个文本文件使用Unicode
编码,其本身是一个Unicode
字符("\\uFEFF")
,位于文本文件头部。在不同的Unicode
编码下,BOM
字符对应的二进制字节如下:
官方文档:http://nodejs.org/api/path.html
操作文件时难免不与文件路径打交道。NodeJS
提供了path
内置模块来简化路径相关操作,并提升代码可读性。以下分别介绍几个常用的API
。
path.normalize
将传入的路径转换为标准路径,具体讲的话,除了解析路径中的.与..外,还能去掉多余的斜杠。如果有程序需要使用路径作为某些数据的索引,但又允许用户随意输入路径时,就需要使用该方法保证路径的唯一性。
官方文档:http://nodejs.org/api/stream.html
当内存中无法一次装下需要处理的数据时,或者一边读取一边处理更加高效时,我们就需要用到数据流。NodeJS
中通过各种Stream
来提供对数据流的操作。
以文件拷贝为例,我们可以为数据来源创建一个只读数据流:
var rs = fs.createReadStream(pathname)
rs.on('data', function (chunk) {
doSomething(chunk)
})
rs.on('end', function () {
cleanUp()
})
- /home/user/workspace/node-echo/ # 工程目录
- bin/ # 存放命令行相关代码
node-echo
+ doc/ # 存放文档
- lib/ # 存放API相关代码
echo.js
- node_modules/ # 存放三方包
+ argv/
+ tests/ # 存放测试用例
package.json # 元数据文件
README.md # 说明文件