#reactjs #next.js #vercel #mdxjs
Вопрос:
Надеюсь, вы все хорошо проводите время. Я работаю над простым приложением NextJS, в котором я хочу иметь несколько поддоменов. Я развертываю приложение на vercel.
Что делает мое приложение, так это то, что у него есть простая текстовая область, в которой вы пишете многомерные выражения, нажимаете кнопку публикации, и это сохранит это многомерное выражение в firebase firestore. Под текстовой областью отображается список всех страниц, которые были опубликованы ранее.
Приложение отображает список всех страниц, например, с именем страницы, которая генерируется случайным образом в качестве поддомена, в то время как фактический домен появляется позже, как показано ниже.
a-mdx-page.mydomain.app
Когда я открываю этот URL-адрес, он извлекает многомерные выражения страницы из firestore и использует пакет next-mdx-remote для сериализации и отображения многомерных выражений. Причина использования пакета next-mdx-remote заключается в том, что мы можем добавлять компоненты react в MDX, и он может отображаться как обычные компоненты react. У меня уже есть пользовательский домен, потому что вы не можете иметь поддомен поверх свободного поддомена в vercel free deployment.
На локальном хосте все работает нормально, и все так, как должно быть, но проблема в том, что когда я развертываю код на Vercel и перехожу к поддомену, он показывает ОШИБКУ 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 serialize использует в нем 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] amp;amp; 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 } }
}
Ответ №1:
Обновите esbuild до версии 0.13.4 или выше
npm i -D esbuild@0.13.4
Смотрите: https://github.com/evanw/esbuild/releases/tag/v0.13.4