源码解析
简化版vite
开发服务

http

在 node 中,实现一个 开发服务 很简单,可以通过内置的 http 模块,实现一个 http 服务:

import { createServer } from "node:http"
 
const server = createServer(async (req, res) => {
  res.end('Hello Word');
})
server.listen(3000);

但这太简单了,我们需要这个 http 服务,能够根据请求的资源链接,返回相关的 html/css/javascript资源,以及图片等各种资源。

比如,如果我们期望返回一个本地磁盘中的一个 html 资源,我们可能需要这么实现:

import { createServer } from "node:http";
import fs from "node:fs";
import path from "node:path";
 
 
const server = createServer(async (req, res) => {
  const index = path.join(process.cwd(), 'src/index.html');
  const stream = fs.createReadStream(index);
  stream.pipe(res);
});
 
server.listen(3001, () => {
  console.log('server listen: http://localhost:3001');
});
 

查看完整示例 (opens in a new tab)

可以预见的是,我们可能需要预先对各种资源在 http server 中进行处理,同时还要使 http server 保证可用,并实现 其他各种相关功能。

但我们并不必须要从零开始实现这些功能,得益于 node 强大的开源社区,有很多的 http-server 实现,这让我们可以从如 express / koa / fastify / connect 等库中选择。

vite 中,使用了 connect 作为 http-server,所以在我们的简化版中,也同样选择 connect

vite2.0 版本之前,选择的是 koa 作为 http-server。 为什么从 koa 切换到 connect,原因我还未做深入了解。

connect

使用 connect 启动一个 http-server 非常简单:

import connect from 'connect'
 
const server = connect()
 
server.listen(3000)

在此基础上,我们可以实现一个简单的 Web http server:

import connect from "connect";
import fs from "node:fs";
import path from "node:path";
 
const server = connect();
 
server.use(async (req, res) => {
  const url = req.url === '/' ? '/index.html' : req.url
  const assert = path.join(process.cwd(), 'src', url);
  if (fs.existsSync(assert)) {
    const stream = fs.createReadStream(assert);
    stream.pipe(res);
  } else {
    res.end();
  }
})
 
server.listen(3001, () => {
  console.log('server listen: http://localhost:3001');
})
 

查看完整示例 (opens in a new tab)

但这个 web-http-server 还不能作为一个 前端的开发服务,它目前只能响应 src 目录中的资源,也没有对 资源地址进行校验,判断资源是否存在等一系列缺陷。