nodejs小白在做的demo時后台返回主頁面html后,頁面請求引用的js文件,后台沒有返回對應請求路徑的靜態資源,所以報錯。原來在java開發下沒有注意過這種問題,一般除了WEB-INF下的文件不能訪問外,其他資源文件都可以直接用http路徑訪問。
1.使用http模塊處理(http模塊時nodejs內置模塊)
public文件夾下的文件js,html默認為靜態資源,后台讀取這些文件然后返回給前台。
1 var http = require('http'); 2 var fs = require('fs') 3 const path = require('path'); 4 const server = http.createServer((req,res)=>{ 5 res.statusCode=200; 6 var pathurl=path.join(__dirname, req.url); 7 var parseurl= path.parse(pathurl); 8 var spliturls=path.normalize( req.url).split(path.sep) 9 var html=""; 10 if(spliturls.length>0&&spliturls[1]=='public'){ 11 if(parseurl.ext=='.js'){ 12 res.setHeader('Content-Type','text/plain'); 13 html= fs.readFileSync(path.join(__dirname, req.url)); 14 }else if(parseurl.ext=='.html'){ 15 res.setHeader('Content-Type','text/html'); 16 html= fs.readFileSync(path.join(__dirname, req.url)); 17 } 18 }else{ 19 res.setHeader('Content-Type','text/html'); 20 html= fs.readFileSync(path.join(__dirname, 'src/index.html')); 21 } 22 res.end(html) 23 }) 24 server.listen('3000','127.0.0.1',()=>{ 25 console.log(`服務器運行在 http://127.0.0.1:3000/`); 26 })
2.使用express模塊(nodejs的一個web框架,封裝了http模塊)
1 var express = require("express"); 2 var app = new express(); 3 const path = require('path'); 4 app.use(express.static(path.join(__dirname,'public'))) 5 app.use('/',function(req,res){ 6 res.setHeader('Content-Type','text/html'); 7 var html= fs.readFileSync(path.join(__dirname, 'src/index.html')); 8 res.end(html) 9 }) 10 app.listen('3000','127.0.0.1')
其中express.static是設置靜態資源的目錄,如果請求這個目錄下的文件,則會返回對應文件。這里需要注意的是前台請求的文件路徑如果是相對路徑,則從public下面的文件開始,不包括public,否則取不到文件,然后又執行下面的use,返回的數據就不對了。
測試項目的實際靜態資源的路徑: E:\mywv\testbb\public,其中testbb是項目名稱,因此如果請求E:\mywv\testbb\public\index.js文件的http請求路徑是http://127.0.0.1:3000/index.js,而不是http://127.0.0.1:3000/public/index.js。
原因:
express.static(path.join(__dirname,'public'))調用的是 serve-static/index.js中的
1 function serveStatic (root, options) { 2 if (!root) { 3 throw new TypeError('root path required') 4 } 5 6 if (typeof root !== 'string') { 7 throw new TypeError('root path must be a string') 8 } 9 10 ......此處省略部分代碼..... 11 ....... 12 // construct directory listener 13 var onDirectory = redirect 14 ? createRedirectDirectoryListener() 15 : createNotFoundDirectoryListener() 16 17 return function serveStatic (req, res, next) { 18 if (req.method !== 'GET' && req.method !== 'HEAD') { 19 if (fallthrough) { 20 return next() 21 } 22 23 // method not allowed 24 res.statusCode = 405 25 res.setHeader('Allow', 'GET, HEAD') 26 res.setHeader('Content-Length', '0') 27 res.end() 28 return 29 } 30 31 var forwardError = !fallthrough 32 var originalUrl = parseUrl.original(req) 33 var path = parseUrl(req).pathname 34 35 // make sure redirect occurs at mount 36 if (path === '/' && originalUrl.pathname.substr(-1) !== '/') { 37 path = '' 38 } 39 40 // create send stream 41 var stream = send(req, path, opts) 42 43 ......此處省略部分代碼...... 44 ........... 45 46 // pipe 47 stream.pipe(res) 48 } 49 }
調用express.static時,使用的serveStatic (root, options)函數,參數root為E:\mywv\testbb\public,創建發送流(send(req, path, opts)),然后在發送文件時stream.pipe(res).當前端請求路徑是
http://127.0.0.1:3000/public/index.js文件時,pipe輸出文件使用的文件路徑生成是有誤的導致文件找不到。
下圖是stream.pipe輸出文件時,文件路徑的生成。