亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

Node.js動手擼一個靜態資源服務器的方法

2024-05-06 16:48:53
字體:
來源:轉載
供稿:網友

簡介

本文介紹了一個簡單的靜態資源服務器的實例項目,希望能給Node.js初學者帶來幫助。項目涉及到http、fs、url、path、zlib、process、child_process等模塊,涵蓋大量常用api;還包括了基于http協議的緩存策略選取、gzip壓縮優化等;最終我們會發布到npm上,做成一個可以全局安裝、使用的小工具。麻雀雖小,五臟俱全,一想是不是還有點小激動?話不多說,放碼過來。

文中源碼地址在最后附錄中。

可先行體驗項目效果:

安裝:npm i -g here11

任意文件夾地址輸入命令:here

step1 新建項目

因為我們要發布到npm上,所以我們先按照國際慣例,npm init,走你!在命令行可以一路回車,有些配置會在最后的發布步驟中細說。

目錄結構如下:

Node.js,靜態資源,服務器

bin文件夾存放我們的執行代碼,web作為一個測試文件夾,里面放了些網頁。

step2 碼碼

step2.1 雛形

靜態資源服務器,通俗講就是我們在瀏覽器地址欄輸入形如“http://域名/test/index.html”的一個地址,服務器從根目錄下的對應文件夾找到index.html,讀出文件內容并返回給瀏覽器,瀏覽器渲染給用戶。

const http = require("http");const url = require("url");const fs = require("fs");const path = require("path");const item = (name, parentPath) => {  let path = parentPath = `${parentPath}/${name}`.slice(1);  return `<div><a href="${path}" rel="external nofollow" >${name}</a></div>`;}const list = (arr, parentPath) => {  return arr.map(name => item(name, parentPath)).join("");}const server = http.createServer((req, res) => {  let _path = url.parse(req.url).pathname;//去掉search  let parentPath = _path;  _path = path.join(__dirname, _path);  try {    //拿到路徑所對應的文件描述對象    let stats = fs.statSync(_path);    if (stats.isFile()) {      //是文件,返回文件內容      let file = fs.readFileSync(_path);      res.end(file);    } else if (stats.isDirectory()) {      //是目錄,返回目錄列表,讓用戶可以繼續點擊      let dirArray = fs.readdirSync(_path);      res.end(list(dirArray, parentPath));    } else {      res.end();    }  } catch (err) {    res.writeHead(404, "Not Found");    res.end();  }});const port = 2234;const hostname = "127.0.0.1";server.listen(port, hostname, () => {  console.log(`server is running on http://${hostname}:${port}`);});

以上這段code就是我們的核心代碼了,已經實現了核心功能,本地運行即可看到返回了文件目錄,點擊文件名便可瀏覽對應的網頁、圖片、文本啦。

step2.2 優化

功能實現了,但是我們可以在某些方面做做優化,提升實用性,順便多學習幾個api(裝逼技巧)。

1. stream

我們目前讀取文件返回給瀏覽器的操作是通過readFile一次性讀出來,一次性返回,這樣當然可以實現功能,但我們有更好的方式——用stream(流)進行IO操作。stream并不是node.js獨有的概念,而是操作系統最基本的一種操作形式,所以理論上講,任何一門server端語言都實現了stream的API。

為什么講用stream是一種更好的方式?因為一次性讀取、操作大文件,內存和網絡是吃不消的,尤其在用戶訪問量比較大的情況下更為明顯;而借助stream可以讓數據流動起來,一點一點操作,從而提升性能。代碼修改如下:

if (stats.isFile()) {  //是文件,返回文件內容  //在createServer時傳入的回調函數被添加到了"request"事件上,回調函數的兩個形參req和res  //分別為http.IncomingMessage對象和http.ServerResponse對象  //并且它們都實現了流接口  let readStream = fs.createReadStream(_path);  readStream.pipe(res);}

編碼實現非常簡單,在需要返回文件內容時,我們創建了一個可讀流,并把它直接導向了res對象。

2. gzip壓縮

gzip壓縮帶來的性能(用戶訪問體驗)提升是非常明顯的,尤其在當下spa應用大行其道的時代,開啟gzip壓縮,可以大幅減小js、css等文件資源的體積,提升用戶訪問速度。作為一個靜態資源服務器,我們當然要加上這個功能。

node中有一個zlib的模塊,提供了很多壓縮相關的api,我們就用它來實現:

const zlib = require("zlib");if (stats.isFile()) {  //是文件,返回文件內容  res.setHeader("content-encoding", "gzip");    const gzip = zlib.createGzip();  let readStream = fs.createReadStream(_path);  readStream.pipe(gzip).pipe(res);}

有了stream的使用經驗,我們再看這段代碼的時候就好理解多了。把文件流先導向gzip對象,再導向res對象。此外,使用gzip壓縮的時候還需要注意一點:需要把響應頭里的content-encoding設置為gzip。否則瀏覽器會把一堆亂碼展示出來。

3. http緩存

緩存這個東西讓人又愛又恨,用得好,可以提升用戶體驗,減輕服務器壓力;用得不好,可能就會面臨各種各樣奇奇怪怪的問題。一般來講瀏覽器http緩存分為強緩存(非驗證性緩存)和協商緩存(驗證性緩存)。

什么叫強緩存呢?強緩存是由cache-control和expires兩個首部字段控制的,現在一般用cache-control。比如我們設置了cache-control: max-age=31536000的響應頭,就是告訴瀏覽器這個資源有一年的緩存期,一年內不用向服務端發送請求,直接從緩存中讀取資源。

而協商性緩存是使用if-modified-since/last-modified、if-none-match/etag等首部字段,配合強緩存,在強緩存沒有命中(或告知瀏覽器no-cache)的時候,向服務器發送請求,確認資源的有效性,決定從緩存中讀取或是返回新的資源。

有了以上概念,我們便可以制定我們的緩存策略:

if (stats.isFile()) {  //是文件,返回文件內容    //增加判斷文件是否有改動,沒有改動返回304的邏輯    //從請求頭獲取modified時間  let IfModifiedSince = req.headers["if-modified-since"];  //獲取文件的修改日期——時間戳格式  let mtime = stats.mtime;  //如果服務器上的文件修改時間小于等于請求頭攜帶的修改時間,則認定文件沒有變化  if (IfModifiedSince && mtime <= new Date(IfModifiedSince).getTime()) {    //返回304    res.writeHead(304, "not modify");    return res.end();  }  //第一次請求或文件被修改后,返回給客戶端新的修改時間  res.setHeader("last-modified", new Date(mtime).toString());  res.setHeader("content-encoding", "gzip");  let reg = //.html$/;  //不同的文件類型設置不同的cache-control  if (reg.test(_path)) {    //我們對html文件執行每次必須向服務器驗證資源有效性的策略    res.setHeader("cache-control", "no-cache");  } else {    //我們對其余的靜態資源文件采取強緩存策略,一個月內無需向服務器索取    res.setHeader("cache-control", `max-age=${1 * 60 * 60 * 24 * 30}`);  }    //執行gzip壓縮  const gzip = zlib.createGzip();  let readStream = fs.createReadStream(_path);  readStream.pipe(gzip).pipe(res);}

這樣一套緩存策略在現代前端項目體系下還是比較合適的,尤其是對于spa應用來講。我們希望index.html能夠保證每次向服務器驗證是否有更新,而其余的文件統一本地緩存一個月(自己定);通過webpack打包或其他工程化方式構建之后,js、css內容如果發生變化,文件名相應更新,index.html插入的manifest(或script鏈接、link鏈接等)清單會更新,保證用戶能夠實時得到最新的資源。

當然,緩存之路千萬條,適合業務才重要,大家可以靈活制定。

4. 命令行參數

作為一個在命令行執行的工具,怎么能不象征性的支持幾個參數呢?

const config = {  //從命令行中獲取端口號,如果未設置采用默認  port: process.argv[2] || 2234,  hostname: "127.0.0.1"}server.listen(config.port, config.hostname, () => {  console.log(`server is running on http://${config.hostname}:${config.port}`);});

這里就簡單的舉個栗子啦,大家可以自由發揮!

5. 自動打開瀏覽器

雖然沒太大卵用,但還是要加。我就是要讓你們知道,我加完之后什么樣,你們就是什么樣 :-( duang~

const exec = require("child_process").exec;server.listen(config.port, config.hostname, () => {  console.log(`server is running on http://${config.hostname}:${config.port}`);  exec(`open http://${config.hostname}:${config.port}`);});

6. process.cwd()

用process.cwd()代替__dirname。

我們最終要做成一個全局并且可以在任意目錄下調用的命令,所以拼接path的代碼修改如下:

//__dirname是當前文件的目錄地址,process.cwd()返回的是腳本執行的路徑_path = path.join(process.cwd(), _path);

step3 發布

基本上我們的代碼都寫完了,可以考慮發布了?。ú话l布到npm上何以顯示逼格?)

step3.1 package.json

得到一個配置類似下面所示的json文件:

{  "name": "here11",  "version": "0.0.13",  "private": false,  "description": "a node static assets server",  "bin": {    "here": "./bin/index.js"  },  "repository": {    "type": "git",    "url": "https://github.com/gww666/here.git"  },  "scripts": {    "test": "node bin/index.js"  },  "keywords": [    "node"  ],  "author": "gw666",  "license": "ISC"}

其中bin和private較為重要,其余的按照自己的項目情況填寫。

bin這個配置代表的是npm i -g xxx之后,我們運行here命令所執行的文件,“here”這個名字可以隨意起。

step3.2 聲明腳本執行類型

在index.js文件的開頭加上:#!/usr/bin/env node

否則linux上運行會報錯。

step3.3 注冊npm賬號

勉強貼一手命令,還不清楚自行百度:

沒有賬號的先添加一個,執行:

npm adduser

然后依次填入

Username: your name
Password: your password
Email: yourmail

npm會給你發一封驗證郵件,記得點一下,不然會發布失敗。

執行登錄命令:

npm login

執行發布命令:

npm publish

發布的時候記得把項目名字、版本號、作者、倉庫啥的改一下,別填成我的。
還有readme文件寫一下,好歹告訴別人咋用,基本上和文首所說的用法是一樣的。

好了,齊活。

step3.4

還等啥啊,趕快把npm i -g xxx 這行命令發給你的小伙伴啊。什么?你沒有小伙伴?告辭!

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91香蕉国产在线观看| 1769国产精品| 91豆花精品一区| 欧美大成色www永久网站婷| 欧美在线视频一区| 国产日韩在线亚洲字幕中文| 91久久在线视频| 亚洲欧洲在线播放| 亚洲成人三级在线| 亚洲成**性毛茸茸| 久久久亚洲欧洲日产国码aⅴ| 国产精品日韩av| 亚洲精品一区二三区不卡| 亚洲aⅴ男人的天堂在线观看| 亚洲激情视频网| 精品偷拍一区二区三区在线看| 最新91在线视频| 国产一区二区三区在线播放免费观看| 亚洲综合精品一区二区| 亚洲激情久久久| 亚洲第一区在线| 精品国产乱码久久久久久婷婷| 日韩在线视频网| 日韩二区三区在线| 51久久精品夜色国产麻豆| 国产精品免费在线免费| 国产美女扒开尿口久久久| 性金发美女69hd大尺寸| 欧美日韩精品在线观看| 国产精品日韩欧美综合| 国外视频精品毛片| 国产一区二区成人| 日韩精品视频观看| 欧美久久精品一级黑人c片| 国模吧一区二区| 欧美极品xxxx| 自拍偷拍亚洲欧美| 国产免费一区二区三区在线观看| 欧美一级淫片播放口| 在线丨暗呦小u女国产精品| 亚洲国产欧美久久| 国产美女91呻吟求| 91久久久久久久久| 色偷偷噜噜噜亚洲男人的天堂| 亚洲美女黄色片| 中文一区二区视频| 欧美乱大交做爰xxxⅹ性3| 在线播放国产一区中文字幕剧情欧美| 欧美韩国理论所午夜片917电影| 久久久久久av| 成人免费福利在线| 国产精品视频一区国模私拍| 亚洲欧美日韩在线一区| 91国内揄拍国内精品对白| 日韩欧美在线一区| 成人a视频在线观看| 欧美大片在线免费观看| 色综合久久天天综线观看| 69视频在线播放| 国产精品91在线| 国产亚洲欧洲在线| 91精品视频在线免费观看| 91精品国产91| 在线亚洲欧美视频| 亚洲成人av在线播放| 欧美孕妇性xx| 97在线视频免费看| 亚洲欧美国产精品va在线观看| 亚洲国产另类久久精品| 国产精品久久久久影院日本| 国产日本欧美一区| 欧美视频二区36p| 亚洲电影中文字幕| 久久久久一本一区二区青青蜜月| 成人精品aaaa网站| 欧美亚洲国产另类| 国产精品久久久久免费a∨| 日韩电影免费在线观看中文字幕| 这里只有精品视频在线| 欧美黑人极品猛少妇色xxxxx| 久久综合88中文色鬼| 一区二区三区四区精品| 欧美xxxx做受欧美.88| 都市激情亚洲色图| 26uuu另类亚洲欧美日本一| 久久久久久高潮国产精品视| 亚洲国产欧美一区二区三区同亚洲| 欧美电影免费在线观看| 午夜精品久久久久久久久久久久久| 秋霞午夜一区二区| 正在播放亚洲1区| 91精品久久久久| 欧美精品国产精品日韩精品| 不卡av在线网站| 亚洲国产另类 国产精品国产免费| 亚洲欧美中文在线视频| 亚洲精品白浆高清久久久久久| 91精品国产自产在线观看永久| 97视频国产在线| 日韩一二三在线视频播| 一本色道久久综合亚洲精品小说| 国产精品av网站| 国产亚洲精品久久久久久牛牛| 97视频网站入口| 精品在线欧美视频| 国产精品wwww| 国产欧美一区二区三区在线| 久久国产精品首页| www.精品av.com| 日韩亚洲欧美中文高清在线| 91久热免费在线视频| 自拍偷拍亚洲欧美| 久久久女人电视剧免费播放下载| 久久久久久999| 97av在线视频免费播放| 亚洲人成电影在线播放| 久久精品国产清自在天天线| 中文字幕国产亚洲| 欧美日韩免费在线| 成人福利在线视频| 欧美成人在线免费视频| 91精品免费视频| 亚洲图中文字幕| 亚洲自拍在线观看| 中文字幕免费国产精品| 91超碰中文字幕久久精品| 久久乐国产精品| 日韩欧美大尺度| 国产精品视频久久| 国产精品一区二区在线| 亚洲视频在线观看| 91欧美激情另类亚洲| 国产精品福利在线观看网址| 成人深夜直播免费观看| 日韩a**站在线观看| 国产亚洲日本欧美韩国| 久久久久久久久久久91| 亚洲国产精品成人av| 久久的精品视频| 国产精品美乳一区二区免费| 亚洲色图色老头| 欧洲成人性视频| 国产激情视频一区| 日韩在线视频免费观看| 亚洲毛片在线观看| 亚洲深夜福利在线| 亚洲欧美另类人妖| 中文字幕视频在线免费欧美日韩综合在线看| 国产97色在线|日韩| 久久99国产精品久久久久久久久| 国产一区玩具在线观看| 富二代精品短视频| 日韩中文字幕不卡视频| 国产日产久久高清欧美一区| 欧美日韩黄色大片| 91av网站在线播放| 午夜精品福利视频| 国产精品普通话| 欧美综合在线第二页| 高跟丝袜一区二区三区| 久久韩国免费视频| 久久夜色精品亚洲噜噜国产mv| 日本在线观看天堂男亚洲| 欧美性受xxxx白人性爽|