前言

本篇文档的主要内容:介绍如何使用 Node.js 的 http 模块来搭建一个本地的静态资源服务器。

参考资料

demo

最终效果

demo.gif

测试地址

源码

  1. .
  2. ├── index.js # 入口模块
  3. ├── package-lock.json
  4. ├── package.json
  5. ├── readme.md
  6. └── resources # 静态资源存放的目录
  7. ├── avatar.jpeg
  8. ├── css
  9. └── index.css
  10. ├── index.html
  11. └── test
  12. └── index.html

必要工具的版本:

  • node.js:v16.15.1
  • npm:v8.11.0
  1. {
  2. "dependencies": {
  3. "@types/node": "^18.8.4"
  4. }
  5. }

👆🏻 这是 package.json 的文件内容,装这个 Node.js 的类型声明库,主要是为了在 vscode 中编写 Node.js 代码时,能够获取到 Node.js API 的智能提示。

  1. // ./index.js
  2. const http = require('http')
  3. const fs = require('fs/promises')
  4. const path = require('path')
  5. /**
  6. * 获取文件状态
  7. * @param {String} filename 文件的绝对路径
  8. * @returns 文件状态,如果绝对路径没法找到对应的文件,返回 null
  9. */
  10. async function getFileStat (filename) {
  11. try {
  12. const stat = await fs.stat(filename)
  13. return stat
  14. } catch (e) {
  15. return null
  16. }
  17. }
  18. /**
  19. * 依据传入的请求资源路径,返回对应的文件内容
  20. * @param {String} url 请求的资源路径
  21. * @returns 文件内容,如果文件不存在,返回 null
  22. */
  23. async function getFileContent (url) {
  24. // 处理 url
  25. url = url.replace(/^\//, '').replace(/\/$/, '')
  26. url = url === '' ? 'index.html' : url
  27. console.log('请求静态资源:', url)
  28. // 获取文件信息
  29. const filename = path.resolve(__dirname, 'resources', url)
  30. const stat = await getFileStat(filename)
  31. if (stat) { // 资源存在
  32. if (stat.isDirectory()) { // 是目录
  33. const childFilename = path.resolve(filename, 'index.html')
  34. const childStat = await getFileStat(childFilename)
  35. if (!childStat) return null
  36. else return await fs.readFile(childFilename)
  37. } else { // 是文件
  38. return await fs.readFile(filename)
  39. }
  40. } else { // 资源不存在
  41. return null
  42. }
  43. }
  44. const server = http.createServer(async (req, res) => {
  45. const content = await getFileContent(req.url)
  46. if (content) {
  47. res.statusCode = 200
  48. res.write(content)
  49. } else {
  50. res.statusCode = 404
  51. res.setHeader('Content-Type', 'text/plain;charset=UTF-8')
  52. // charset=UTF-8 在响应中主动告诉浏览器使用UTF-8编码格式来接收数据
  53. // text/plain 纯文本格式
  54. res.write('资源不存在')
  55. }
  56. res.end()
  57. })
  58. server.on('listening', () => {
  59. console.log('listen 1012')
  60. console.log('启动服务,开始监听 1012 端口')
  61. })
  62. server.listen(1012)