目录
前言
在我们刚开始学习Node.js时,我们只会在页面上输出'hellow world'之类的字符串或者给客户端,只能响应一个干巴巴的html骨架。这还远远不够的,我们并没有把相关的CSS,JS这些引用的静态资源连同html一起响应给用户。 要想完成这些,似并不是个很难的问题,但这对于初学者来说却经常会犯“想当然”的错误。因此,接下来我们就通过两个简单的正反案例,来学习怎么将那些外链资源反馈给用户。
一、准备阶段
先展示一下目录结构
图 1
图 2
展示一下最终响应的完整页面
图 3
二、案例
案例1
我们在app.js文件里创建好服务器:
let http = require('http')
let fs = require('fs')
let server = http.createServer()
server.listen(3000, function () {
console.log('server is running');
})
server.on('request', function (req, res) {
let url = req.url
if(url === '/') {
fs.readFile('./view/index.html',function(err,data){
if(err) {
res.end('404 Not Found')
return
}
res.end(data)
})
}
})
代 码 1
之后我们通过浏览器输入网址请求页面,结果就会出现这样的情景:
图 4
只有index文件html的骨架,没有样式,图片。这些外链资源依然没有同html一起响应给客户端,这是为什么呢? 这里很多新手都犯了一个“想当然”的错误:我们固认为用户请求对了url,服务器就只需要通过readFile方法找到index.html这个文件,并把它读取,响应给用户,就可以了。 这是错误的,因为浏览器收到HTML响应内容之后,就要开始从上到下依次解析,当在解析的过程中,如果发现:link, script, img, iframe, video, audio等带有 scr 或者 link 的href 属性标签的时候,浏览器会自动对服务端发出这些资源的新的请求。
图 5
我们通过检查Network可以看到,这些响应都失败了,这是因为我们在服务器文件里并没有配置相关的req.url的原因(见代码1)。
案例2
如果是因为我们没有给index.html文件中的外链资源配置相关url,那我们在配置不就好了,但是又遇到了另一个问题:客户端与服务器之间的交互是“一条请求对应一条响应”,一个页面里有如次之多的外部资源(样式,图片,第三方包,js等),难道我们就要一条一条编写请求路径吗? 这显然不可能。为了解决这个问题,我们会将所有可公开的资源放在一个public文件中,我们把整个文件公开,就不需要 一 一 去设置路径了。
我们重新来过吧:
首先是aap.js文件展示
let http = require('http')
let fs = require('fs');
let server = http.createServer()
server.listen(3000,function(){
console.log('server is running');
})
server.on('request',function(req,res){
let url = req.url
//响应这个html网页
if(url === '/') {
fs.readFile('./view/index.html',function(err,data){
if(err) {
res.end('Not Found!')
} else {
res.end(data)
}
})
//响应html中所有外链资源
} else if (url.indexOf('/public/') === 0) {
fs.readFile('.' + url,function(err,data){
if(err) {
res.end('404 Not Found')
} else {
res.end(data)
}
})
}
})
代 码 2
响应过程:当用户发出http请求,服务端会响应请求,读取index.html文件并反馈给用户,用户的浏览器在解析index文件时,遇到带有scr和href属性的外链标签(除了<a>标签,因为链接标签时用户自己点击时才触发的请求),又会重新对这些外部资源发出请求。
代码解释:当用户输入‘/’(或者什么都不写),服务端会响应给用户html页面,当用户的浏览器发出“以/public/开头”的资源请求时,服务器会读取与用户输入的url相同的文件路径,注意:读取的路径要加" . ", html文件里的路径前面不加“ . ” 如图:
html文件
图 6
这是因为浏览器解析html文件时,遇到scr,link属性,就会把这两个属性值当作req.url请求,去向服务器请求这些外链资源,因此固然不能在前面加“.”
而app.js中的readFile需要加“.”是因为要读取服务器里的public文件,这里服务器就渲染了页面,而非是浏览器通过html(因为index.html里的scr和link属性值此时已经不是引用文件的路径了,而是浏览器自动向服务器发出的资源请求!)