nodejs 学习笔记(四)—— 搭建静态Web服务器

在学习笔记(一)里我们已经搭建过一个最简单的服务器,但这个服务器只能返回简单的信息。学习了fs模块,可以利用它实现更复杂的功能。

现在有这样一个需求,在地址栏里输入网址,需要服务器返回相应的html页面,以及页面里依赖的css、js、json等格式的文件。这里的重点是根据不同的路径用fs模块读取相应的文件返回给浏览器,并且根据文件类型设置不同的 ContentType。

准备一个mime.json文件,里面存储了后缀名和ContentType的映射关系,再创建一个getMime方法,用来返回后缀对应的ContentType

// 包装成Promise用来实现同步方法
function getMime(extname) {
    return new Promise((resolve, reject) => {
        fs.readFile('./data/mime.json', (err, data) => {
            if (err) {
                reject(err)
                return
            }
            let mimeObj = JSON.parse(data.toString())
            resolve(mimeObj[extname])
        })
    })
}

接着在app.js里处理请求,借用了path模块的extname方法获取后缀

const http = require('http')
const fs = require('fs')
const getMime = require('./module/common.js')
const path = require('path')

const server = http.createServer((req, res) => {
    const url = new URL(req.url, 'http://127.0.0.1:3000')
    // 获取路径
    let pathname = url.pathname
    // 获取后缀
    let extname = path.extname(pathname)
    // 过滤掉图标
    if (pathname != 'favicon.ico') {
        // 默认跳转到index.html
        pathname = pathname ? pathname : 'index.html'
        fs.readFile('./static' + pathname, async (err, data) => {
            if (err) {
                // 页面不存在返回404
                res.setHeader('ContentType', 'text/html')
                res.end('404')
                return
            }
            res.statusCode = 200;
            // getMime方法——通过后缀获取对应的ContentType
            res.setHeader('ContentType', await getMime(extname))
            res.end(data)
        })
    }
})

server.listen(3000, () => {
    console.log('服务器运行在 http://localhost:3000')
})

目录结构:

 当我们访问 http://localhost:3000 时,默认请求index.html,浏览器解析index.html时遇到<script>、<link>标签则继续向服务器请求js、css文件,服务器根据后缀名设置不同的 ContentType 并返回相应数据。

接下来我们把上面的处理逻辑抽离出来封装成一个方法放在新建的 routes.js 文件里:

// 改成同步方式
function getMime(extname) {
    let data = fs.readFileSync('./data/mime.json')
    let mimeObj = JSON.parse(data.toString())
    console.log(mimeObj[extname])
    return mimeObj[extname]
}

exports.static = function (req, res, staticPath) {
    const url = new URL(req.url, 'http://127.0.0.1:3000')
    // 获取路径
    let pathname = url.pathname
    // 过滤掉图标
    if (pathname != 'favicon.ico') {
        // 默认跳转到index.html
        pathname = pathname === '/' ? '/index.html' : pathname
        // 获取后缀
        let extname = path.extname(pathname)
        try {
            let data = fs.readFileSync('./' + staticPath + pathname)
            if (err) {
                // 页面不存在返回404
                res.setHeader('ContentType', 'text/html')
                res.end('404')
                return
            }
            res.statusCode = 200;
            // getMime方法——通过后缀获取对应的ContentType
            res.setHeader('ContentType', await getMime(extname))
            res.end(data)
 } catch (error) { } } }

然后在app.js引入 static 方法

const http = require('http')
const routes = require('./module/routes')

const server = http.createServer((req, res) => {
    // 如果是访问静态资源,指向static目录下的文件
    routes.static(req, res, 'static')
})

server.listen(3000, () => {
    console.log('服务器运行在 http://localhost:3000')
})

这样,所有请求都会先由 static 方法 处理。在实际应用中,有些资源是保存在服务器上不会变化的,称为静态资源,在本例中指的是index.html,css、js、图片等文件。通过这样一个静态web服务器我们就能够处理静态资源了。

还有一些根据请求可以动态改变文件内容的称为动态资源,借助模板引擎可以将静态模板与动态数据结合起来生成动态文件,我们下节再讨论。

原文地址:https://www.cnblogs.com/zdd2017/p/14658233.html