如何在"公共/"文件夹之外的".mdx"文件中使用图像,同时在Next JS中使



我正在使用next-mdx-remote制作博客,并希望使用public/文件夹之外的.mdx文件中的图像。

这是我的博客项目的完整代码→ 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

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

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

每个帖子都在blog/tutorials/内自己的文件夹中,每个文件夹都包含该特定帖子中使用的图像。

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

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

我不能使用importrequire,因为它是next-mdx-remote的限制。

我尝试使用一个名为Image的自定义组件,该组件在下面使用img并将其传递给hydrate但它也不起作用。

组件/图像.js

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

页面/博客/[蛞蝓].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>
)
}

以下 MDX 文件使用通过hydrate传递的上述Image组件。

hello-world/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

我什至尝试使用MDXProvider,但它也没有用。

页数/索引.js

import { MDXProvider } from '@mdx-js/react'
const components = { Image }
const HomePage = ({ posts }) => {
return (
<MDXProvider components={components}>
...
</MDXProvider>
)
}

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

在这种情况下,我能够加载图像。我的想法是使用 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

我的下一个.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
}
}

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

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

请注意,从Next.js v11开始,您可以将任何目录中的图像导入到mdx文件中,而无需任何其他配置 - 参考1和参考2

最新更新