5

希望你们都玩得开心。我正在开发一个简单的 NextJs 应用程序,我想在其中包含多个子域。我正在vercel上部署应用程序。

我的应用程序所做的是它有一个简单的文本区域,您可以在其中编写 MDX,单击“发布”按钮,它将将该 MDX 保存到 firebase firestore。在文本区域下方,它显示了之前发布的所有页面的列表。

应用程序呈现所有页面的列表,例如随机生成的页面名称作为子域,而实际域稍后出现,如下所示。

a-mdx-page.mydomain.app

当我打开该 URL 时,它将从 firestore 获取页面 MDX 并使用 next-mdx-remote 包来序列化和呈现 MDX。使用 next-mdx-remote 包的原因是我们可以在 MDX 中添加 react 组件,它可以像普通的 react 组件一样渲染。我已经有一个自定义域,因为您不能在 vercel 免费部署中的免费子域之上拥有一个子域。

在 localhost 上一切正常,一切正常,但问题是当我在 Vercel 上部署代码并导航到子域时,它在网站上显示 ERROR 500 并在日志中显示以下错误。

[GET] /   21:21:03:30

2021-10-24T16:21:04.018Z    8e52d5da-ff1f-4840-a09b-199233834a5d    ERROR   Error: The package "esbuild-linux-64" could not be found, and is needed by esbuild.
If you are installing esbuild with npm, make sure that you don't specify the
"--no-optional" flag. The "optionalDependencies" package.json feature is used
by esbuild to install the correct binary executable for your current platform.
    at generateBinPath (/var/task/node_modules/esbuild/lib/main.js:1643:15)
    at esbuildCommandAndArgs (/var/task/node_modules/esbuild/lib/main.js:1699:11)
    at ensureServiceIsRunning (/var/task/node_modules/esbuild/lib/main.js:1856:25)
    at Object.transform (/var/task/node_modules/esbuild/lib/main.js:1751:37)
    at serialize (/var/task/node_modules/next-mdx-remote/dist/serialize.js:287:43)
    at async getServerSideProps (/var/task/.next/server/pages/index.js:261:25)
    at async Object.renderToHTML (/var/task/node_modules/next/dist/server/render.js:428:24)
    at async doRender (/var/task/node_modules/next/dist/server/next-server.js:1144:38)
    at async /var/task/node_modules/next/dist/server/next-server.js:1236:28
    at async /var/task/node_modules/next/dist/server/response-cache.js:64:36 {
  page: '/'
}
RequestId: 8e52d5da-ff1f-4840-a09b-199233834a5d Error: Runtime exited with error: exit status 1
Runtime.ExitError

据我了解,next-mdx-remote 序列化函数在其中使用 esbuild,当我在 vercel 上部署应用程序时,npm 只是不下载它的平台特定包,但可能是我错了。

我试图为此搜索解决方案,但没有任何答案可以帮助我。

以下是应用程序使用的所有代码。

import { useState } from "react"
import { collection, doc, getDoc, getDocs, setDoc } from "firebase/firestore"
import matter from "gray-matter"
import { MDXRemote } from "next-mdx-remote"
import { serialize } from "next-mdx-remote/serialize"
import {
  uniqueNamesGenerator,
  adjectives,
  colors,
  animals,
} from "unique-names-generator"

import { db } from "../utils/fire-client"
import Layout from "../components/Layout"
import { HOSTNAME } from "../config"
import MDXComponents from "../components/mdx"

export default function Index({ posts, isPage = false, mdxSource }) {
  const [mdxCode, setMdxCode] = useState("# THIS IS MDX")
  const [message, setMessage] = useState("")

  const addPageToCollection = async (name, content) => {
    const pagesCollection = collection(db, "pages")
    await setDoc(doc(pagesCollection, name), {
      name,
      content,
    })
  }

  function publishPage() {
    const randomName = uniqueNamesGenerator({
      dictionaries: [adjectives, colors, animals],
    })

    addPageToCollection(randomName, mdxCode)
    setMessage(
      "New Page Added: " + randomName + "\nReload page To see it in the list"
    )

    setTimeout(() => {
      setMessage("")
    }, 5000)
  }

  return (
    <Layout>
      {isPage ? (
        <>
          <header>
            <nav>
              <a href={"http://" + HOSTNAME}>
                <a> Go back home</a>
              </a>
            </nav>
          </header>
          <main>
            <MDXRemote {...mdxSource} components={MDXComponents} />
          </main>
        </>
      ) : (
        <>
          <h1>Home Page</h1>

          <textarea
            name="mdxCode"
            id="mdxCode"
            value={mdxCode}
            onChange={(e) => setMdxCode(e.target.value)}
            className="w-full h-1/2 border-2 border-gray-400 p-2"
          />

          <button className="btn btn-primary" onClick={publishPage}>
            Publish
          </button>

          <div>{message}</div>

          <ul>
            <div className="mt-4 font-bold">Pages List</div>
            {posts.map((post) => (
              <li key={post.name}>
                <a href={`http://${post.name}.${HOSTNAME}`}>{post.name}</a>
              </li>
            ))}
          </ul>
        </>
      )}
    </Layout>
  )
}

export async function getServerSideProps({ req, res }) {
  const host = req.headers.host.split(".")

  if (host[0] !== HOSTNAME.split(".")[0] && host[0] !== "www") {
    const docRef = doc(db, "pages", host[0])
    const docSnap = await getDoc(docRef)

    if (docSnap.exists()) {
      const { content, data } = matter(docSnap.data().content)
      const mdxSource = await serialize(content, {
        // Optionally pass remark/rehype plugins
        mdxOptions: {
          remarkPlugins: [],
          rehypePlugins: [],
        },
        scope: data,
      })

      if (mdxSource) {
        return {
          props: {
            isPage: true,
            mdxSource,
          },
        }
      }
    } else {
      return {
        props: {
          redirect: {
            destination: "/",
          },
        },
      }
    }
  }

  const pagesCollection = collection(db, "pages")
  const pagesSnapshot = await getDocs(pagesCollection)
  const pagesList = pagesSnapshot.docs.map((doc) => doc.data())

  if (pagesList.length > 0) {
    return {
      props: {
        posts: pagesList,
      },
    }
  }

  return { props: { posts } }
}
4

1 回答 1

0

将 esbuild 更新到 0.13.4 或更高版本

npm i -D esbuild@0.13.4

见:https ://github.com/evanw/esbuild/releases/tag/v0.13.4

于 2021-11-19T14:43:18.870 回答