h3 Implicit event handler conversion is deprecated. Use `eventHandler()` or `fromNodeMiddleware()` to define event handlers

huangapple go评论155阅读模式
英文:

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 &quot;fs&quot;;
import path from &quot;path&quot;;
import { createApp } from &quot;h3&quot;;
import { createServer as createViteServer } from &quot;vite&quot;;
import { listen } from &quot;listhen&quot;;
import sirv from &quot;sirv&quot;;
const DEV_ENV = &quot;development&quot;;
const bootstrap = async () =&gt; {
const app = createApp();
let vite;
if (process.env.NODE_ENV === DEV_ENV) {
vite = await createViteServer({
server: { middlewareMode: true },
appType: &quot;custom&quot;,
});
app.use(vite.middlewares);
} else {
app.use(sirv(&quot;dist/client&quot;, {
gzip: true,
})
);
}
app.use(&quot;*&quot;, async (req, res, next) =&gt; {
const url = req.originalUrl;
let template, render;
try {
if (process.env.NODE_ENV === DEV_ENV) {
template = fs.readFileSync(path.resolve(&quot;./index.html&quot;), &quot;utf-8&quot;);
template = await vite.transformIndexHtml(url, template);
render = (await vite.ssrLoadModule(&quot;/src/entry-server.jsx&quot;)).render;
} else {
template = fs.readFileSync(
path.resolve(&quot;dist/client/index.html&quot;),
&quot;utf-8&quot;
);
render = (await import(&quot;./dist/server/entry-server.js&quot;)).render;
}
const appHtml = await render({ path: url });
const html = template.replace(`&lt;!--ssr-outlet--&gt;`, appHtml);
res.statusCode = 200;
res.setHeader(&quot;Content-Type&quot;, &quot;text/html&quot;).end(html);
} catch (error) {
vite.ssrFixStacktrace(error);
next(error);
}
});
return { app };
};
bootstrap()
.then(async ({ app }) =&gt; {
console.log(&quot;here&quot;)
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:

{
&quot;name&quot;: &quot;frontend&quot;,
&quot;private&quot;: true,
&quot;version&quot;: &quot;0.0.0&quot;,
&quot;type&quot;: &quot;module&quot;,
&quot;scripts&quot;: {
&quot;lint&quot;: &quot;eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0&quot;,
&quot;dev&quot;: &quot;NODE_ENV=development node server&quot;,
&quot;build&quot;: &quot;npm run build:client &amp;&amp; npm run build:server&quot;,
&quot;build:client&quot;: &quot;vite build --outDir dist/client&quot;,
&quot;build:server&quot;: &quot;vite build --ssr src/entry-server.jsx --outDir dist/server&quot;,
&quot;serve&quot;: &quot;NODE_ENV=production node server&quot;
},
&quot;dependencies&quot;: {
&quot;@reduxjs/toolkit&quot;: &quot;^1.9.5&quot;,
&quot;axios&quot;: &quot;^1.3.6&quot;,
&quot;h3&quot;: &quot;^1.6.6&quot;,
&quot;listhen&quot;: &quot;^1.0.4&quot;,
&quot;react&quot;: &quot;^18.2.0&quot;,
&quot;react-dom&quot;: &quot;^18.2.0&quot;,
&quot;react-icons&quot;: &quot;^4.8.0&quot;,
&quot;react-redux&quot;: &quot;^8.0.5&quot;,
&quot;react-router-dom&quot;: &quot;^6.10.0&quot;,
&quot;react-transition-group&quot;: &quot;^4.4.5&quot;,
&quot;serve&quot;: &quot;^14.2.0&quot;,
&quot;sirv&quot;: &quot;^2.0.3&quot;
},
&quot;devDependencies&quot;: {
&quot;@redux-devtools/core&quot;: &quot;^3.13.1&quot;,
&quot;@types/react&quot;: &quot;^18.0.28&quot;,
&quot;@types/react-dom&quot;: &quot;^18.0.11&quot;,
&quot;@vitejs/plugin-react&quot;: &quot;^4.0.0-beta.0&quot;,
&quot;eslint&quot;: &quot;^8.39.0&quot;,
&quot;eslint-plugin-react&quot;: &quot;^7.32.2&quot;,
&quot;eslint-plugin-react-hooks&quot;: &quot;^4.6.0&quot;,
&quot;eslint-plugin-react-refresh&quot;: &quot;^0.3.4&quot;,
&quot;sass&quot;: &quot;^1.62.0&quot;,
&quot;vite&quot;: &quot;^4.3.0&quot;
}
}

And my index.html like this:

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot; /&gt;
&lt;link rel=&quot;icon&quot; type=&quot;image/svg+xml&quot; href=&quot;/vite.svg&quot; /&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
&lt;title&gt;Vite + React&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id=&quot;app&quot;&gt;&lt;!--ssr-outlet--&gt;&lt;/div&gt;
&lt;script type=&quot;module&quot; src=&quot;/src/entry-client.jsx&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

entry-client.jsx:

import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom/client&quot;;
import Router from &quot;./router.jsx&quot;;
import store from &quot;./store/store&quot;;
import { Provider } from &quot;react-redux&quot;;
ReactDOM.hydrateRoot(
document.getElementById(&quot;app&quot;),
&lt;React.StrictMode&gt;
&lt;Provider store={store}&gt;
&lt;Router /&gt;
&lt;/Provider&gt;
&lt;/React.StrictMode&gt;
);

entry-server.jsx:

import ReactDOMServer from &quot;react-dom/server&quot;;
import { StaticRouter } from &quot;react-router-dom/server&quot;;
import Router from &quot;./router&quot;;
export const render = ({ path }) =&gt; {
return ReactDOMServer.renderToString(
&lt;StaticRouter location={path}&gt;
&lt;Router /&gt;
&lt;/StaticRouter&gt;
);
};

and finally, the output of the terminal when I run npm run dev

 npm run dev                                                                ✘  10133   13:19    12.06.23
&gt; frontend@0.0.0 dev
&gt; 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) =&gt; {
const url = req.originalUrl;
let template, render;
try {
if (process.env.NODE_ENV === DEV_ENV) {
template = fs.readFileSync(path.resolve(&quot;./index.html&quot;), &quot;utf-8&quot;);
template = await vite.transformIndexHtml(url, template);
render = (await vite.ssrLoadModule(&quot;/src/entry-server.jsx&quot;)).render;
} else {
template = fs.readFileSync(
path.resolve(&quot;dist/client/index.html&quot;),
&quot;utf-8&quot;
);
render = (await import(&quot;./dist/server/entry-server.js&quot;)).render;
}
const appHtml = await render({ path: url });
const html = template.replace(`&lt;!--ssr-outlet--&gt;`, appHtml);
res.statusCode = 200;
res.setHeader(&quot;Content-Type&quot;, &quot;text/html&quot;).end(html);
} catch (error) {
vite.ssrFixStacktrace(error);
next(error);
}
}
&gt; Local:    http://localhost:3001/
&gt; Network:  http://192.168.0.20:3001/

h3 Implicit event handler conversion is deprecated. Use `eventHandler()` or `fromNodeMiddleware()` to define event handlers

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

以下是您提供的代码的翻译部分:

所以问题都在错误消息中我只是不理解它

必须将reqresnext函数包装在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 &#39;fs/promises&#39;
import path from &#39;path&#39;
import { createApp, fromNodeMiddleware, toNodeListener } from &#39;h3&#39;
import { createServer as createViteServer } from &#39;vite&#39;
import { listen } from &#39;listhen&#39;
import sirv from &#39;sirv&#39;
const DEV_ENV = &#39;development&#39;
const bootstrap = async () =&gt; {
const app = createApp()
let vite
if (process.env.NODE_ENV === DEV_ENV) {
vite = await createViteServer({
server: { middlewareMode: true },
appType: &#39;custom&#39;
})
app.use(fromNodeMiddleware(vite.middlewares))
} else {
app.use(
fromNodeMiddleware(sirv(&#39;dist/client&#39;, {
gzip: true
}))
)
}
app.use(
&#39;*&#39;,
fromNodeMiddleware(async (req, res, next) =&gt; {
const url = req.originalUrl
let template, render
try {
if (process.env.NODE_ENV === DEV_ENV) {
template = await fs.readFile(path.resolve(&#39;./index.html&#39;), &#39;utf-8&#39;)
template = await vite.transformIndexHtml(url, template)
render = (await vite.ssrLoadModule(&#39;/src/entry-server.jsx&#39;)).render
} else {
template = await fs.readFile(
path.resolve(&#39;dist/client/index.html&#39;),
&#39;utf-8&#39;
)
render = (await import(&#39;./dist/server/entry-server.js&#39;)).render
}
const appHtml = await render({ path: url })
const html = template.replace(&#39;&lt;!--ssr-outlet--&gt;&#39;, appHtml)
res.statusCode = 200
res.setHeader(&#39;Content-Type&#39;, &#39;text/html&#39;).end(html)
} catch (error) {
vite.ssrFixStacktrace(error)
next(error)
}
})
)
return { app }
}
bootstrap()
.then(async ({ app }) =&gt; {
await listen(toNodeListener(app), { port: 3001 })
})
.catch(console.error)

huangapple
  • 本文由 发表于 2023年6月12日 11:29:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76453494.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定