其餘章節請看:javascript
咱們用 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() 是一個空方法,則說明咱們的服務器不提供任何服務。
不要把 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 只是報錯,仍會繼續監聽。
其餘章節請看: