在 Next JS 中使用 Webpack 创建将 URL 路径映射到组件的加载器
Create loader that maps URL path to a component using Webpack in Next JS
我想在 Next.js 中创建一个加载器,它使用 Webpack underhood 它是 next.config.js
配置文件,将为 /blog
路由和 Tutorial.js
加载 Blog.js
/tutorial
路线。
MDX 数据在 pages/
目录中。 pages/
包含 blog/
和 /tutorial
,它们有自己的 .mdx
个文件。
我的文件夹结构如下:
.
├── README.md
├── components
│ ├── Blog.js
│ ├── Image.js
│ └── Tutorial.js
├── jsconfig.json
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── blog
│ │ ├── hello-world
│ │ │ ├── Rustin_Cohle.jpg
│ │ │ └── index.mdx
│ │ └── shit-world
│ │ └── index.mdx
│ ├── blog.js
│ ├── index.js
│ ├── tutorial
│ │ └── console-log-in-javascript
│ │ └── index.mdx
│ └── tutorial.js
├── prettier.config.js
├── src
└── utils
├── blog
│ ├── getAllBlogPreviews.js
│ ├── getStaticPaths.js
│ └── getStaticProps.js
├── common
│ ├── getAllPreviews.js
│ ├── getStaticFilePaths.js
│ └── getStaticFileProps.js
├── date.js
├── mdxUtils.js
└── tutorial
├── getAllTutorialPreviews.js
├── getStaticPaths.js
└── getStaticProps.js
我的 next.config.js
文件如下所示:
const { createLoader } = require('simple-functional-loader')
const rehypePrism = require('@mapbox/rehype-prism')
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
})
module.exports = withBundleAnalyzer({
pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx'],
experimental: {
modern: true,
},
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]',
},
},
],
})
const mdx = [
options.defaultLoaders.babel,
{
loader: '@mdx-js/loader',
options: {
rehypePlugins: [rehypePrism],
},
},
]
config.module.rules.push({
test: /\.mdx$/,
oneOf: [
{
resourceQuery: /preview/,
use: [
...mdx,
createLoader(function (src) {
console.log('src ')
console.log(src)
console.log('src ')
if (src.includes('<!--more-->')) {
const [preview] = src.split('<!--more-->')
return this.callback(null, preview)
}
const [preview] = src.split('<!--/excerpt-->')
return this.callback(null, preview.replace('<!--excerpt-->', ''))
}),
],
},
{
test: /blog/,
use: [
...mdx,
createLoader(function (src) {
const content = [
'import Blog from "@/components/Blog"',
'export { getStaticProps } from "@/utils/blog/getStaticProps"',
'export { getStaticPaths } from "@/utils/blog/getStaticPaths"',
'console.log("/blog")',
src,
'export default (props) => <Blog meta={meta} {...props} />',
].join('\n')
if (content.includes('<!--more-->')) {
return this.callback(null, content.split('<!--more-->').join('\n'))
}
return this.callback(null, content.replace(/<!--excerpt-->.*<!--\/excerpt-->/s, ''))
}),
],
},
{
test: /tutorial/,
use: [
...mdx,
createLoader(function (src) {
const content = [
'import Tutorial from "@/components/Tutorial"',
'export { getStaticProps } from "@/utils/tutorial/getStaticProps"',
'export { getStaticPaths } from "@/utils/tutorial/getStaticPaths"',
'console.log("/tutorial")',
src,
'export default (props) => <Tutorial meta={meta} {...props} />',
].join('\n')
if (content.includes('<!--more-->')) {
return this.callback(null, content.split('<!--more-->').join('\n'))
}
return this.callback(null, content.replace(/<!--excerpt-->.*<!--\/excerpt-->/s, ''))
}),
],
},
],
})
return config
},
})
我正在使用 test: /blog/
和 test: /tutorial/
,但它不是那样工作的。我不确定如何让它发挥作用?
我已将我的完整代码上传到 Github 的 tailwind
分支 → https://github.com/deadcoder0904/blog-mdx-next/tree/tailwind which is adapted from https://github.com/tailwindlabs/blog.tailwindcss.com
如何让 blog/
使用 Blog.js
而 tutorial/
使用 Tutorial.js
?
我必须使用 Webpack 的包含功能,例如:
include: [path.resolve(__dirname, 'pages/blog')]
而不是
test: /blog/
& 同 tutorial
.
这是提交 → https://github.com/deadcoder0904/blog-mdx-next/commit/84ad0042de3ec229dd130ef2491511c5e3090110
我想在 Next.js 中创建一个加载器,它使用 Webpack underhood 它是 next.config.js
配置文件,将为 /blog
路由和 Tutorial.js
加载 Blog.js
/tutorial
路线。
MDX 数据在 pages/
目录中。 pages/
包含 blog/
和 /tutorial
,它们有自己的 .mdx
个文件。
我的文件夹结构如下:
.
├── README.md
├── components
│ ├── Blog.js
│ ├── Image.js
│ └── Tutorial.js
├── jsconfig.json
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── blog
│ │ ├── hello-world
│ │ │ ├── Rustin_Cohle.jpg
│ │ │ └── index.mdx
│ │ └── shit-world
│ │ └── index.mdx
│ ├── blog.js
│ ├── index.js
│ ├── tutorial
│ │ └── console-log-in-javascript
│ │ └── index.mdx
│ └── tutorial.js
├── prettier.config.js
├── src
└── utils
├── blog
│ ├── getAllBlogPreviews.js
│ ├── getStaticPaths.js
│ └── getStaticProps.js
├── common
│ ├── getAllPreviews.js
│ ├── getStaticFilePaths.js
│ └── getStaticFileProps.js
├── date.js
├── mdxUtils.js
└── tutorial
├── getAllTutorialPreviews.js
├── getStaticPaths.js
└── getStaticProps.js
我的 next.config.js
文件如下所示:
const { createLoader } = require('simple-functional-loader')
const rehypePrism = require('@mapbox/rehype-prism')
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
})
module.exports = withBundleAnalyzer({
pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx'],
experimental: {
modern: true,
},
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]',
},
},
],
})
const mdx = [
options.defaultLoaders.babel,
{
loader: '@mdx-js/loader',
options: {
rehypePlugins: [rehypePrism],
},
},
]
config.module.rules.push({
test: /\.mdx$/,
oneOf: [
{
resourceQuery: /preview/,
use: [
...mdx,
createLoader(function (src) {
console.log('src ')
console.log(src)
console.log('src ')
if (src.includes('<!--more-->')) {
const [preview] = src.split('<!--more-->')
return this.callback(null, preview)
}
const [preview] = src.split('<!--/excerpt-->')
return this.callback(null, preview.replace('<!--excerpt-->', ''))
}),
],
},
{
test: /blog/,
use: [
...mdx,
createLoader(function (src) {
const content = [
'import Blog from "@/components/Blog"',
'export { getStaticProps } from "@/utils/blog/getStaticProps"',
'export { getStaticPaths } from "@/utils/blog/getStaticPaths"',
'console.log("/blog")',
src,
'export default (props) => <Blog meta={meta} {...props} />',
].join('\n')
if (content.includes('<!--more-->')) {
return this.callback(null, content.split('<!--more-->').join('\n'))
}
return this.callback(null, content.replace(/<!--excerpt-->.*<!--\/excerpt-->/s, ''))
}),
],
},
{
test: /tutorial/,
use: [
...mdx,
createLoader(function (src) {
const content = [
'import Tutorial from "@/components/Tutorial"',
'export { getStaticProps } from "@/utils/tutorial/getStaticProps"',
'export { getStaticPaths } from "@/utils/tutorial/getStaticPaths"',
'console.log("/tutorial")',
src,
'export default (props) => <Tutorial meta={meta} {...props} />',
].join('\n')
if (content.includes('<!--more-->')) {
return this.callback(null, content.split('<!--more-->').join('\n'))
}
return this.callback(null, content.replace(/<!--excerpt-->.*<!--\/excerpt-->/s, ''))
}),
],
},
],
})
return config
},
})
我正在使用 test: /blog/
和 test: /tutorial/
,但它不是那样工作的。我不确定如何让它发挥作用?
我已将我的完整代码上传到 Github 的 tailwind
分支 → https://github.com/deadcoder0904/blog-mdx-next/tree/tailwind which is adapted from https://github.com/tailwindlabs/blog.tailwindcss.com
如何让 blog/
使用 Blog.js
而 tutorial/
使用 Tutorial.js
?
我必须使用 Webpack 的包含功能,例如:
include: [path.resolve(__dirname, 'pages/blog')]
而不是
test: /blog/
& 同 tutorial
.
这是提交 → https://github.com/deadcoder0904/blog-mdx-next/commit/84ad0042de3ec229dd130ef2491511c5e3090110