英文:
h3 Implicit event handler conversion is deprecated. Use `eventHandler()` or `fromNodeMiddleware()` to define event handlers
问题
我尝试在vite中使用SSR,并且遇到了问题。server.js运行(尽管有警告),但当我尝试在本地访问服务器时,浏览器却一直卡住。
在server.js文件中,我使用了h3、sirv和listhen。此外,我还使用了react-router-dom 6.4。
如果我在await之前放置一个console.log("here"),它会被触发。所以看起来它在等待一个HTTP请求,但当浏览器转到localhost:3001时,浏览器会一直旋转,不加载,就像在等待响应。
我假设问题出在server.js文件中。
以下是我的server.js文件:
// app/server.js
import fs from "fs";
import path from "path";
import { createApp } from "h3";
import { createServer as createViteServer } from "vite";
import { listen } from "listhen";
import sirv from "sirv";
const DEV_ENV = "development";
const bootstrap = async () => {
const app = createApp();
let vite;
if (process.env.NODE_ENV === DEV_ENV) {
vite = await createViteServer({
server: { middlewareMode: true },
appType: "custom",
});
app.use(vite.middlewares);
} else {
app.use(sirv("dist/client", {
gzip: true,
})
);
}
app.use("*", async (req, res, next) => {
const url = req.originalUrl;
let template, render;
try {
if (process.env.NODE_ENV === DEV_ENV) {
template = fs.readFileSync(path.resolve("./index.html"), "utf-8");
template = await vite.transformIndexHtml(url, template);
render = (await vite.ssrLoadModule("/src/entry-server.jsx")).render;
} else {
template = fs.readFileSync(
path.resolve("dist/client/index.html"),
"utf-8"
);
render = (await import("./dist/server/entry-server.js")).render;
}
const appHtml = await render({ path: url });
const html = template.replace("<!--ssr-outlet-->", appHtml);
res.statusCode = 200;
res.setHeader("Content-Type", "text/html").end(html);
} catch (error) {
vite.ssrFixStacktrace(error);
next(error);
}
});
return { app };
};
bootstrap()
.then(async ({ app }) => {
console.log("here");
await listen(app, { port: 3001 });
})
.catch(console.error);
我使用以下命令运行它:
npm run dev
或者
npm run serve
我的package.json文件如下:
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"dev": "NODE_ENV=development node server",
"build": "npm run build:client && npm run build:server",
"build:client": "vite build --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.jsx --outDir dist/server",
"serve": "NODE_ENV=production node server"
},
"dependencies": {
"@reduxjs/toolkit": "^1.9.5",
"axios": "^1.3.6",
"h3": "^1.6.6",
"listhen": "^1.0.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.8.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.10.0",
"react-transition-group": "^4.4.5",
"serve": "^14.2.0",
"sirv": "^2.0.3"
},
"devDependencies": {
"@redux-devtools/core": "^3.13.1",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@vitejs/plugin-react": "^4.0.0-beta.0",
"eslint": "^8.39.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.4",
"sass": "^1.62.0",
"vite": "^4.3.0"
}
}
我的index.html文件如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="app"><!--ssr-outlet--></div>
<script type="module" src="/src/entry-client.jsx"></script>
</body>
</html>
希望这些信息有助于解决您的问题。如果您有其他问题或需要进一步的帮助,请随时提出。
英文:
I'm trying to get SSR working with vite and having a bad time. The server.js runs (thought it does have a warning), but when I try to go to the server localcally, the browser just hangs.
I'm using h3, sirv and listhen in the server.js file. Also I'm using react-router-dom 6.4.
If I put a console.log("here"), before the await it gets hit. So it looks like it is awaiting a http request, but when the browser goes to localhost:3001 the browser just keeps spinning and doesn't load like its waiting for a response.
What am I doing wrong!? I suspect something in the server.js.
I've got the following server.js
// app/server.js
import fs from "fs";
import path from "path";
import { createApp } from "h3";
import { createServer as createViteServer } from "vite";
import { listen } from "listhen";
import sirv from "sirv";
const DEV_ENV = "development";
const bootstrap = async () => {
const app = createApp();
let vite;
if (process.env.NODE_ENV === DEV_ENV) {
vite = await createViteServer({
server: { middlewareMode: true },
appType: "custom",
});
app.use(vite.middlewares);
} else {
app.use(sirv("dist/client", {
gzip: true,
})
);
}
app.use("*", async (req, res, next) => {
const url = req.originalUrl;
let template, render;
try {
if (process.env.NODE_ENV === DEV_ENV) {
template = fs.readFileSync(path.resolve("./index.html"), "utf-8");
template = await vite.transformIndexHtml(url, template);
render = (await vite.ssrLoadModule("/src/entry-server.jsx")).render;
} else {
template = fs.readFileSync(
path.resolve("dist/client/index.html"),
"utf-8"
);
render = (await import("./dist/server/entry-server.js")).render;
}
const appHtml = await render({ path: url });
const html = template.replace(`<!--ssr-outlet-->`, appHtml);
res.statusCode = 200;
res.setHeader("Content-Type", "text/html").end(html);
} catch (error) {
vite.ssrFixStacktrace(error);
next(error);
}
});
return { app };
};
bootstrap()
.then(async ({ app }) => {
console.log("here")
await listen(app, { port: 3001 });
})
.catch(console.error);
And i'm running it with
npm run dev
or
npm run serve
My package.json looks like this:
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"dev": "NODE_ENV=development node server",
"build": "npm run build:client && npm run build:server",
"build:client": "vite build --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.jsx --outDir dist/server",
"serve": "NODE_ENV=production node server"
},
"dependencies": {
"@reduxjs/toolkit": "^1.9.5",
"axios": "^1.3.6",
"h3": "^1.6.6",
"listhen": "^1.0.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.8.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.10.0",
"react-transition-group": "^4.4.5",
"serve": "^14.2.0",
"sirv": "^2.0.3"
},
"devDependencies": {
"@redux-devtools/core": "^3.13.1",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@vitejs/plugin-react": "^4.0.0-beta.0",
"eslint": "^8.39.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.4",
"sass": "^1.62.0",
"vite": "^4.3.0"
}
}
And my index.html like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="app"><!--ssr-outlet--></div>
<script type="module" src="/src/entry-client.jsx"></script>
</body>
</html>
entry-client.jsx:
import React from "react";
import ReactDOM from "react-dom/client";
import Router from "./router.jsx";
import store from "./store/store";
import { Provider } from "react-redux";
ReactDOM.hydrateRoot(
document.getElementById("app"),
<React.StrictMode>
<Provider store={store}>
<Router />
</Provider>
</React.StrictMode>
);
entry-server.jsx:
import ReactDOMServer from "react-dom/server";
import { StaticRouter } from "react-router-dom/server";
import Router from "./router";
export const render = ({ path }) => {
return ReactDOMServer.renderToString(
<StaticRouter location={path}>
<Router />
</StaticRouter>
);
};
and finally, the output of the terminal when I run npm run dev
╰
npm run dev ✘ 10133 13:19 12.06.23
> frontend@0.0.0 dev
> NODE_ENV=development node server
[h3] Implicit event handler conversion is deprecated. Use `eventHandler()` or `fromNodeMiddleware()` to define event handlers.
Handler: function app(req, res, next){ app.handle(req, res, next); }
[h3] Implicit event handler conversion is deprecated. Use `eventHandler()` or `fromNodeMiddleware()` to define event handlers.
Route: *
Handler: async (req, res, next) => {
const url = req.originalUrl;
let template, render;
try {
if (process.env.NODE_ENV === DEV_ENV) {
template = fs.readFileSync(path.resolve("./index.html"), "utf-8");
template = await vite.transformIndexHtml(url, template);
render = (await vite.ssrLoadModule("/src/entry-server.jsx")).render;
} else {
template = fs.readFileSync(
path.resolve("dist/client/index.html"),
"utf-8"
);
render = (await import("./dist/server/entry-server.js")).render;
}
const appHtml = await render({ path: url });
const html = template.replace(`<!--ssr-outlet-->`, appHtml);
res.statusCode = 200;
res.setHeader("Content-Type", "text/html").end(html);
} catch (error) {
vite.ssrFixStacktrace(error);
next(error);
}
}
> Local: http://localhost:3001/
> Network: http://192.168.0.20:3001/
Sorry I know that is a lot of code. But I can't figure out what would be causing it to hang like that. The browser doesn't load the page, and the browser just keeps 'spinning' like its waiting for a response that never comes.
Could it be the asynchronous stuff in the server.js file?
答案1
得分: 0
以下是您提供的代码的翻译部分:
所以问题都在错误消息中。我只是不理解它。
必须将(req、res、next)函数包装在fromNodeMiddleware中。
更新后的server.js文件在这里:
import fs from 'fs/promises'
import path from 'path'
import { createApp, fromNodeMiddleware, toNodeListener } from 'h3'
import { createServer as createViteServer } from 'vite'
import { listen } from 'listhen'
import sirv from 'sirv'
const DEV_ENV = 'development'
const bootstrap = async () => {
const app = createApp()
let vite
if (process.env.NODE_ENV === DEV_ENV) {
vite = await createViteServer({
server: { middlewareMode: true },
appType: 'custom'
})
app.use(fromNodeMiddleware(vite.middlewares))
} else {
app.use(
fromNodeMiddleware(sirv('dist/client', {
gzip: true
}))
)
}
app.use(
'*',
fromNodeMiddleware(async (req, res, next) => {
const url = req.originalUrl
let template, render
try {
if (process.env.NODE_ENV === DEV_ENV) {
template = await fs.readFile(path.resolve('./index.html'), 'utf-8')
template = await vite.transformIndexHtml(url, template)
render = (await vite.ssrLoadModule('/src/entry-server.jsx')).render
} else {
template = await fs.readFile(
path.resolve('dist/client/index.html'),
'utf-8'
)
render = (await import('./dist/server/entry-server.js')).render
}
const appHtml = await render({ path: url })
const html = template.replace('<!--ssr-outlet-->', appHtml)
res.statusCode = 200
res.setHeader('Content-Type', 'text/html').end(html)
} catch (error) {
vite.ssrFixStacktrace(error)
next(error)
}
})
)
return { app }
}
bootstrap()
.then(async ({ app }) => {
await listen(toNodeListener(app), { port: 3001 })
})
.catch(console.error)
请注意,我只翻译了代码部分,不包括您的问题或其他内容。如果您需要进一步的帮助,请随时提出。
英文:
So it was all in the error message. I just didn't understand it.
Had to wrap the (req, res, next) functions in fromNodeMiddleware
Updated server.js file is here:
import fs from 'fs/promises'
import path from 'path'
import { createApp, fromNodeMiddleware, toNodeListener } from 'h3'
import { createServer as createViteServer } from 'vite'
import { listen } from 'listhen'
import sirv from 'sirv'
const DEV_ENV = 'development'
const bootstrap = async () => {
const app = createApp()
let vite
if (process.env.NODE_ENV === DEV_ENV) {
vite = await createViteServer({
server: { middlewareMode: true },
appType: 'custom'
})
app.use(fromNodeMiddleware(vite.middlewares))
} else {
app.use(
fromNodeMiddleware(sirv('dist/client', {
gzip: true
}))
)
}
app.use(
'*',
fromNodeMiddleware(async (req, res, next) => {
const url = req.originalUrl
let template, render
try {
if (process.env.NODE_ENV === DEV_ENV) {
template = await fs.readFile(path.resolve('./index.html'), 'utf-8')
template = await vite.transformIndexHtml(url, template)
render = (await vite.ssrLoadModule('/src/entry-server.jsx')).render
} else {
template = await fs.readFile(
path.resolve('dist/client/index.html'),
'utf-8'
)
render = (await import('./dist/server/entry-server.js')).render
}
const appHtml = await render({ path: url })
const html = template.replace('<!--ssr-outlet-->', appHtml)
res.statusCode = 200
res.setHeader('Content-Type', 'text/html').end(html)
} catch (error) {
vite.ssrFixStacktrace(error)
next(error)
}
})
)
return { app }
}
bootstrap()
.then(async ({ app }) => {
await listen(toNodeListener(app), { port: 3001 })
})
.catch(console.error)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论