我是一名刚刚接触Nodejs有3周左右的新手小白,经历了迷茫、困顿、挫败以后终于对Nodejs有了基础掌握,算是刚刚入门。
我想把我目前所掌握的Nodejs相关知识写成文章,巩固本身所学、为其余新手小白提供一点点Nodejs入门帮助。javascript
关于个人知识背景,补充几点:css
言归正传,小白教小白入门Nodejs正式开始...html
免责声明:本文中的知识点、讲解内容仅仅是我我的目前的理解,不敢保证100%都是正确的,仅供参考,同时欢迎批评指正。前端
Nodejs官方对本身的介绍很是简单——Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。java
Nodejs与网页JS的区别:node
JS和Nodejs虽然都遵循ECMAScript标准(都是Javascript),可是运行环境不一样,拥有的API不一样,因此他们功能相差很大。python
相同点:
对于一些基础类型语法,好比String、Array、Date,ES6新语法等,JS和Nodejs是没有区别的。git
不一样点:
好比JS能够操做网页元素(好比修改CSS样式),拥有浏览器中的windows对象、拥有鼠标事件等,Nodejs都不具备这些——因此JS是前端。
一样Nodejs能够操做系统底层文件,建立服务监听,而JS都不具备这些——因此Nodejs是后端。github
Nodejs的优点:
相对其余编程语言,好比Java/.Net/python,这些语言可以作的事情很是很是多,好比开发桌面软件或APP,Web服务端只是他们众多应用领域中的其中一种,而Nodejs从诞生到如今惟一用途就是Web服务端。正则表达式
那些语言对于计算能力要求比较高,属于CPU(或GPU)操做频繁,也称“CPU密集”,(好比用Python写大数据处理、人工智能、区块链等,对于计算量要求比较大),而Web服务对数据计算量少,但对I/O(文件读写)操做频繁,也称“I/O密集”,恰好正式Nodejs的优点。
Nodejs是I/O异步非阻塞:
能够答应干不少活,至于何时干完不能保证,可是答应过的就必定会去干,只是早晚而已。
拿比喻来讲,异步非阻塞至关于一个饭店里的店小二,来一位客人就记录他点的菜,并把所点的菜名传递给后厨,接着就能够接待下一位客户,至于后厨何时作好店小二不能保证,可是若是后厨把饭菜作好后,店小二可以精准的把饭菜送到对应客人的桌子上。
与之对应的是“I/O阻塞”,好比Apache服务器:
答应一件事,必须作完了才能够去作另一件事,若是须要处理不少事就会一件件堆积“阻塞”起来。
还拿饭店店小二来比喻,就是来一个客人,这个店小二记录他点的菜,而后把所点的菜名传递给后厨,而后很是耐心等待后厨作菜(这个时候又来了一位顾客,这个店小二也不去理会新客人,依然守在后厨门口耐心等待第一位客人的菜是否作好),时间过去了10分钟,店小二和第二位顾客没有任何沟通,第二位客人一脸懵,跟着店小二一块儿等待。当后厨把第一位客人的饭菜作好,店小二把饭菜送到第一位客户桌子上,说了一句:对您的服务已完成,我终于能够去接待第二位顾客了。这时候才去找第二位顾客,询问你吃点什么?
想象一下上面“非阻塞”和“阻塞”对应的饭店场景,在现实生活中哪一个更合理?哪一个饭店能更好生存下去?
若是不能理解异步非阻塞,学Nodejs会很艰难。会被各类状况下的箭头函数弄懵,因此上面就多啰嗦了几句。
听说,Nodejs性能是Php的80倍。 Php才是最好的语言。
软件下载地址:http://nodejs.cn/download/
根据本身电脑系统选择对应版本下载,并一路下一步安装。
VSCode简介:全称Visual Studio Code,是微软推出的一款免费软件开发IDE。
优秀的IDE有不少,好比HBuilderX、Sublime等,为何Nodejs开发首选IDE是VSCode?
选择VSCode的3个理由:
一、TypeScript是微软开发的(虽然Nodejs入门时还用不到,但未来必定会用到),VSCode也是微软开发的,毫无疑问VSCode是支持TypeScript最好IDE。
二、VSCode内置DOS操做窗口,调试Nodejs很是方便。
三、VSCode插件扩展众多,自己仍是免费软件。
VSCode安装:
软件下载地址:https://code.visualstudio.com...
根据本身电脑系统选择对应版本下载,并一路下一步安装。
NPM是随同NodeJS一块儿安装的包管理工具,除了Nodejs默认自带的包(类模块),平常开发会须要大量别人封装好的包(类模块),这些每次都须要从国外服务器上下载,为了快速下载和安装,可使用淘宝国内的npm镜像:cnpm。
关于cnpm的具体介绍、安装方法,使用方法,参见其官网:https://npm.taobao.org/
小结:
至此,已经完成了Nodejs开发环境的安装,对Nodejs有了一点点初步印象。在正式开始学习Nodejs以前,须要一些计算机网络通讯基础知识,如今进入下一章。
如下每个知识点均可以无限展开来说,可是做为Nodejs入门的知识储备,这里只讲最基础的那个点,够入门用便可。
协议规定:任何一条网络传输消息(也称报文)都必须由:消息头(字符串形式) + 消息内容主体(二进制数据) 两部分构成。
补充说明:
先后端传递数据时,须要写清楚是以"GET"仍是"POST"方式发送,这里面的区别是什么?其实就是告诉对方:
若是是"GET"方式,代表我(发送方)把数据写在了“消息头”里,你(接收方)记得从“消息头”里获取。 数据传递表现形式为:http://www.xx.com/xx?name=puxiao&qq=78657141,这类数据比较简单,信息量比较小。 若是是"POST"方式,代表我(发送方)把数据写在了“消息主体”里,你(接收方)记得从“消息主体”里获取。 数据不会在网址中出现,传递数据内容较大,好比上传一张图片或获取一个网页。
虽然本篇入门为“静态资源服务器”,不牵扯“动态数据交互”,可是了解上面知识点很是重要。
浏览器与服务器约定好的缓存依据,一共有4种方式:强制缓存(2种) + 协商缓存(2种)
强制缓存的2种方式:
一、Expires (到期时间,字符串形式(GMT或UTC形式))
服务端返回信息头对应为:res.setHeader['Expires',(new Date(Date.now() + 3600)).toGMTString()];//将当前服务器时间+3600毫秒,产生新的日期时间,并将该时间转换为GMT字符串形式
缺点:若客户电脑时间不正确,或不一样时区,不能保证必定和服务器时间匹配,可结合Cache-Control使用。
二、Cache-Control (有效期为多少秒)
服务端头返回信息头对应为:res.setHeader['Cache-Control','max-age=60'];//告诉浏览器60秒内不用询问我,可直接使用本地缓存
补充说明:
将秒数设置比较小,可进行数据缓存策略,好比某一块数据10秒内就使用本地缓存。
将描述设置比较大(好比N天),可进行静态文件缓存策略,好比某图片或css文件N天以内均可使用本地缓存。
协商缓存的2种方式:
一、Modified (修改时间,字符串形式(GMT或UTC形式)):服务端Last-Modified/客户端If-Modified-Since
服务端获取某文件的修改时间代码为:stats.mtime.toGMTString(); 将服务器获取文件的修改时间与客户端文件修改时间进行对比,若相同则返回304,若不相同则发送新的文件给客户端
特别提醒:在req.headers中,默认将浏览器消息头中的大写改成了小写,因此正确获取应该是res.headers['if-modified-since']。
二、Etag (电子戳):服务端Etage/客户端If-None-Match
1.能够简单采用 文件大小 + 文件修时间,将获得字符串值约定为电子戳(可针对此值进行md5换算以便更加精准) 2.将服务器获得文件电子戳与客户端文件电子戳进行对比,若相同则返回304,若不相同则发送新的文件给客户端
补充说明:
更多状态码可查看:https://developer.mozilla.org...
正则表达式、箭头函数、ES6新语法都属于JS的基础知识,若是你不熟悉,建议先百度了解。
在学习Nodejs以前,确定见过听过各类全栈名词,虽然Nodejs入门还都用不到这些框架和技术,可是先了解一下他们是作什么的,作到心中有数,当看到别人说这些名词时,不慌不乱。
如下关于计算机的进程、线程名词解释、CPU任务分配原则,若不感兴趣或理解不了(由于我也仅仅是有一个很大概、粗略的认识,若是说错了敬请见谅 ),能够跳过。
进程:假如电脑上目前运行的程序有Photoshop、QQ、Nodejs,每个程序都对应一个进程,一个CPU会给每个进程分配必定的内存。
线程:一个进程中能够有多个线程,全部这些线程共享这个进程中的资源(内存、计算能力),若是其中一个线程发生错误则会影像整个进程。
单线程:一个进程中只有一个线程(如Nodejs)
缺点:一瞬间只能作一件事
优势:进程中就本身一个线程,精力更加集中(彻底拥有本身所属的进程拥有的所有内存资源调度)
单进程多线程:一个进程中可建立多个线程(如Apache)
优势:能够经过创造多个线程,一瞬间能够同时作多件事情
缺点:CPU分配给本进程的资源是固定的,因此可以建立线程的数量是有限的,而且由于每一个线程共享一个进程,因此如有一个线程出问题卡住了,会影响其余线程,进而影响整个进程。
“Nodejs自己为单进程单线程”,听上去没有多线程强大,可是Nodejs说本身是单线程,真的是这样吗?
还记得开头是怎么介绍Nodejs的吗?“Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。”
没错,Nodejs背后靠山是Chrome V8,而这个V8在调用系统底层进行I/O操做时是多线程的,进而能够约等于说Nodejs是"多线程"的。(背靠V8好乘凉)。
等一等!以上关于进程、线程、内存资源分配都是在电脑单核CPU的前提下,那若是电脑是多核CPU,那是又是什么状况呢?
多核CPU处理进程,任务分配原则:
假如电脑(服务器也是电脑)是4核处理器:A核、B核、C核、D核,那么平时电脑是怎么处理分配资源给不一样进程呢?
好比电脑上恰好运行了4个程序(进程):PS、QQ、迅雷、Nodejs。
电脑怎么安排任务?会不会是让A核来处理PS,B核来处理QQ,C核来处理迅雷,D核来处理Nodejs?
答案是不会!
现实的状况很残酷(能者多劳原则),为了整体性能,电脑的任务安排是:
A核你来处理PS、你来处理QQ,你来处理迅雷,你来处理Nodejs。
B核、C核、D核大家都歇着,何时A核实在忙不过来了,B核你再上!
固然上面论述只是作了适当夸张,实际中还会加入别的平衡策略。
默认Nodejs是单进程,即便电脑上是多核CPU,也只能使用其中一个CPU而已。
可是能够经过Nodejs自带的类模块:cluster(集群)来实现多进程(实际上是子进程,每一个子进程里依然是一个单线程),几核CPU能够分裂出几个子进程,充分利用好多核CPU的性能。
在Nodejs开发过程当中,咱们须要不断引用别人编写好的代码包。
关于NPM更多中文介绍,能够访问:https://www.npmjs.cn
再次强调一下,npm代码包都存放在国外服务器上,咱们为了方便最好使用淘宝的npm国内镜像服务,即cnpm。
NPM引入(安装)第三方代码包的几个知识点:
其中--save和--save-dev的区别略微有一点绕,若是不明白能够百度或者暂时先放一下,不影响本文后续编程。
本篇入门文章讲的“建立静态资源服务器”所用到的代码模块,都是Nodejs内置的(由于这些模块太基础、使用太频繁,因此Nodejs内置了这些模块),只须要引入2个别人的代码包。
第1个:@types/node
默认在VSCode里建立的项目只有网页JS代码提示,缺乏Nodejs的代码提示(没有代码提示不表明不能正常运行),因此在本次代码示例中,咱们须要引入一个叫“@types/node”的代码包。
关于@types/node,可访问官方地址(英文):https://www.npmjs.com/package...
官方提供的安装示例:
npm install --save @types/node
1. install 可简写为 i,即 npm i --save @types/node 2. npm 可替换为 cnpm,即:cnpm i --save @types/node
有些时候,若是使用cnpm安装不成功(极少状况),只能用npm,为了下载代码包快一些,咱们能够经过新增一个参数,继续使用淘宝国内镜像文件。
上述安装代码可修改成:
npm i --save @types/node --registry=https://registry.npm.taobao.org
第2个:art-template(模板引擎)
当返回某个目录内的资源列表式,经过这个模板引擎生成对应页面。
Nodejs模板引擎有很是多种,常见的有:handlebars、jade、ejs、art-template
本次咱们选择使用art-template,详细使用方法请访问:https://aui.github.io/art-tem...
拥有面对对象编程经验的人都知道,一个复杂的项目必定须要被拆分红多个小模块,每一个小模块又会继续往下划分不一样的类,每个类拥有本身的属性、方法。
目前不管网页JS仍是Nodejs,都不是传统的面对对象语言(尽管ES6之后已经很是进步了、Typescript就是为了弥补这个缺憾而诞生的,Typescript模拟出了相似面对对象的编程写法,但仅仅是模拟并非原生),没法提供标准意义上的“类”。
因而有了Commonjs模块化这个概念(本文一直称呼这种代码形式为类模块或代码模块),详细介绍能够参考:http://javascript.ruanyifeng....
类模块实现方法是经过内置的module类的exports属性,来对外声明(提供)本身内部属性和方法的调用。
这里的某个类模块其实就是一个编写好的.js文件。
调用方则经过 const xx = require('./xxx.js') 来将xxx.js模块引入到本身内部(其余面对对象语言通常都采用import xxx的形式引入)。
如下为我的对Commonjs模块化的一个理解:
仍是以其余面对对象语言(好比jave、AS3)来和Commonjs模块化作对比。
其余面对对象语言的属性和类,在声明以前都会有访问修饰符,好比public(公开)、private(私有)、protect(仅子类可见),static(归属于类的,而非实例的)。
Commonjs模块化的exports表现出来的,特别像其余语言中的“public static”这个概念。
被引入的类模块(代码模块),“不须要实例化(也没办法实例化)”,使用起来相似“面对对象中类的公开静态属性或方法”。
以上仅为我我的理解,当我把module.exports理解为 public static 后,我对于Commonjs模块化一会儿清晰了不少。
想学任何一门编程语言,最应该先看、多看、反复看的就是他们的官方帮助文档,Nodejs中文文档请访问:http://nodejs.cn/api/
内置代码模块太多,做为刚开始入门,没有必要和精力所有看完。
本文讲的建立静态资源服务器,只须要看如下几个点便可:
http(建立http server服务) :http://nodejs.cn/api/http.html
仅看http类模块整体介绍和http.createServer方法便可
path(资源路径相关) :http://nodejs.cn/api/path.html
全看
fs(文件系统) :http://nodejs.cn/api/fs.html
fs整体介绍、fs.stat方法、fs.Stats类、fs.readdir方法(读取某个文件夹的内容)、fs.createReadStream(以流的方式读取某个文件)
这里读取文件咱们不使用fs.readFile方法,由于该方法只有把文件所有读取完成后才会触发后续事件,不像createReadStream方法,以流的形式读取(读取一点就输出一点)。
module(内置模块,即Commonjs模块化) :http://nodejs.cn/api/modules....
仅看module.exports便可
process(内置进程类模块) :http://nodejs.cn/api/process....
仅看process.cwd()便可。
zlib(压缩) :http://nodejs.cn/api/zlib.html
仅看zlib整体介绍、zlib.gzip方法和zlib.createGzip方法、
通常网页有3中压缩方式:gzip、deflate、br,这3种压缩方式在zlib中的使用方法相似,只是类的名字不同而已。
这3个用法相似:zlib.gzip、zlib.deflate、zlib.brotliCompress(注意不是zlib.br)
这3个用法相似:zlib.createGzip、zlib.createDeflate、zlib.createBrotliCompress(注意不是zlib.createBr)
Nodejs目前一共有41个内置类模块,而上面已列出的有6个模块,耐心看完,后续代码照着再反复敲几遍,真的能够达到Nodejs入门的标准了。
---前面铺垫了那么多,终于该进入项目正式内容了---
本次开发的项目名称为“建立本地静态资源服务器”,咱们分析一下这个Nodejs项目须要知足的业务内容。
从用户的角度讲,他的操做流程是:
1. 在浏览器地址栏中输入本地请求地址,如http://127.0.0.1:8899 摁回车 2. 网页显示出根目录下的静态资源内容:各类文件(如.html、.jpg、.js等)和文件夹 3. 若点击某个文件,则经过网页打开此文件 4. 若点击某个文件夹,则显示该文件夹内的资源:各类文件(如.html、.jpg、.js等)和文件夹
须要考虑的意外状况有:
从后台的角度讲,他的业务流程是:
1. 建立一个本地http服务,静静开始等待用户访问并为其提供服务 2. 侦听到用户的http请求,分析url地址获取到请求资源地址,并将该地址转化为本地资源地址 3. 尝试获取该资源信息 4. 若发现本地不存在该资源,向用户发送404,告知用户该资源不存在 5. 若发现本地该资源存在,则判断该资源是文件仍是文件夹 6. 如果文件,则将该文件内容发送给用户 7. 如果文件夹,则将该文件夹内资源信息,整理发送给用户
须要额外考虑的几点:
根据上述的需求分析,能够大致梳理出后端业务执行流程,以下图:
注意,当你访问任意某个资源时,浏览器会额外多一条针对站标favicon.ico文件的请求,咱们忽略这个便可。
以windows系统为例,假设咱们要将本项目全部源代码存放在F:\node\hello中。
项目初始化的操做步骤是:
此致项目Nodejs初始化第一阶段完成,下一步开始第二阶段:引入咱们须要使用的2个第三方类模块
项目初始化后,紧接着要进行VSCode调试配置,操做步骤及流程,以下图所示:
调试配置设置:
至此,终于能够开始编写代码了。
这里直接列出项目结构:
项目结构说明:
./config/config.js 用来存放一些基础配置常量,好比要建立服务的端口889九、哪些格式的文件须要被压缩等
./config/mimetype.js 用来存放服务器支持的文件格式以及该文件格式对应消息头部中的Content-Type
./view/404.html 定义好的404页面
./view/dir.html 定义好的目录页面模板
./cache.js 用来处理缓存相关的类模块
./compress.js 用来处理压缩相关的类模块
./index.js 项目启动js,用来建立http服务,并根据用户url请求得到对应资源在服务器的绝对路径
./route.js 整个项目核心类模块,根据请求资源路径进行一系列后续操做
不少服务端框架都有“路由”这个概念,这里的route.js的做用就是将资源请求进行下一步分配(判断)并进行回应。
这里就不针对每一个js类模块展开来说了,你能够直接下载个人项目源码进行分析。
项目源文件下载地址:https://pan.baidu.com/s/1Chbg... 密码:g4yy
在VSCode中进行调试,正常运行结果以下:
为啥不展开来说?每一个类模块具体都是什么代码,具体实现了哪些功能不该该是本篇文章的核心吗?
我是这样认为的:
我但愿你必定先把官方帮助文档看明白、而后再看我提供的源码、而后再本身从头写一遍。
这样你才能真正入门,才能真正领悟到Nodejs的开发编写思路。
若你真的真的基础太差,理解不了,可私信给我。
Nodejs思想,网络通讯知识才是最难理解和须要学习的那部分,再次强调一下,那些具体的代码仅仅是一个表象而已。
但愿你养成一个好的学习、解决问题的方法:看官方文档、在思否/掘金上搜索或提问、或百度一下。
小白教小白Nodejs入门是我花了2天时间写出来的第一篇Nodejs技术分享文章,感谢你的阅读。
明天就是2020年1月1日,咱们一块儿加油!