Express static 托管靜態文件 理解


  今天偶爾看了一下服務端渲染,遇到了express.static, 在以前學習webpack配置服務端渲染時,也使用express.static 中間件,兩者配置不太一樣,由於當時也沒有認真學,所以 一時之間非常困惑,不知道它是怎么正確使用。看了Express 官網,介紹的也是非常簡單,還是不太懂,就查了一些資料,算是有一點懵懂的認識。

  首先要認識一點,在服務器上,一切都是資源, 我們發出的任何請求,都是請求資源。當我們在瀏覽器中輸入www.baidu.com的時候,我們是向www.baidu.com服務器請求index.html資源,發送的請求是get請求。頁面中可能會有css, img, js等文件,當html 文件在進行解析的時候,它碰到css, img, js時,就會向服務器發送請求,請求這些資源,這些請求也是get 請求。我們平時寫js 代碼,發送ajax 請求, 它請求的也是資源,只不過通常是json 字符串或xml。 在web 的領域,一切請求全都是為了資源,資源也可以任意的形式,文本文件,圖片文件, 字符片段等等。只要明白了這一點,理解靜態文件服務就相對輕松了。

  現在用express 搭建一個服務器,來實戰理解一下express.static 托管靜態資源。新建一個目錄,就叫express-static吧。 npm init -y 快速創建package.json文件,npm install express --save 安裝express 依賴。新建server.js,來寫服務器代碼.  我們先按照Express的官網的要求使用express.static中間件。那就要再新建一個public文件夾,在里面建index.html 文件,和css 文件。整個目錄結構如下:

  index.html 中隨便寫點什么,我們就寫一個h1好了,還要引入css, 文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <h1>express.static 托管靜態資源</h1>
</body>
</html>

  css也簡單點,直接給h1 一個color 就可以了,

h1 {
  color: red;
}

  現在來寫server.js 服務端代碼,文件也很簡單,只使用了express.static中間件。它接受一個參數,就是靜態資源文件所在的目錄,在這里是public目錄,直接把public傳遞給它就可以了,按照官網的說法,只要這樣配置,服務器就可以提供靜態文件訪問了。nodemon server.js 啟動服務器試一下。

var express = require('express');
var path = require('path');

var app = express();

// 利用express.static中間件來托管靜態資源。
app.use(express.static(path.join(__dirname, 'public')));

app.listen(5000, () => {
    console.log('start: 5000')
}) 

  服務器啟動后,打開瀏覽器,輸入localhost:5000, 它確定顯示了index.html的內容,並且也應用到了css 樣式,確實是訪問到了靜態文件html, css.

  剛才在上面說了,當我們在瀏覽器地址欄中,輸入網址時,它是在請求資源index.html,html在解析的過程中碰到css, 它也是在請求資源,css文件,我們來看一下是不是這樣,這樣用到瀏覽器控制台中的NetWork 板塊。打開控制台,找到Network版塊

  可以看到,它確實是發送了兩個請求,一個是localhost, 一個是style.css,和我們預想的一樣。點擊localhost 的看一下具體的內容

  發送的url : http://localhost:5000/,  請求方式是Get 請求。點到圖中的Preview 或Response看一下, 返回的是index.html 文件

  現在可以再來看一下style.css

  它請求的地址是 http://localhost:5000/style.css,我們在index.html中寫的是 href='./style.css' 相對路徑,但在真實的請求中,它是向服務器根目錄請求的資源。當然方法還是get 請求。Response是我們寫的css 文件。

  靜態文件的訪問請求,服務器確實是幫我們處理好了,這肯定是我們express.static的功勞。我們把express.static的那段代碼注釋掉就知道了。注釋掉代碼,

// 利用express.static中間件來托管靜態資源。
// app.use(express.static(path.join(__dirname, 'public')));

  然后刷新一下瀏覽器, 任何資源都訪問不到。

 

  看一下控制台的Network, 404 not found, 也就是說,服務器沒有處理這個請求的代碼

   我們知道,它這里其實是發送了一個get 請求,請求的地址是http://localhost: 5000,  根據這個請求內容,我們可以自己寫一個處理請求,其實它就是路由,get 請求用到的是app.get, 由於這里的請求是服務器根地址,所以路徑是'/', 響應就是index.html文件,這里用到是sendfile 來發送文件,  代碼如下:

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public/index.html'))
})

  這時刷新瀏覽器,可以看到頁面顯示文字了,但是字體顏色是黑色,樣式有問題

  這時再看控制台, localhost 請求成功了,style.css 是紅色的,狀態是404 not found, 也就是沒有找到資源

  這時我們已經知道了, 瀏覽器向服務器請求了css 資源,但是在服務端並沒有處理這個請求,所以就報404的錯誤,這時和處理html 一樣,我們要寫一個路由,來處理css請求,這里還是get請求,所以app.get, 因為請求的是所有的css文件,請求的處理路徑要寫成’*.css’, 文件的發送還是用sendFile. 

app.get('*.css', (req, res) => {
    res.sendFile(path.join(__dirname, 'public/style.css'))
})

  這時再刷新瀏覽器,可以看到顏色變紅了,打開控制台,style.css也請求成功了,這時我們沒有使用express.static 靜態服務中間件, 而是自已寫的路由,你會發現作用是一樣的。我們的頁面中還沒有js, image 等資源,如果有的話,我們還需要寫處理js文件和圖片文件的路由,分別對應js 和image 文件的請求。

  到這里就明白了,html,js, css, image 都是存放在服務端的資源,當在瀏覽器中輸入網址的后,我們就是向服務器請求這些資源,相對應的服務端就要有對應的路由來處理這些請求,否則就是404 not found 錯誤。對於這些靜態文件的路由處理,代碼邏輯都是一致的,就是返回請求的文件。再往大處想一想,我們每寫一個網站的服務端,都要處理這些靜態文件的請求, 因為幾乎所有的html文件是都包括js, css, image 文件, 是不是太麻煩了,我們可以復制粘貼,但也是不太好,最好的辦法,當然是把這些一致的處理邏輯抽離出來,形成一個單獨的組件,直接使用組件就好了,這就是express.static 中間件的由來,它就是處理js, css, image等靜態文件的請求,它把我們對靜態文件的路由處理封裝起來。 它的參數是一個文件夾,就是當有請求過來的時候,直接到該文件來下尋找資源,如果有,就直接返回文件,程序不再向下執行,如果找不到,程序再向下執行。那我們直接把靜態文件放到該文件夾,就不用寫這些靜態文件的路由了。

  這里還要注意一點,express.static 中間件的使用,要放到其它處理請求邏輯的前面, 因為頁面在渲染的過程中首先請求的就是html, css, js 文件。如果有的其它請求處理這些靜態文件的請求,那就不會返回靜態文件了。我們寫一個匹配任意請求的文件,app.get(‘*’), 而且把它放到express.static 中間件的前面, 試一試, 整個server.js 如下:

var express = require('express');
var path = require('path');

var app = express();

// 匹配任意請求*, 並且放到express.static 靜態服務器的前面。
app.get('*',  (req, res) => {
    res.send('Hello word');
})
app.use(express.static(path.join(__dirname, 'public')));

app.listen(5000, () => {
    console.log('start: 5000')
}) 

  這時再刷新瀏覽器, 只看到了hello world.

  打開控制台的Network, 你會發現 Respone 返回的hello world 字符串,而不是html 文件, 因為app.get(‘*’) 把我們靜態文件的請求給攔截了,並返回了。路由的處理就是有一個匹配就返回,我們的express.static本質上也是一個路由,所以輪不到它進行執行了。

  在express的官網,express.static 還有一種使用情況, 就是兩個參數,第一個參數是一個路徑,第二個參數才是express.static 的使用。

app.use('/static', express.static('public'));

  第一個參數路徑,表示的是我們的靜態文件的引入路徑的前面有一個路徑/static ,比如,我們的index.html中引入css 改成如下方式

<link rel="stylesheet" href=" /static/style.css">  

  css 的資源請求的路徑前面肯定會再一個static目錄,http://localhost:5000/static/style.css,因為前端資源請求前面有static路徑, 所以我們靜態文件的路由處理,前面也要加static路徑進行匹配。

var express = require('express');
var path = require('path');

var app = express();

// 因為前端資源請求前面有static路徑, 所以我們靜態文件的路由處理,前面也要加static路徑進行匹配。
app.use('/static', express.static(path.join(__dirname, 'public')));

// 為了處理html 文件的請求。
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public/index.html'))
})
app.listen(5000, () => {
    console.log('start: 5000')
}) 

  這時再刷新瀏覽器,沒有問題,打開控制台,也沒有問題。 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM