Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

小白教小白入门Nodejs——以创建本地静态资源服务器为例子(全文1.3万字)

Puxiao 2020-01-01 08:37:05 阅读数:37 评论数:0 点赞数:0 收藏数:0

前言

我是一名刚刚接触Nodejs有3周左右的新手小白,经历了迷茫、困顿、挫败之后终于对Nodejs有了基础掌握,算是刚刚入门。
我想把我目前所掌握的Nodejs相关知识写成文章,巩固自己所学、为其他新手小白提供一点点Nodejs入门帮助。

关于我的知识背景,补充几点:

  1. 我原本是一名网页设计师,无任何后台编程经验,是最近几个月才自学的前端(Http5+CSS3+JS),对VUE、Webpack等最新的前端技术栈只是简单了解、并无任何实际经验。
  2. 在我成为网页设计师更早之前(大概10年前),我曾经是一名Flash动画设计与开发人员,10年前的AS3的编程经验为我现在学习JS和Nodejs提供了非常大的帮助。因为AS3是面对对象语言,所以我对类、面对对象、设计模式这些并不陌生。

言归正传,小白教小白入门Nodejs正式开始...

免责声明:本文中的知识点、讲解内容仅仅是我个人目前的理解,不敢保证100%都是正确的,仅供参考,同时欢迎批评指正。

环境搭建:Nodejs + VSCode + CNPM

1. Nodejs简介与安装

Nodejs官方对自己的介绍非常简单——Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。

Nodejs与网页JS的区别

  1. 网页中的JS,是运行在浏览器环境下的JavaScript,他实际上是:ECMAScript标准 + WebAPI(DOM操作+Web事件)
  2. Nodejs是运行在Chrome V8环境下的Javascript,他实际上是:ECMAScript标准 + Nodejs API(Chrome V8提供的系统底层操作)

JS和Nodejs虽然都遵循ECMAScript标准(都是Javascript),但是运行环境不同,拥有的API不同,所以他们功能相差很大。

网页JS与Nodejs的区别

相同点:
对于一些基础类型语法,比如String、Array、Date,ES6新语法等,JS和Nodejs是没有区别的。

不同点:
比如JS可以操作网页元素(比如修改CSS样式),拥有浏览器中的windows对象、拥有鼠标事件等,Nodejs都不具有这些——所以JS是前端。
同样Nodejs可以操作系统底层文件,创建服务监听,而JS都不具有这些——所以Nodejs是后端。

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才是最好的语言。

Nodejs安装:

软件下载地址:http://nodejs.cn/download/
根据自己电脑系统选择对应版本下载,并一路下一步安装。

VSCode简介与安装

VSCode简介:全称Visual Studio Code,是微软推出的一款免费软件开发IDE。

优秀的IDE有很多,比如HBuilderX、Sublime等,为什么Nodejs开发首选IDE是VSCode?

选择VSCode的3个理由:
1、TypeScript是微软开发的(虽然Nodejs入门时还用不到,但将来一定会用到),VSCode也是微软开发的,毫无疑问VSCode是支持TypeScript最好IDE。
2、VSCode内置DOS操作窗口,调试Nodejs非常方便。
3、VSCode插件扩展众多,本身还是免费软件。

VSCode安装
软件下载地址:https://code.visualstudio.com...
根据自己电脑系统选择对应版本下载,并一路下一步安装。

CNPM简介与安装

NPM是随同NodeJS一起安装的包管理工具,除了Nodejs默认自带的包(类模块),日常开发会需要大量别人封装好的包(类模块),这些每次都需要从国外服务器上下载,为了快速下载和安装,可以使用淘宝国内的npm镜像:cnpm。

关于cnpm的具体介绍、安装方法,使用方法,参见其官网:https://npm.taobao.org/

小结:
至此,已经完成了Nodejs开发环境的安装,对Nodejs有了一点点初步印象。在正式开始学习Nodejs之前,需要一些计算机网络通信基础知识,现在进入下一章。

背景知识:学习Nodejs前需要了解的几个知识点

以下每一个知识点都可以无限展开来讲,但是作为Nodejs入门的知识储备,这里只讲最基础的那个点,够入门用即可。

HTTP传输协议

协议规定:任何一条网络传输消息(也称报文)都必须由:消息头(字符串形式) + 消息内容主体(二进制数据) 两部分构成。

补充说明:

  1. 一条消息可以没有消息主体,但必须有消息头。
  2. 消息头包含:固定名称的字段(约定好的) + 用户自定义的字段(可以有,也可以没有)

前后端传递数据时,需要写清楚是以"GET"还是"POST"方式发送,这里面的区别是什么?其实就是告诉对方:

如果是"GET"方式,表明我(发送方)把数据写在了“消息头”里,你(接收方)记得从“消息头”里获取。
数据传递表现形式为:http://www.xx.com/xx?name=puxiao&qq=78657141,这类数据比较简单,信息量比较小。
如果是"POST"方式,表明我(发送方)把数据写在了“消息主体”里,你(接收方)记得从“消息主体”里获取。
数据不会在网址中出现,传递数据内容较大,比如上传一张图片或获取一个网页。

虽然本篇入门为“静态资源服务器”,不牵扯“动态数据交互”,但是了解上面知识点非常重要。

关于浏览器缓存

浏览器与服务器约定好的缓存依据,一共有4种方式:强制缓存(2种) + 协商缓存(2种)

强制缓存的2种方式:

1、Expires (到期时间,字符串形式(GMT或UTC形式))

服务端返回信息头对应为:res.setHeader['Expires',(new Date(Date.now() + 3600)).toGMTString()];//将当前服务器时间+3600毫秒,产生新的日期时间,并将该时间转换为GMT字符串形式

缺点:若客户电脑时间不正确,或不同时区,不能保证一定和服务器时间匹配,可结合Cache-Control使用。

2、Cache-Control (有效期为多少秒)

服务端头返回信息头对应为:res.setHeader['Cache-Control','max-age=60'];//告诉浏览器60秒内不用询问我,可直接使用本地缓存

补充说明:
将秒数设置比较小,可进行数据缓存策略,比如某一块数据10秒内就使用本地缓存。
将描述设置比较大(比如N天),可进行静态文件缓存策略,比如某图片或css文件N天之内都可使用本地缓存。

协商缓存的2种方式:

1、Modified (修改时间,字符串形式(GMT或UTC形式)):服务端Last-Modified/客户端If-Modified-Since

服务端获取某文件的修改时间代码为:stats.mtime.toGMTString();
将服务器获取文件的修改时间与客户端文件修改时间进行对比,若相同则返回304,若不相同则发送新的文件给客户端

特别提醒:在req.headers中,默认将浏览器消息头中的大写改为了小写,所以正确获取应该是res.headers['if-modified-since']。

2、Etag (电子戳):服务端Etage/客户端If-None-Match

1.可以简单采用 文件大小 + 文件修时间,将得到字符串值约定为电子戳(可针对此值进行md5换算以便更加精准)
2.将服务器得到文件电子戳与客户端文件电子戳进行对比,若相同则返回304,若不相同则发送新的文件给客户端

补充说明:

  1. 强制缓存不需要向服务器发送请求,浏览器自己默默从本地缓存中读取,文件头信息为304
  2. 协商缓存需要向服务器发送请求,服务器根据判断来决定是否可以返回304
  3. 若当前地址为整个页面入口,则不响应上述缓存机制,上述缓存机制只针页面入口中引用的文件或F5刷新模式(非地址栏里敲回车进行的访问)。
  4. 理论上直接地址栏敲地址摁回车访问某个文件是不会产生缓存的。但平时直接访问某个文件依然为缓存是因为DNS的缓存而不是服务器的缓存。
  5. 若浏览器请求头中Cache-Control: no-cache,此时请求信息头中不会包含其他3中缓存头信息,因此服务器匹配任何缓存信息头都会失败,则会发送最新文件给客户端(返回时依然包含缓存信息头,客户端可进行缓存)
  6. 若浏览器请求头中Cache-Control: no-store,此时客户端和服务器都不会进行缓存相关操作。

常见网页信息状态码(响应码)

  • 200 新的、正常的、成功的状态码
  • 304 缓存的状态码(仅有消息头,不含消息主体)
  • 404 请求失败,请求所希望得到的资源未被在服务器上发现

更多状态码可查看:https://developer.mozilla.org...

Nodejs常用到的DOS命令

  • 盘符+: 进入某硬盘分区,例如进入F盘为 f:
  • cd xxx 进入 xxx文件夹
  • cd .. 返回上一级文件夹
  • mkdir+名称 新建文件夹
  • cls 清除已有文字信息(清屏)
  • code . 启动VSCode并打开当前文件夹
  • Ctr+C 结束当前执行中的命令(或输入exit)

正则表达式、箭头函数、ES6新语法

正则表达式、箭头函数、ES6新语法都属于JS的基础知识,如果你不熟悉,建议先百度了解。

全栈名词解释

在学习Nodejs之前,肯定见过听过各种全栈名词,虽然Nodejs入门还都用不到这些框架和技术,但是先了解一下他们是做什么的,做到心中有数,当看到别人说这些名词时,不慌不乱

  • Vue、React、Angular:用来做前端数据页面渲染(与之对应的是后端模板引擎SSR)
  • Koa、Express、Nest、Egg:基于Nodejs二次开发的服务框架
  • MySQL、MongoDB:数据库
  • Typescript:微软推出的,针对JS语言的一种“包装”,甚至可以理解为“语法糖”,让JS以面对对象方式进行编程
  • Webpack:一种代码资源打包工具,减小代码和图片数量与体积
  • Eslint:一种代码约定格式协议,方便整个项目开发人员以相同的风格来进行编写,控制代码可读性、约束部分代码可执行性
  • Sass、Less:针对CSS样式的一种扩展处理方式
  • SSR:服务端渲染,服务端根据后台数据,通过模板引擎,组织生成一个网页文件返回给前台(常见的模板引擎有Handlebars、腾讯技术牛人写的art-template等)

进程线程名词解释:进程、线程、单线程、多线程、多核CPU

以下关于计算机的进程、线程名词解释、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简介与操作

在Nodejs开发过程中,我们需要不断引用别人编写好的代码包。

  • 这些代码包都是全球Nodejs开发者通过NPM官网https://www.npmjs.com,加入到(贡献给)npm公共代码资源库里的。
  • 其中A开发者编写的代码里可能引用了B开发者(其他开发者)的代码包,而B开发者的代码里有引用了C开发者的代码包。当你的项目需要使用A开发者的代码包时,理论上你还需要引入B代码包、C代码包,这样会非常麻烦。为了简化你的代码引用这部分工作,于是有了“npm”这个代码包管理器。

关于NPM更多中文介绍,可以访问:https://www.npmjs.cn

再次强调一下,npm代码包都存放在国外服务器上,我们为了方便最好使用淘宝的npm国内镜像服务,即cnpm

NPM引入(安装)第三方代码包的几个知识点

  • npm 可替换为 cnpm
  • install 可简写为 i
  • -g 表示全局安装(其他任何项目都可使用)
  • --save 本项目需使用(代码包会自动下载到你项目的node_modules文件夹中)
  • --save-dev 仅供本项目本地使用(请注意是“本地使用”,如果别人通过“npm install --production”也想创建一份你的项目,他创建的时候是不包含 --save-dev 引用的代码包的)

其中--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...

Commonjs模块化概念解释

拥有面对对象编程经验的人都知道,一个复杂的项目一定需要被拆分成多个小模块,每个小模块又会继续往下划分不同的类,每一个类拥有自己的属性、方法。

目前无论网页JS还是Nodejs,都不是传统的面对对象语言(尽管ES6以后已经非常进步了、Typescript就是为了弥补这个缺憾而诞生的,Typescript模拟出了类似面对对象的编程写法,但仅仅是模拟并不是原生),无法提供标准意义上的“类”。

于是有了Commonjs模块化这个概念(本文一直称呼这种代码形式为类模块或代码模块),详细介绍可以参考:http://javascript.ruanyifeng....

类模块实现方法是通过内置的module类的exports属性,来对外声明(提供)自己内部属性和方法的调用。
这里的某个类模块其实就是一个编写好的.js文件。
调用方则通过 const xx = require('./xxx.js') 来将xxx.js模块引入到自己内部(其他面对对象语言一般都采用import xxx的形式引入)。

  • ./ 表示同一目录(引入自己写的类模块必须使用./或者../)
  • 如果不写./则表示引入的类来自内置类
  • 想引入的xxx.js中的后缀.js可以省略掉不写
  • 通常引入写法为:const xx = require('./xxx') 即可。

以下为个人对Commonjs模块化的一个理解:

还是以其他面对对象语言(比如jave、AS3)来和Commonjs模块化做对比。

其他面对对象语言的属性和类,在声明之前都会有访问修饰符,比如public(公开)、private(私有)、protect(仅子类可见),static(归属于类的,而非实例的)。

Commonjs模块化的exports表现出来的,特别像其他语言中的“public static”这个概念。
被引入的类模块(代码模块),“不需要实例化(也没办法实例化)”,使用起来类似“面对对象中类的公开静态属性或方法”。

以上仅为我个人理解,当我把module.exports理解为 public static 后,我对于Commonjs模块化一下子清晰了很多。

本项目使用的Nodejs类模块

想学任何一门编程语言,最应该先看、多看、反复看的就是他们的官方帮助文档,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://127.0.0.1:8899/puxiao或http://127.0.0.1:8899/puxiao/index.html
  2. 用户在请求某资源时,给该资源地址上增加某些参数,而我们此次为静态资源服务器,如何应对?例如:https://127.0.0.1:8899/logo.png?v=1

从后台的角度讲,他的业务流程是

1. 创建一个本地http服务,静静开始等待用户访问并为其提供服务
2. 侦听到用户的http请求,分析url地址获取到请求资源地址,并将该地址转化为本地资源地址
3. 尝试获取该资源信息
4. 若发现本地不存在该资源,向用户发送404,告知用户该资源不存在
5. 若发现本地该资源存在,则判断该资源是文件还是文件夹
6. 若是文件,则将该文件内容发送给用户
7. 若是文件夹,则将该文件夹内资源信息,整理发送给用户

需要额外考虑的几点:

  1. 若是文件,考虑是否告知用户使用本地缓存,还是真实发送该文件给用户
  2. 若是文件,考虑是否是受支持、可访问的文件格式,是否应该将本文件发送给客户(比如服务器设定不允许用户访问.mp4资源,那么即使服务器上有该资源,依然告知用户该资源不存在)
  3. 若是文件,考虑是否可以对该文件进行压缩,减小传输体积
  4. 若是文件夹,如何把文件夹内的文件列表信息生成对应的网页数据,以及如何压缩该网页数据

业务执行流程梳理

根据上述的需求分析,可以大体梳理出后端业务执行流程,如下图:
静态资源服务器业务执行流程.jpg

注意,当你访问任意某个资源时,浏览器会额外多一条针对站标favicon.ico文件的请求,我们忽略这个即可。

核心代码:类模块划分和实现

项目初始化

以windows系统为例,假设我们要将本项目所有源代码存放在F:\node\hello中。

项目初始化的操作步骤是

  1. 左下角系统 开始 -> cmd.exe -> 进入DOS命令窗口
  2. 通过DOS命令进入到F:\node\hello 目录中(可以使用mkdir命令新建对应文件夹,或者直接在电脑通过右键新建对应文件夹)
  3. (DOS命令可参考本文中的“背景知识:学习Nodejs前需要了解的几个知识点 -> Nodejs常用到的DOS命令”)
  4. 执行初始化:npm init,之后会进行一系列设置询问,并最终初始化完成。若不理解这一步,可以百度“npm init”,有大量相关介绍文章。
  5. 若想跳过中间的各种询问,可将初始化代码换成:npm init -y (使用默认值)

此致项目Nodejs初始化第一阶段完成,下一步开始第二阶段:引入我们需要使用的2个第三方类模块

  1. 引入@types/node:cnpm i --save @types/node 尽管引用的是淘宝国内代码库镜像,但是依然需要几秒钟的下载时间,请等待
  2. 引入art-template:cnpm i --save art-template 安装完成后,至此项目初始化完成
  3. 执行:code . 让VSCode打开本目录(或者直接打开VSCode,选择打开项目文件夹)。

VSCode调试配置

项目初始化后,紧接着要进行VSCode调试配置,操作步骤及流程,如下图所示:

VSCode调试配置.jpg

调试配置设置

  1. 默认项目启动文件为index.js。可以根据自己喜好修改,比如改为app.js。
  2. 默认调试每次都启动默认js,也可以新增自己的调试方式,比如修改launch.json,将configurations的值(默认数组里就只有一种调试模式),复制新增一份,并将其中的name值修改为"当前文件"、program值修改为"${file}",该模式下可以启动当前js文档,方便调试使用。

VSCode_调试设置.jpg

至此,终于可以开始编写代码了。

类模块划分及具体实现

这里直接列出项目结构

Nodejs创建静态服务器源码项目结构.jpg

项目结构说明
./config/config.js 用来存放一些基础配置常量,比如要创建服务的端口8899、哪些格式的文件需要被压缩等
./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中进行调试,正常运行结果如下:

项目调试运行结果.jpg

为啥不展开来讲?每个类模块具体都是什么代码,具体实现了哪些功能不应该是本篇文章的核心吗?
我是这样认为的

  1. 我相信读这篇文章的人,是拥有一定网页JS源码编写能力的。
  2. 不同类模块里需要使用到的Nodejs方法和属性,我已经在本文上面部分中“Commonjs模块化概念解释、本项目使用的Nodejs类模块”中做了充分介绍。
  3. 遇到不懂的Nodejs属性和方法,可查阅官方帮助文档,那里有充分详细的介绍,我就没必要再复述一遍。
  4. 我代码里用的都是最基础的JS语法,整个代码业务推进的方式和本文上面“业务执行流程梳理”完全一致。
  5. 在返回给用户的数据中,关于如何设置状态码(200304404)、如何设置缓存,如何压缩等,均已经在本文上面部分中做了充分讲述。

我希望你一定先把官方帮助文档看明白、然后再看我提供的源码、然后再自己从头写一遍。
这样你才能真正入门,才能真正领悟到Nodejs的开发编写思路

若你真的真的基础太差,理解不了,可私信给我。

项目总结

  1. Nodejs的入门核心点在于新的知识储备(比如DOS命令)、Nodejs运行原理、网络通信协议、设计模式等,不在于某个Nodejs的具体语法使用。
  2. 这些语法具体去编写代码时,和写前台JS没有太大的差别,只不过这些新的函数是Nodejs API提供的而已。
  3. 前端JS不需要考虑性能(CPU和内存)、而后端性能、安全才是第一。一定要在思维方式上进行一个切换。
  4. 本文中的“Nodejs简介与安装”、“背景知识:学习Nodejs前需要了解的几个知识点”、“基础概念:Nodejs开发的基本知识”才是整个Nodejs入门核心,至于项目中的源码,那只是一些基础语法的组合而已。

Nodejs思想,网络通信知识才是最难理解和需要学习的那部分,再次强调一下,那些具体的代码仅仅是一个表象而已

后语

希望你养成一个好的学习、解决问题的方法:看官方文档、在思否/掘金上搜索或提问、或百度一下。

小白教小白Nodejs入门是我花了2天时间写出来的第一篇Nodejs技术分享文章,感谢你的阅读

明天就是2020年1月1日,我们一起加油!

版权声明
本文为[Puxiao]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000021456655