I want to create a loader in Next.js which uses Webpack underhood it's next.config.js
config file that will load Blog.js
for /blog
route & Tutorial.js
for /tutorial
route.
The MDX data is in pages/
directory. pages/
contains blog/
& /tutorial
which have their own .mdx
files.
My folder structure is as follows:
.
├── 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
My next.config.js
file looks like:
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
},
})
I am using test: /blog/
& test: /tutorial/
but it doesn't work that way. I am not sure how I can make it work?
I have the uploaded my complete code on the tailwind
branch at Github → https://github.com/deadcoder0904/blog-mdx-next/tree/tailwind which is adapted from https://github.com/tailwindlabs/blog.tailwindcss.com
How do I make it that blog/
uses Blog.js
& tutorial/
uses Tutorial.js
?
I had to use Webpack's include feature like:
instead of
& same with
tutorial
.Here's the commit → https://github.com/deadcoder0904/blog-mdx-next/commit/84ad0042de3ec229dd130ef2491511c5e3090110