在Next JS中使用`next-mdx-remote`时,如何在`public/`文件夹外的`.mdx`文件中使用图像?

dea*_*904 5 javascript reactjs next.js mdxjs

我正在使用next-mdx-remote创建一个博客,并希望在.mdx文件public/夹外的文件中使用图像。

这是我的博客项目的完整代码?https://github.com/deadcoder0904/blog-mdx-remote

我有以下文件夹结构:

.
??? package-lock.json
??? package.json
??? pages
?   ??? _app.js
?   ??? blog
?   ?   ??? [slug].js
?   ??? dark.css
?   ??? index.js
?   ??? new.css
??? posts
?   ??? blog
?   ?   ??? hello-world
?   ?   ?   ??? Rustin_Cohle.jpg
?   ?   ?   ??? index.mdx
?   ?   ??? shit-world
?   ?       ??? index.mdx
?   ??? tutorials
?       ??? console-log-in-javascript
?           ??? index.mdx
??? utils
    ??? mdxUtils.js
Run Code Online (Sandbox Code Playgroud)

我的所有内容都在posts/文件夹中。

我有 2 个文件夹:blog/&tutorials/

每篇文章都在它们自己的文件夹中,blog/或者tutorials/这些文件夹中的每一个都包含在该特定文章中使用的图像。

例如,在hello-world文件夹中,有 1 张名为 的图像Rustin_Cohle.jpg

我想在hello-world/index.mdx文件中使用这个图像,但我无法做到。

我不能使用importrequire因为它是next-mdx-remote.

我尝试使用称为在下面使用的自定义组件并将Imageimg传递给hydrate但它也不起作用。

组件/Image.js

.
??? package-lock.json
??? package.json
??? pages
?   ??? _app.js
?   ??? blog
?   ?   ??? [slug].js
?   ??? dark.css
?   ??? index.js
?   ??? new.css
??? posts
?   ??? blog
?   ?   ??? hello-world
?   ?   ?   ??? Rustin_Cohle.jpg
?   ?   ?   ??? index.mdx
?   ?   ??? shit-world
?   ?       ??? index.mdx
?   ??? tutorials
?       ??? console-log-in-javascript
?           ??? index.mdx
??? utils
    ??? mdxUtils.js
Run Code Online (Sandbox Code Playgroud)

页面/博客/[slug].js

export const Image = ({ src, alt }) => (
    <img style={{ backgroundColor: 'red' }} src={src} alt={alt} />
)
Run Code Online (Sandbox Code Playgroud)

以下 MDX 文件使用上述Image组件作为通过hydrate.

你好世界/index.mdx

---
title: Hello World
date: '2019-09-06T14:54:37.229Z'
tags: ['hello', 'world']
author: John Doe
description: This is the first post
---

Hey this is my first post

![Rustin Cohle](./Rustin_Cohle.jpg)

<img src="./Rustin_Cohle.jpg" alt="Rust Cohle" />

<Image src="./Rustin_Cohle.jpg" alt="Rust Cohle" />

This is the end of the first post
Run Code Online (Sandbox Code Playgroud)

我什至尝试使用MDXProvider& 它也不起作用。

页面/index.js

import hydrate from 'next-mdx-remote/hydrate'
import { Image } from '../components/Image'

const components = { Image }

const Blog = ({ source, frontMatter }) => {
  const content = hydrate(source, { components })
  return (
    <div>
      <h1>{frontMatter.title}</h1>
      {content}
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

那我如何使用图像?我希望它们只在特定帖子的文件夹中,就像hello-world博客只在hello-world/文件夹中包含它的图像一样。

Tul*_*ria 5

我能够在这种情况下加载图像。我的想法是使用 webpackfile-loader来实现这一点,并向组件映射添加更多信息,告知当前帖子的放置位置(注意组件功能)。

我的页面 [slug].js 是这样的:

import renderToString from 'next-mdx-remote/render-to-string'
import hydrate from 'next-mdx-remote/hydrate'
import matter from 'gray-matter'

import { getAllPostSlugs, getPostdata } from '../lib/posts'

const components = (slug) => ({
  h1: ({ children }) => <h1>{children}</h1>,
  img: ({ src, alt }) => {
    return (
      <p>
        <img
          alt={alt}
          src={require('../content/' + slug + '/' + src).default}
        />
      </p>
    )
  }
})

const Post = ({ source, frontMatter, slug }) => {
  const content = hydrate(source, {
    components: components(slug)
  })
  return (
    <>
      <h1>Post</h1>
      <p>{content}</p>
    </>
  )
}

export async function getStaticPaths() {
  const paths = getAllPostSlugs()
  return {
    paths,
    fallback: false
  }
}

export async function getStaticProps({ params }) {
  const postContent = await getPostdata(params.slug)
  const { data, content } = matter(postContent)
  const mdxSource = await renderToString(content, {
    components: components(params.slug),
    scope: data
  })
  return {
    props: {
      slug: params.slug,
      source: mdxSource,
      frontMatter: data
    }
  }
}

export default Post
Run Code Online (Sandbox Code Playgroud)

还有我的 next.config.js:

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.(svg|png|jpe?g|gif|mp4)$/i,
      use: [
        {
          loader: 'file-loader',
          options: {
            publicPath: '/_next',
            name: 'static/media/[name].[hash].[ext]'
          }
        }
      ]
    })
    return config
  }
}
Run Code Online (Sandbox Code Playgroud)

Ps:它就像下一个/图像的魅力:)

  • 您好 - 这里是 next-mdx-remote 的作者。只是顺便说一句,这是一个非常酷的想法和实现。图里奥干得好! (2认同)

dea*_*904 3

不幸的是,这是不可能的,因为next-mdx-remote将 markdown 内容视为数据并且根本不通过 Webpack :(

  • 大家好,我是 next-mdx-remote 的作者——只是确认这是真的。我的建议是使用“public”文件夹中的图像。 (4认同)