Vite SSR + Node.js native HTTP server?

m1m5dgzv  于 2023-05-06  发布在  Node.js
关注(0)|答案(1)|浏览(147)

是否可以使用Node.js本地HTTP服务器创建Vite SSR应用程序?Vite文档中的指南使用Express。但我更喜欢使用Node.js原生HTTP服务器,如下所示:

const port = 3000
const host = 'localhost'
const requestListener = async function (req, res) {

  const vite = await createViteServer({
    server: { middlewareMode: true },
    appType: 'custom'
  })

  // Use vite's connect instance as middleware
  vite.middlewares

  // Serve index.html as follows:
  const url = req.url

  let template
  template = fs.readFileSync(
    path.resolve(__dirname, 'index.html'),
    'utf-8'
  )
  template = await vite.transformIndexHtml(url, template)

  const render = (await vite.ssrLoadModule('/src/entry-server.js')).render

  const { 
    appHtml
  } = await render(url)

  const html = template
    .replace(`{{ appHtml }}`, appHtml)

  res.setHeader("Content-Type", "text/html")
  res.writeHead(200)
  res.end(html)
}

const server = createServer(requestListener)
server.listen(port, host, () => {
    console.log(`Server is running on http://${host}:${port}`)
})

我的尝试在终端上有以下错误:

$ npm run dev

> dev
> node server

Server is running on http://localhost:3000
WebSocket server error: Port is already in use

浏览器错误:

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
entry-client.js:1 Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.

有什么想法吗

de90aj5v

de90aj5v1#

如果您添加Vite中间件并提供静态文件,它应该与Vite SSR和Node.js本地HTTP服务器一起工作:

const { createServer } = require('http');
const { createViteServer } = require('vite');
const fs = require('fs');
const path = require('path');
const url = require('url');

const port = 3000;
const host = 'localhost';

async function createRequestListener() {
  const vite = await createViteServer({
    server: { middlewareMode: 'ssr' },
  });

  return async function (req, res) {
    try {
      const parsedUrl = new url.URL(req.url, `http://${host}:${port}`);
      let serveUrl = parsedUrl.pathname;

      if (vite.middlewares) {
        await new Promise((resolve) =>
          vite.middlewares(req, res, resolve)
        );
      }

      if (req.method === 'GET' && serveUrl.endsWith('.js')) {
        res.setHeader('Content-Type', 'application/javascript');
      }

      if (serveUrl === '/') {
        serveUrl = '/index.html';
      }

      if (serveUrl.endsWith('.html')) {
        const template = fs.readFileSync(
          path.resolve(__dirname, './index.html'),
          'utf-8'
        );

        const transformedTemplate = await vite.transformIndexHtml(
          serveUrl,
          template
        );

        const render = (await vite.ssrLoadModule('/src/entry-server.js')).render;
        const { appHtml } = await render(parsedUrl);

        const html = transformedTemplate.replace('{{ appHtml }}', appHtml);

        res.setHeader('Content-Type', 'text/html');
        res.writeHead(200);
        res.end(html);
      } else {
        res.end();
      }
    } catch (err) {
      console.error(err);
      res.writeHead(500);
      res.end(err.message);
    }
  };
}

createRequestListener().then((requestListener) => {
  const server = createServer(requestListener);
  server.listen(port, host, () => {
    console.log(`Server is running on http://${host}:${port}`);
  });
});

相关问题