From 3e9038ee7e3cbe5f23f04e596f4798e965b64b1b Mon Sep 17 00:00:00 2001 From: nehhhhha6 Date: Sat, 29 Mar 2025 18:38:45 +0530 Subject: [PATCH 1/2] redirect-issue --- app/navigation.ts | 0 src/app/MdxLoader.jsx | 24 ++++++++++++++++++++++++ src/app/MdxWrapper.jsx | 27 +++++++++++++++++++++++++++ src/app/navigation.ts | 11 +++++++++++ src/app/page.jsx | 22 ++++++++++++++++++++++ src/app/utils/mdxUtils.js | 14 ++++++++++++++ 6 files changed, 98 insertions(+) create mode 100644 app/navigation.ts create mode 100644 src/app/MdxLoader.jsx create mode 100644 src/app/MdxWrapper.jsx create mode 100644 src/app/navigation.ts create mode 100644 src/app/page.jsx create mode 100644 src/app/utils/mdxUtils.js diff --git a/app/navigation.ts b/app/navigation.ts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/app/MdxLoader.jsx b/src/app/MdxLoader.jsx new file mode 100644 index 000000000000..065d18ba9926 --- /dev/null +++ b/src/app/MdxLoader.jsx @@ -0,0 +1,24 @@ +'use client' + +import React from 'react' + +// This will be a mapping object for all your MDX files +import StuffMdx from './stuff.mdx' +import AnotherMdx from './another.mdx' +// ... import all your MDX files + +const mdxComponents = { + './stuff.mdx': StuffMdx, + './another.mdx': AnotherMdx, + // ... map all your imports +} + +export default function MdxLoader({ filePath }) { + const Component = mdxComponents[filePath] + + if (!Component) { + return
MDX file not found: {filePath}
+ } + + return +} diff --git a/src/app/MdxWrapper.jsx b/src/app/MdxWrapper.jsx new file mode 100644 index 000000000000..c1e371c20a2f --- /dev/null +++ b/src/app/MdxWrapper.jsx @@ -0,0 +1,27 @@ +'use client' + +import React, { useState, useEffect } from 'react' + +export default function MdxWrapper({ filePath }) { + const [Component, setComponent] = useState(null) + const [error, setError] = useState(null) + + useEffect(() => { + async function loadMdx() { + try { + const module = await import(`${filePath}`) + setComponent(() => module.default) + } catch (err) { + console.error(`Error loading MDX file: ${filePath}`, err) + setError(err) + } + } + + loadMdx() + }, [filePath]) + + if (error) return
Error loading MDX content
+ if (!Component) return
Loading...
+ + return +} diff --git a/src/app/navigation.ts b/src/app/navigation.ts new file mode 100644 index 000000000000..b62c182388eb --- /dev/null +++ b/src/app/navigation.ts @@ -0,0 +1,11 @@ +import { redirect as nextRedirect } from 'next/dist/client/components/redirect' + +export function redirect(path: string): ReturnType { + if (path === '' || path === undefined) { + throw new Error( + 'Redirect path cannot be empty. This would cause an infinite loop.' + ) + } + + return nextRedirect(path) +} diff --git a/src/app/page.jsx b/src/app/page.jsx new file mode 100644 index 000000000000..d2ce51e1bd1f --- /dev/null +++ b/src/app/page.jsx @@ -0,0 +1,22 @@ +import { Suspense } from 'react' +// import { redirect } from './navigation' - removed + +// Instead of importing dynamically, create an async component +async function MdxContent({ filePath }) { + // This works in a server component + const { default: Content } = await import(`${filePath}`) + return +} + +export default function Home() { + // This will now throw an error instead of causing an infinite loop + // redirect(""); + + return ( +
+ Loading MDX...
}> + + + + ) +} diff --git a/src/app/utils/mdxUtils.js b/src/app/utils/mdxUtils.js new file mode 100644 index 000000000000..0cca0a530491 --- /dev/null +++ b/src/app/utils/mdxUtils.js @@ -0,0 +1,14 @@ +import fs from 'fs' +import path from 'path' + +// This function can be used at build time to generate a mapping of MDX files +export function getMdxFiles(dir) { + const mdxDir = path.join(process.cwd(), dir) + const filenames = fs.readdirSync(mdxDir) + const mdxFiles = filenames.filter((name) => name.endsWith('.mdx')) + + return mdxFiles.map((filename) => ({ + filename, + path: `${dir}/${filename}`, + })) +} From b3d5f88606450a33d3ed6800a745d13637a7574a Mon Sep 17 00:00:00 2001 From: naaa760 Date: Sun, 27 Jul 2025 20:52:24 +0530 Subject: [PATCH 2/2] fix: handle raw-loader CSS imports correctly Fixes #82000 - Next.js still imports CSS as styles even when loaded with raw-loader - Add webpack rules to handle raw-loader imports before CSS processing - Support multiple raw-loader patterns: ?raw, ?raw-loader, git add packages/next/src/build/webpack/config/blocks/css/index.ts test/integration/css-fixtures/raw-loader-import/next.config.js test/integration/css-fixtures/raw-loader-import/pages/index.js test/integration/css-fixtures/raw-loader-import/pages/styles.css test/integration/css-fixtures/raw-loader-import/test/raw-loader.test.jsraw-loader! - Return raw source content instead of processed CSS when using raw-loader - Add test fixture to verify raw-loader behavior When users import CSS with raw-loader (e.g., require('!!raw-loader!./foo.css')), they now get raw source content as expected instead of having styles applied. --- .../build/webpack/config/blocks/css/index.ts | 24 ++++++++++ .../raw-loader-import/next.config.js | 14 ++++++ .../raw-loader-import/pages/index.js | 44 ++++++++++++++++++ .../raw-loader-import/pages/styles.css | 14 ++++++ .../raw-loader-import/test/raw-loader.test.js | 46 +++++++++++++++++++ 5 files changed, 142 insertions(+) create mode 100644 test/integration/css-fixtures/raw-loader-import/next.config.js create mode 100644 test/integration/css-fixtures/raw-loader-import/pages/index.js create mode 100644 test/integration/css-fixtures/raw-loader-import/pages/styles.css create mode 100644 test/integration/css-fixtures/raw-loader-import/test/raw-loader.test.js diff --git a/packages/next/src/build/webpack/config/blocks/css/index.ts b/packages/next/src/build/webpack/config/blocks/css/index.ts index 198c35cbf002..5b7ed3b77a4a 100644 --- a/packages/next/src/build/webpack/config/blocks/css/index.ts +++ b/packages/next/src/build/webpack/config/blocks/css/index.ts @@ -204,6 +204,30 @@ export const css = curry(async function css( const fns: ConfigurationFn[] = [] + // Handle raw-loader imports before any CSS processing + // This prevents CSS files imported with raw-loader from being processed as CSS + fns.push( + loader({ + oneOf: [ + { + test: regexLikeCss, + resourceQuery: /raw/, + type: 'asset/source', + }, + { + test: regexLikeCss, + resourceQuery: /raw-loader/, + type: 'asset/source', + }, + { + test: regexLikeCss, + resourceQuery: /!!raw-loader!/, + type: 'asset/source', + }, + ], + }) + ) + const googleLoader = require.resolve( 'next/dist/compiled/@next/font/google/loader' ) diff --git a/test/integration/css-fixtures/raw-loader-import/next.config.js b/test/integration/css-fixtures/raw-loader-import/next.config.js new file mode 100644 index 000000000000..b84b3fb8f9e7 --- /dev/null +++ b/test/integration/css-fixtures/raw-loader-import/next.config.js @@ -0,0 +1,14 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + webpack: (config) => { + // This is the problematic configuration mentioned in the GitHub issue + // It should work with our fix + config.module.rules.push({ + resourceQuery: /raw/, + type: 'asset/source', + }) + return config + }, +} + +module.exports = nextConfig diff --git a/test/integration/css-fixtures/raw-loader-import/pages/index.js b/test/integration/css-fixtures/raw-loader-import/pages/index.js new file mode 100644 index 000000000000..79a1ff684cf8 --- /dev/null +++ b/test/integration/css-fixtures/raw-loader-import/pages/index.js @@ -0,0 +1,44 @@ +import React from 'react' + +// Import CSS with raw-loader - this should return raw source, not processed CSS +const rawCss = require('!!raw-loader!./styles.css') + +export default function HomePage() { + return ( +
+

Raw Loader Test

+

+ This page tests that CSS imported with raw-loader returns raw source + instead of processed CSS. +

+ +

Raw CSS Content:

+
+        {rawCss}
+      
+ +

Test Results:

+
    +
  • + If the CSS content above shows raw CSS (like{' '} + + .test {'{'} color: red; {'}'} + + ), the fix is working ✅ +
  • +
  • + If the page has a red background (from the CSS being applied), the fix + is not working ❌ +
  • +
+
+ ) +} diff --git a/test/integration/css-fixtures/raw-loader-import/pages/styles.css b/test/integration/css-fixtures/raw-loader-import/pages/styles.css new file mode 100644 index 000000000000..3f7475472afc --- /dev/null +++ b/test/integration/css-fixtures/raw-loader-import/pages/styles.css @@ -0,0 +1,14 @@ +/* This CSS file is imported with raw-loader */ +/* If the fix is working, this should be returned as raw text, not applied as styles */ + +body { + background-color: red !important; + color: white !important; +} + +.test { + color: red; + font-weight: bold; +} + +/* This should not be applied to the page when imported with raw-loader */ diff --git a/test/integration/css-fixtures/raw-loader-import/test/raw-loader.test.js b/test/integration/css-fixtures/raw-loader-import/test/raw-loader.test.js new file mode 100644 index 000000000000..1d562563d0a6 --- /dev/null +++ b/test/integration/css-fixtures/raw-loader-import/test/raw-loader.test.js @@ -0,0 +1,46 @@ +/* eslint-env jest */ +import { join } from 'path' +import { createNext, FileRef } from 'e2e-utils' +import { fetchViaHTTP } from 'next-test-utils' + +describe('Raw Loader CSS Import', () => { + let next + + beforeAll(async () => { + const files = { + 'pages/index.js': new FileRef(join(__dirname, '../pages/index.js')), + 'pages/styles.css': new FileRef(join(__dirname, '../pages/styles.css')), + 'next.config.js': new FileRef(join(__dirname, '../next.config.js')), + } + + next = await createNext({ + files, + dependencies: { + 'raw-loader': '^4.0.2', + }, + }) + }) + + afterAll(async () => { + await next.destroy() + }) + + it('should return raw CSS content instead of applying styles', async () => { + const res = await fetchViaHTTP(next.url, '/') + const html = await res.text() + + // The page should NOT have a red background (which would indicate CSS was applied) + expect(html).not.toContain('background-color: red') + + // The page should contain the raw CSS content + expect(html).toContain('/* This CSS file is imported with raw-loader */') + expect(html).toContain('body {') + expect(html).toContain('background-color: red !important;') + expect(html).toContain('.test {') + expect(html).toContain('color: red;') + + // The page should show the test instructions + expect(html).toContain('Raw Loader Test') + expect(html).toContain('If the CSS content above shows raw CSS') + }) +})