前言
我是一名刚刚接触Nodejs有3周左右的新手小白,经历了迷茫、困顿、挫败之后终于对Nodejs有了基础掌握,算是刚刚入门。
我想把我目前所掌握的Nodejs相关知识写成文章,巩固自己所学、为其他新手小白提供一点点Nodejs入门帮助。
关于我的知识背景,补充几点:
- 我原本是一名网页设计师,无任何后台编程经验,是最近几个月才自学的前端(Http5+CSS3+JS),对VUE、Webpack等最新的前端技术栈只是简单了解、并无任何实际经验。
- 在我成为网页设计师更早之前(大概10年前),我曾经是一名Flash动画设计与开发人员,10年前的AS3的编程经验为我现在学习JS和Nodejs提供了非常大的帮助。因为AS3是面对对象语言,所以我对类、面对对象、设计模式这些并不陌生。
言归正传,小白教小白入门Nodejs正式开始...
免责声明:本文中的知识点、讲解内容仅仅是我个人目前的理解,不敢保证100%都是正确的,仅供参考,同时欢迎批评指正。
环境搭建:Nodejs + VSCode + CNPM
1. Nodejs简介与安装
Nodejs官方对自己的介绍非常简单——Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
Nodejs与网页JS的区别:
- 网页中的JS,是运行在浏览器环境下的JavaScript,他实际上是:ECMAScript标准 + WebAPI(DOM操作+Web事件)
- Nodejs是运行在Chrome V8环境下的Javascript,他实际上是:ECMAScript标准 + Nodejs API(Chrome V8提供的系统底层操作)
JS和Nodejs虽然都遵循ECMAScript标准(都是Javascript),但是运行环境不同,拥有的API不同,所以他们功能相差很大。
相同点:
对于一些基础类型语法,比如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传输协议
协议规定:任何一条网络传输消息(也称报文)都必须由:消息头(字符串形式) + 消息内容主体(二进制数据) 两部分构成。
补充说明:
- 一条消息可以没有消息主体,但必须有消息头。
- 消息头包含:固定名称的字段(约定好的) + 用户自定义的字段(可以有,也可以没有)
前后端传递数据时,需要写清楚是以"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,若不相同则发送新的文件给客户端
补充说明:
- 强制缓存不需要向服务器发送请求,浏览器自己默默从本地缓存中读取,文件头信息为304
- 协商缓存需要向服务器发送请求,服务器根据判断来决定是否可以返回304
- 若当前地址为整个页面入口,则不响应上述缓存机制,上述缓存机制只针页面入口中引用的文件或F5刷新模式(非地址栏里敲回车进行的访问)。
- 理论上直接地址栏敲地址摁回车访问某个文件是不会产生缓存的。但平时直接访问某个文件依然为缓存是因为DNS的缓存而不是服务器的缓存。
- 若浏览器请求头中Cache-Control: no-cache,此时请求信息头中不会包含其他3中缓存头信息,因此服务器匹配任何缓存信息头都会失败,则会发送最新文件给客户端(返回时依然包含缓存信息头,客户端可进行缓存)
- 若浏览器请求头中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等)和文件夹
需要考虑的意外情况有:
- 用户直接在地址栏中,输入请求某个具体的文件或文件夹资源地址,而这个文件或文件夹并不存在,例如:http://127.0.0.1:8899/puxiao或http://127.0.0.1:8899/puxiao/index.html
- 用户在请求某资源时,给该资源地址上增加某些参数,而我们此次为静态资源服务器,如何应对?例如:https://127.0.0.1:8899/logo.png?v=1
从后台的角度讲,他的业务流程是:
1. 创建一个本地http服务,静静开始等待用户访问并为其提供服务
2. 侦听到用户的http请求,分析url地址获取到请求资源地址,并将该地址转化为本地资源地址
3. 尝试获取该资源信息
4. 若发现本地不存在该资源,向用户发送404,告知用户该资源不存在
5. 若发现本地该资源存在,则判断该资源是文件还是文件夹
6. 若是文件,则将该文件内容发送给用户
7. 若是文件夹,则将该文件夹内资源信息,整理发送给用户
需要额外考虑的几点:
- 若是文件,考虑是否告知用户使用本地缓存,还是真实发送该文件给用户
- 若是文件,考虑是否是受支持、可访问的文件格式,是否应该将本文件发送给客户(比如服务器设定不允许用户访问.mp4资源,那么即使服务器上有该资源,依然告知用户该资源不存在)
- 若是文件,考虑是否可以对该文件进行压缩,减小传输体积
- 若是文件夹,如何把文件夹内的文件列表信息生成对应的网页数据,以及如何压缩该网页数据
业务执行流程梳理
根据上述的需求分析,可以大体梳理出后端业务执行流程,如下图:
注意,当你访问任意某个资源时,浏览器会额外多一条针对站标favicon.ico文件的请求,我们忽略这个即可。
核心代码:类模块划分和实现
项目初始化
以windows系统为例,假设我们要将本项目所有源代码存放在F:\node\hello中。
项目初始化的操作步骤是:
- 左下角系统 开始 -> cmd.exe -> 进入DOS命令窗口
- 通过DOS命令进入到F:\node\hello 目录中(可以使用mkdir命令新建对应文件夹,或者直接在电脑通过右键新建对应文件夹)
- (DOS命令可参考本文中的“背景知识:学习Nodejs前需要了解的几个知识点 -> Nodejs常用到的DOS命令”)
- 执行初始化:npm init,之后会进行一系列设置询问,并最终初始化完成。若不理解这一步,可以百度“npm init”,有大量相关介绍文章。
- 若想跳过中间的各种询问,可将初始化代码换成:npm init -y (使用默认值)
此致项目Nodejs初始化第一阶段完成,下一步开始第二阶段:引入我们需要使用的2个第三方类模块
- 引入@types/node:cnpm i --save @types/node 尽管引用的是淘宝国内代码库镜像,但是依然需要几秒钟的下载时间,请等待
- 引入art-template:cnpm i --save art-template 安装完成后,至此项目初始化完成
- 执行:code . 让VSCode打开本目录(或者直接打开VSCode,选择打开项目文件夹)。
VSCode调试配置
项目初始化后,紧接着要进行VSCode调试配置,操作步骤及流程,如下图所示:
调试配置设置:
- 默认项目启动文件为index.js。可以根据自己喜好修改,比如改为app.js。
- 默认调试每次都启动默认js,也可以新增自己的调试方式,比如修改launch.json,将configurations的值(默认数组里就只有一种调试模式),复制新增一份,并将其中的name值修改为"当前文件"、program值修改为"${file}",该模式下可以启动当前js文档,方便调试使用。
至此,终于可以开始编写代码了。
类模块划分及具体实现
这里直接列出项目结构:
项目结构说明:
./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中进行调试,正常运行结果如下:
为啥不展开来讲?每个类模块具体都是什么代码,具体实现了哪些功能不应该是本篇文章的核心吗?
我是这样认为的:
- 我相信读这篇文章的人,是拥有一定网页JS源码编写能力的。
- 不同类模块里需要使用到的Nodejs方法和属性,我已经在本文上面部分中“Commonjs模块化概念解释、本项目使用的Nodejs类模块”中做了充分介绍。
- 遇到不懂的Nodejs属性和方法,可查阅官方帮助文档,那里有充分详细的介绍,我就没必要再复述一遍。
- 我代码里用的都是最基础的JS语法,整个代码业务推进的方式和本文上面“业务执行流程梳理”完全一致。
- 在返回给用户的数据中,关于如何设置状态码(200/304/404)、如何设置缓存,如何压缩等,均已经在本文上面部分中做了充分讲述。
我希望你一定先把官方帮助文档看明白、然后再看我提供的源码、然后再自己从头写一遍。
这样你才能真正入门,才能真正领悟到Nodejs的开发编写思路。
若你真的真的基础太差,理解不了,可私信给我。
项目总结
- Nodejs的入门核心点在于新的知识储备(比如DOS命令)、Nodejs运行原理、网络通信协议、设计模式等,不在于某个Nodejs的具体语法使用。
- 这些语法具体去编写代码时,和写前台JS没有太大的差别,只不过这些新的函数是Nodejs API提供的而已。
- 前端JS不需要考虑性能(CPU和内存)、而后端性能、安全才是第一。一定要在思维方式上进行一个切换。
- 本文中的“Nodejs简介与安装”、“背景知识:学习Nodejs前需要了解的几个知识点”、“基础概念:Nodejs开发的基本知识”才是整个Nodejs入门核心,至于项目中的源码,那只是一些基础语法的组合而已。
Nodejs思想,网络通信知识才是最难理解和需要学习的那部分,再次强调一下,那些具体的代码仅仅是一个表象而已。
后语
希望你养成一个好的学习、解决问题的方法:看官方文档、在思否/掘金上搜索或提问、或百度一下。
小白教小白Nodejs入门是我花了2天时间写出来的第一篇Nodejs技术分享文章,感谢你的阅读。
明天就是2020年1月1日,我们一起加油!