Next.js出现重复CSS Chunk,如何仅保留preload类型链接?
解决Next.js保留CSS Preload标签并移除重复Stylesheet标签的问题
这个问题其实是Next.js的默认优化行为导致的——它会自动为CSS资源生成preload预加载标签和stylesheet实际应用标签:前者用来提前拉取资源提升加载速度,后者负责渲染样式。如果你想只保留preload标签并确保样式正常生效,可以通过自定义_document.js来实现,具体步骤如下:
1. 自定义pages/_document.js文件
Next.js的_document.js是修改HTML文档结构的核心入口,我们可以在这里过滤并调整head中的链接标签。创建或修改该文件:
import Document, { Html, Head, Main, NextScript } from 'next/document' class MyDocument extends Document { static async getInitialProps(ctx) { const initialProps = await Document.getInitialProps(ctx) // 处理head中的链接标签:保留preload的CSS,添加onload事件,移除对应的stylesheet标签 initialProps.head = initialProps.head .map(elem => { // 为preload的CSS标签添加onload事件,加载完成后转为stylesheet if (elem.type === 'link' && elem.props.rel === 'preload' && elem.props.href.includes('/_next/static/css/styles.chunk.css')) { return { ...elem, props: { ...elem.props, onLoad: "this.onload=null;this.rel='stylesheet'" } } } // 移除对应的stylesheet标签 if (elem.type === 'link' && elem.props.rel === 'stylesheet' && elem.props.href.includes('/_next/static/css/styles.chunk.css')) { return null } return elem }) .filter(Boolean) // 过滤掉被标记为null的元素 return initialProps } render() { return ( <Html> <Head /> <body> <Main /> <NextScript /> </body> </Html> ) } } export default MyDocument
2. 关键细节说明
- 为什么要加
onload事件?:preload只是告诉浏览器提前加载资源,但不会自动解析应用样式。添加这个事件后,当CSS文件加载完成,会自动将rel属性改为stylesheet,让浏览器应用样式,避免页面无样式的问题。 - 适配多个CSS chunk:如果你的项目有多个CSS chunk文件,可以把
includes('/_next/static/css/styles.chunk.css')改成正则匹配,比如/^\/_next\/static\/css\/.*\.chunk\.css$/.test(elem.props.href),这样就能处理所有的CSS chunk文件。
3. 验证效果
重启你的Next.js开发服务器,查看页面的HTML源码,应该只会看到带有onload属性的preload标签,而对应的stylesheet标签已经被移除,同时页面样式能正常渲染。
内容的提问来源于stack exchange,提问作者Askhat
相关产品推荐
相关产品推荐

