基于node搭建的本地静态资源服务器

在进行前端项目开发时,经常会需要用到本地静态资源服务器,以便于在本地进行调试。本文介绍了如何使用node搭建一个本地静态资源服务器。

在之前,我一直用的基于IIS、Nginx或者Apache来实现的,还有基于相关服务的成熟的web端系统,比如 h5ai, directorylister等等,既美观,功能又多。直到某天升级了MAC系统,以前配置都丢了不说,新版本系统还删除了自带的Apache,然后安装Nginx又遇到权限问题,折腾一个小时也没搞定。。。

后来想想,其实对于满足前端开发预览需求来说,Nginx、Apache等服务太重了,而且还需要配置,不如自己基于node来实现一个最基础功能的本地静态资源服务器,这样就不用担心系统升级或者换电脑后,配置丢失的问题了。

下面先直接放源码,单独一个js文件,无其他任何依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
const http = require("http")
const fs = require("fs")
const path = require("path")

const blockedFiles = ["secret.txt", ".exe"]
const ignore = [
".git",
".vscode",
".DS_Store",
"node_modules",
"package-lock.json",
".htaccess",
]

const server = http.createServer((req, res) => {
const filePath = path.join(__dirname, req.url)

// Check if file is blocked
if (blockedFiles.some((file) => filePath.includes(file))) {
res.statusCode = 403
res.end("Access to this file is forbidden")
return
}

// Check if file exists
fs.access(filePath, fs.constants.F_OK, (err) => {
if (err) {
res.statusCode = 404
res.end("File not found")
return
}

// Check if file is a directory
fs.stat(filePath, (err, stats) => {
if (err) {
res.statusCode = 500
res.end("Internal server error")
return
}

if (stats.isDirectory()) {
// Serve index file if it exists
const indexFilePath = path.join(filePath, "index.html")
fs.access(indexFilePath, fs.constants.F_OK, (err) => {
if (err) {
// Generate directory listing
fs.readdir(filePath, (err, files) => {
if (err) {
res.statusCode = 500
res.end("Internal server error")
return
}

const html = `
<html>
<head>
<title>Directory listing for ${req.url}</title>
</head>
<body>
<h1>Directory listing for ${req.url}</h1>
<ul>
${files
.filter((item) => !ignore.includes(item))
.sort()
.map(
(file) =>
`<li><a href="${path.join(
req.url,
file
)}">${file}</a></li>`
)
.join("")}
</ul>
</body>
</html>
`

res.setHeader("Content-Type", "text/html")
res.end(html)
})
} else {
// Serve index file
serveFile(indexFilePath, res)
}
})
} else {
// Serve file
serveFile(filePath, res)
}
})
})
})

function serveFile(filePath, res) {
const fileStream = fs.createReadStream(filePath)
fileStream.on("open", () => {
res.setHeader("Content-Type", getContentType(filePath))
fileStream.pipe(res)
})
fileStream.on("error", (err) => {
res.statusCode = 500
res.end("Internal server error")
})
}

function getContentType(filePath) {
const extname = path.extname(filePath)
switch (extname) {
case ".html":
return "text/html"
case ".css":
return "text/css"
case ".js":
return "text/javascript"
case ".json":
return "application/json"
case ".png":
return "image/png"
case ".jpg":
case ".jpeg":
return "image/jpeg"
default:
return "application/octet-stream"
}
}

server.listen(3300, () => {
console.log("Server listening on port 3300")
})

以上只是一个最简单的实现,目录列表页也是最简单的,只是为了满足基本的预览需求,如果有更多需求,可以自行修改。

本文永久链接: https://www.mulianju.com/node-local-assets-server/