I'm using React, Next JS, and styled-components. Right now I've followed the documentation and have the following file structure. I want to simply get a global CSS working on a STATIC HTML page. I expected Next JS's SSG to work properly. Please DO NOT tell me to use a server. I know that's an easy fix. I want to get this working on a local static page I open from my file explorer.
pages/
_app.tsx
_document.tsx
index.tsx
styles/core.css
I am very simply importing a core.css in my _app.tsx
import { AppProps } from 'next/app';
import '../styles/core.css';
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
export default MyApp;
Now when I go and generate a page via SSG (I do not want to use a server), the generated HTML file has these 2 lines in it
<link rel="preload" href="/_next/static/css/4da684a704d068a3.css" as="style" crossorigin=""/>
<link rel="stylesheet" href="/_next/static/css/4da684a704d068a3.css" crossorigin="" data-n-g=""/>
When I go to open the index.html the console shows this error
Access to CSS stylesheet at 'file:///C:/_next/static/css/4da684a704d068a3.css' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome-untrusted, https, edge.
How do I solve this issue? Changing the HTML line to
<link rel="stylesheet" href="_next/static/css/4da684a704d068a3.css">
makes it work. Please help, I cannot find anything online.
Here's my _document.tsx if it helps
import Document, { Head, Html, Main, NextScript, DocumentContext, DocumentInitialProps } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () => originalRenderPage({
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
}
} finally {
sheet.seal()
}
}
}
Here's my config
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
output: 'export',
compiler: {
styledComponents: true,
},
}
module.exports = nextConfig
I wish there were a better solution. Here's what I ended up doing if anyone else ever faces this same niche issue.
const fs = require('fs');
const cheerio = require('cheerio');
// Read the generated HTML file
const html = fs.readFileSync('./out/target.html', 'utf8');
// Load the HTML into cheerio
const $ = cheerio.load(html);
// Find all <link> tags with crossorigin attribute and remove it
$('link[crossorigin]').removeAttr('crossorigin');
$('script[crossorigin]').removeAttr('crossorigin');
// Write the modified HTML back to the file
fs.writeFileSync('./out/target.html', $.html(), 'utf8');
I run this JS file whenever I build.
next build && node ./scripts/modify_html.js