前端學習 node 快速入門 系列 —— 簡易版 Apache

其餘章節請看:javascript

前端學習 node 快速入門 系列css

簡易版 Apache

咱們用 node 來實現一個簡易版的 Apache:提供靜態資源訪問的能力html

實現

直接上代碼。前端

- demo
    - static            // 靜態資源文件夾
        - index.html    // 主頁
        - 1.jpg         
        - 1.css
        - 1.js
    - index.js          // 入口文件

index.html:java

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="1.css">
</head>
<body>
   <p>歡迎來到首頁</p>
   <img src="1.jpg" alt="">
   <section></section>
   <script src='1.js'></script>
</body>
</html>

1.js 和 1.css:node

document.querySelector('section').innerHTML = '我來自js' // js

body{color:red} // css

index.js(入口文件):apache

const http = require('http')
const fs = require('fs')
const server = http.createServer()

const requestListener = (req, res) => {
    const url = req.url
    // 若是url是 '/',則返回主頁
    if(url === '/'){
        fs.readFile('./static/index.html', (err, data) => {
            if (err) throw err;
            res.end(data)
        });
        return
    }

    // 若是url不是 '/',則返回資源(找不到資源則報 404)
    fs.readFile('./static/' + url, (err, data) => {
        if (err) {
            res.writeHead(404, {'Content-type':'text/html;charset=utf8'})
            res.end('沒有找到對應的資源')
        }
        res.end(data)
    })
}

server.on('request', requestListener)
server.listen('3000', () => {
    console.log('服務器已啓動')
})

啓動服務器:npm

$ node index

檢驗服務器是否能提供靜態資源訪問的能力。後端

1. 瀏覽器輸入 http://localhost:3000/1.css

頁面顯示:body{color:red}

2. 瀏覽器輸入 http://localhost:3000/1.js

頁面顯示:document.querySelector('section').innerHTML = '鎴戞潵鑷猨s'(未指定編碼,因此中文亂碼。不礙事)

3. 瀏覽器輸入 http://localhost:3000/1.jpg
頁面顯示:1.jpg(正常顯示圖片)

3 種靜態資源都能正常響應。瀏覽器

訪問主頁:

瀏覽器輸入:http://localhost:3000/index.html 或 http://localhost:3000/

頁面顯示:
歡迎來到首頁
圖片
我來自js

主頁和其中的圖片、css 以及 js 配合的很是完美。

:中文亂碼的問題沒有出現。由於咱們在 html 頁面中 使用了 <meta charset="utf-8"> 來指定編碼。

一般訪問不存在的資源會返回 404。請看:

瀏覽器輸入:http://localhost:3000/2.css

頁面顯示:
沒有找到對應的資源

擴展

至此,咱們的簡易版 apache 其實已經大功告成。在此基礎之上,咱們再擴展一下。

個人服務器我作主

理解這一點很重要:這個服務器徹底由咱們作主

如今全部的請求都會進入 requestListener() 方法,若是 url 是 '/',服務器就返回主頁(index.html),不然就去 static 文件夾中讀取相應的資源,若是沒有找到對應的資源,就作 404 的處理。假如 requestListener() 是一個空方法,則說明咱們的服務器不提供任何服務。

全部的請求都是 url

不要把 http://localhost:3000/1.css 中的 1.css 當成文件路徑,而要當成 url,由於全部的請求都是 url。請看示例:

const requestListener = (req, res) => {
    ...
    if(url.endsWith('.myCss')){
        url = url.replace('.myCss', '.css') // url 得聲明成 let
    }
    fs.readFile('./static/' + url, (err, data) => { // {1}
        ...
    })
}

在 index.js 的 fs.readFile('./static/'(行{1}) 上面增長三行代碼。

瀏覽器輸入 http://localhost:3000/1.myCss

頁面顯示:body{color:red}

如今給服務器發送請求 http://localhost:3000/1.myCss,服務器也會返回 1.css 文件的內容。有些網站的 url 設計的很是優雅。請看:

http://product.dangdang.com/29200520.html

// 更優雅
https://www.douban.com/group/topic/214827461/

重定向

未登陸的狀態去訪問頁面,一般會被重定向到首頁。咱們來模擬一下:

if(url.endsWith('.myCss')){
    url = url.replace('.myCss', '.css') 
    res.writeHead(302, {'Location':'/'}) // {1}
    // 行{1} 等價於下面兩行
    // res.statusCode = '302'
    // res.setHeader('Location', '/') 
    
}

在 index.js 中增長 res.writeHead(302, {'Location':'/'})(行{1}),瀏覽器輸入 http://localhost:3000/1.myCss,頁面會重定向到主頁。

:沒有後端開發經驗的學習 node 會比較吃力。好比重定向,咱們想到的多是經過調用一個重定向的方法來實現,而 node 寫起來更底層。

302 是臨時重定向。301 是永久重定向。請看示例:

// 臨時重定向
Request URL: http://localhost:3000/1.myCss
Request Method: GET
Status Code: 302 Found

Request URL: http://localhost:3000/1.myCss
Request Method: GET
Status Code: 302 Found

// 永久重定向
Request URL: http://localhost:3000/1.myCss
Request Method: GET
Status Code: 301 Moved Permanently

Request URL: http://localhost:3000/1.myCss
Request Method: GET
Status Code: 301 Moved Permanently (from disk cache) // {1}

臨時重定向,瀏覽器每次都會去服務器那裏;而永久重定向,第二次就不會去服務器那裏,而是直接在瀏覽器端重定向過去(行{1})

自動重啓服務

每次修改入口文件,都須要從新啓動服務器(執行 node index),很是麻煩。

能夠經過 nodemon 來幫助咱們自動重啓服務。

// 全局安裝 nodemon。
$ npm install --global nodemon

// 必定要全局安裝 nodemon。不然執行 nodemon -v 會報錯。
$ nodemon -v

// 運行入口文件。
$ nodemon index // {1}

使用 nodemon 很是簡單。經過 npm 全局安裝後,用 nodemon 代替 node(行{1})運行入口文件便可。

:筆者還嘗試了 supervisor,感受沒有 nodemon 好用。好比我輸入 let a = (處在一個語法錯誤的狀態)而後保存,supervisor 會退出服務,而 nodemon 只是報錯,仍會繼續監聽。

其餘章節請看:

前端學習 node 快速入門 系列

相關文章
相關標籤/搜索