前言
全局安装 http-server
npm install http-server -g
http-server 以当前文件夹为根目录的服务被启动
Server服务
现在手写下这个服务
这里要做的功能是仿 http-server 启动服务 浏览器能够访问当前文件夹下的启动的这个服务
基本步骤:
初始化
npm init -y
有一个执行命令的脚本 用于解析用户的参数 新建bin/www文件 便于记忆 有病的环境
1 | // bin/www |
配脚本
package.json
文件添加如下配置:
映射到全局
iTerm cd到当前目录17.http/ npm link
可以看到全局命令下有个server命令,执行它就会执行bin/www
拓展功能
- -help
基本上写一个命令行工具都会有这样一个功能 server - -help
这里会用到这个比较流行的工具 commander
npm install commander
解析命令行参数的,只要写工具,必备的包。
先可以参考下http-server的- -help
-p
-p 改端口号(默认是8080) http-server -p 3000
这样开启的端口就是3000
现在实现跟上面一样的功能 server -p 3000
现在需要用commander去解析命令行工具 现在去www文件
1 | // www |
babel es6 => es5
安装 npm install @babel/cli @babel/core @babel/preset-env --save-dev
@babel/cli (在命令行里面调它,它默认会调用 @babel/core)
@babel/core (babel的核心文件,找配置文件.babelrc,它会根据配置文件去调 @babel/preset-env 这个包)
@babel/preset-env (它的功能就是把es6=>es5)
新建 .babelrc
文件
1 | { |
下面这个文件的作用只做require 解析参数的功能放到 /src/main.js
1 | // www |
1 | // main.js |
好 现在来解析
可以用 npx babel –help 查看参数 这里npx 会走node_modules/.bin/babel
转化 npx babel src -d dist
解析src文件夹下的内容 放到dist文件夹下
现在 server 就能够获取到编译好的代码 但是每次main.js改动都需要手动执行 现如下npx babel src -d dist --watch
加一个监控 可以自动编译 这样在node环境就可以用es6语法来写这个功能了
小调整 用npx可能给别人用不太好 package.json增加line11、12
npm run babel:watch
npm run babel
解析参数
1 | // main.js |
执行 server –help
设置option参数可以 执行 npm commander 参考
执行 server -p 3000 打印 3000 3000
通过解析的参数启动一个服务
获取当前文件夹下的内容(文件夹、文件),拼接成模板显示出来,如图:
新建server.js
1 | // main.js |
1 | // server.js |
1 | // server.js |
新建 template.html
1 |
|
http优化策略
1) 压缩
客户端说我支持:Accept-Encoding: gzip, deflate, br(这里node支持前2种)
服务器:Content-Encoding: gzip
怎么实现
转化流
流:可读流(源码里面自己实现了一个_read) 可写流(源码里自己实现了一个_write) 双工流_read _write
转化流:压缩就是靠这个转化流实现的
现在自己构建一个转化流
1 | const {Transform} = require('stream'); |
延伸 插入一个知识点
1 | // 标准输出 |
补gif图
进阶 如果输入 abc 能够输出ABC
中间做一步转化 把读取到的内容先放到一个流里面转化完 再把它写出来
1 | const {Transform} = require('stream'); |
补gif图
压缩 gzip
1 | const zlib = require('zlib'); |
1.txt
1 | 1111111111111111111.... |
压缩是可解压的 大致会压缩成 这里有1百万个1 把重复的替换掉 变得更小
怎么应用
开始写压缩流程
客户端说我支持:Accept-Encoding: gzip, deflate, br 先将服务启动起来 server
访问http-1.md http://127.0.0.1:8080/http-1.md 现在是4.5k 没有压缩
1 | // 如果文件很大 在服务器上压缩会有性能问题 |
2)缓存
强制缓存
先新建 1.html 、1.css 启动服务 server http://127.0.0.1:8080/1.html
1 | <!--1.html--> |
1 | // 1.css |
1 | // server.js |
现在看看效果 访问 http://127.0.0.1:8080/1.html
如图所示浏览器缓存了 ‘css’
如图所示 css走的缓存
但是这里html还是走的服务器
如果设置强制缓存 首页是不会缓存的 所以首页一定会发起请求,如果首页设置了强制缓存,它包含的资源则会走缓存
1 | // 其他的设置 |
对比缓存
1 | cache(filePath,req,res,statObj){// 协商缓存/ 对比缓存 |
第一次刷新 res里有这个时间戳
第二次刷新请求,请求头带了这个时间戳
并且这时的状态码是304
- 存在的问题
1) 文件可能没发生变化 但是修改时间变化了 (写入新的数据然后又撤销了,这样文件没有被修改,但是修改的那个时间戳改变了)
2) 精确的时间不准确 会导致问题 同一时间内改了很多次
3) cdn (静态资源通过cdn cdn分发的时间不一样也会导致缓存失效)
解决方式 : 指纹
指纹
什么叫指纹:把整个内容进行md5,md5之后 内容只要有一点发生改变,md5戳也会发生变化
新建 2.crypto.js
1 | // 2.crypto.js |
1 | // server.js |
完整的server.js
1 | // server.js |
这里测试这个服务的时候 千万别忘了这个是es6语法 要在node中执行需要转化成es5 转化的服务要开起来 npm run babel:watch
Tips
__dirname 指当前执行文件的目录
process.cwd() 指当前执行命令的目录