Next.js 全局 CSS 不能从自定义 <App> 以外的文件导入
Posted
技术标签:
【中文标题】Next.js 全局 CSS 不能从自定义 <App> 以外的文件导入【英文标题】:Next.js Global CSS cannot be imported from files other than your Custom <App> 【发布时间】:2020-07-11 11:44:18 【问题描述】:我的 React 应用运行良好,还使用了全局 CSS。
我运行了npm i next-images
,添加了一张图片,编辑了next.config.js
、ran npm run dev
,现在我收到了这条消息
Global CSS cannot be imported from files other than your Custom <App>. Please move all global CSS imports to pages/_app.js.
Read more: https://err.sh/next.js/css-global
我查看了文档,但我发现说明有点混乱,因为我是 React 新手。
另外,为什么现在会发生这个错误?你认为它与 npm install 有什么关系吗?
我已尝试删除与代码一起添加的新文件,但这并不能解决问题。我也尝试了阅读更多:建议。
我的最高层组件。
import Navbar from './Navbar';
import Head from 'next/head';
import '../global-styles/main.scss';
const Layout = (props) => (
<div>
<Head>
<title>Bitcoin Watcher</title>
</Head>
<Navbar />
<div className="marginsContainer">
props.children
</div>
</div>
);
export default Layout;
我的 next.config.js
// next.config.js
const withSass = require('@zeit/next-sass')
module.exports = withSass(
cssModules: true
)
我的 main.scss 文件
@import './fonts.scss';
@import './variables.scss';
@import './global.scss';
我的 global.scss
body
margin: 0;
:global
.marginsContainer
width: 90%;
margin: auto;
我觉得最奇怪的是,这个错误在没有改变任何与 CSS 或 Layout.js 相关的情况下就出现了,而且它以前可以工作?
我已将 main.scss 导入移至 pages/_app.js 页面,但样式仍未通过。这就是 _app.js 页面的样子
import '../global-styles/main.scss'
export default function MyApp( Component, props )
return <Component ...props />
【问题讨论】:
【参考方案1】:尝试在你的 scss 文件名中包含“.module”。
将main.scss
更改为main.module.scss
例子:
import styles from './todolist-profile-info.module.scss'
【讨论】:
【参考方案2】:Next.js
停止抱怨当您的文件命名为 module
时,例如,将 import '../global-styles/main.scss';
更改为 import '../global-styles/main.module.scss';
将修复警告,您可以将您的样式放在 global-styles
中,或者例如,在您的component
.
next.config.js
中不需要额外的依赖项/配置。
【讨论】:
【参考方案3】:将此添加到您的_app.js
import '../styles/globals.css'
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案4】:您无需在 next.config.js
内执行任何操作。
假设您正在使用像 Bootstrap 这样的全局 css,这意味着它包含的 css 旨在应用于您的整个应用程序以及其中的所有不同页面。
全局 css 文件必须以非常特殊的方式连接到 NextJS。
所以你需要在pages/
目录中创建_app.js
。
将文件命名为_app.js
至关重要。
然后在该文件的顶部,您将通过以下方式导入 Bootstrap css:
import 'bootstrap/dist/css/bootstrap.css';
然后您将添加以下内容:
export default ( Component, pageProps ) =>
return <Component ...pageProps />;
;
那么代码中发生了什么?
好吧,在幕后,每当您尝试使用 NextJS 导航到某个不同的页面时,NextJS 都会从您的 pages/
目录中的不同文件之一导入您的组件。
NextJS 不只是将您的组件显示在屏幕上。
相反,它将其封装在自己的自定义默认组件中,并在 NextJS 内部称为 App。
您通过定义_app.js
所做的是定义您自己的自定义应用程序组件。
因此,每当您尝试访问浏览器内的路由或根路由时,NextJS 都会导入该给定组件并将其作为 Component
属性传递给 AppComponent
。
所以Component
等于您在pages/
目录中拥有的任何组件。然后pageProps
将成为您打算传递给pages/
内部文件的一组组件。
长话短说,这个东西就像你试图在屏幕上显示的组件的薄包装。
你为什么要定义这个?
好吧,如果你想在项目中包含一些全局 css,例如 Bootstrap 是一个全局 css,你只能将全局 css 导入到 _app.js
文件中。
事实证明,如果你尝试访问其他组件或其他页面,NextJS 不会加载甚至解析这些文件。
因此,您可能在其中导入的任何 css 都不会包含在最终的 html 文件中。
所以你有一个必须包含在每个页面上的全局 css,它必须被导入到应用程序文件中,因为它是唯一保证每次用户访问你的应用程序时都会加载的文件。
不要忘记,除了在_app.js
中导入css,您还必须在终端中运行npm install bootstrap
。
您可以在此处阅读更多信息: https://nextjs.org/docs/messages/css-global
【讨论】:
【参考方案5】:使用内置的 Next.js CSS 加载器(参见here)
而不是旧版@zeit/next-sass
。
-
将
@zeit/next-sass
包替换为sass
。
删除next.config.js
。或者不要更改其中的 CSS 加载。
按照错误消息中的建议移动全局 CSS。
由于 Next.js 9.2 全局 CSS 必须在 Custom <App>
组件中导入。
// pages/_app.js
import '../global-styles/main.scss'
export default function MyApp( Component, pageProps )
return <Component ...pageProps />
要仅将样式添加到特定组件或页面,您可以使用对CSS 模块的内置支持。(请参阅here)
例如,如果您有一个组件 Button.js
,您可以创建一个 Sass 文件 button.module.scss
并将其包含在组件中。
【讨论】:
嘿,我之前创建了 main.scss 并将其移动到该文件,但它不起作用。我又试了一次,还是没有应用。我有以下代码: import '../global-styles/main.scss' export default function MyApp( Layout, props ) returnnode-sass
而不是@zeit/next-sass
,我刚刚对其进行了测试并更新了答案。如果您在命令行或浏览器的控制台中有任何特定错误,请告诉我。
这肯定有所作为。全局 css 现在在 _app.js 中工作。最后一件还没有工作的事情,以前工作的,是::global .marginsContainer width: 90%;边距:自动;
我来这个答案是因为我试图在组件中使用 scss。显然现在我需要将我的 scss 文件与 components/my-component/ 文件夹分开并将其放在页面中?我很困惑..
@AntonDozortsev,从 Next.js 9.2 开始(参见Next.js 9.2 Blog Post)。【参考方案6】:
您可以用您自己的替换过于固执己见且坦率地过度设计的 NextJs CSS 加载器。这是一个简单的全局css:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports =
reactStrictMode: true,
webpack: (config, buildId, dev, isServer, defaultLoaders, webpack ) =>
// Find and remove NextJS css rules.
const cssRulesIdx = config.module.rules.findIndex(r => r.oneOf)
if (cssRulesIdx === -1)
throw new Error('Could not find NextJS CSS rule to overwrite.')
config.module.rules.splice(cssRulesIdx, 1)
// Add a simpler rule for global css anywhere.
config.plugins.push(
new MiniCssExtractPlugin(
experimentalUseImportModule: true,
filename: 'static/css/[contenthash].css',
chunkFilename: 'static/css/[contenthash].css',
)
)
config.module.rules.push(
test: /\.css$/i,
use: !isServer ? ['style-loader', 'css-loader'] : [MiniCssExtractPlugin.loader, 'css-loader'],
)
return config
,
【讨论】:
【参考方案7】:对我来说,问题是因为我在我的 next.config.js
文件中使用了两个 module.exports,就像这样
const withPlugins = require('next-compose-plugins')
const sass = require('@zeit/next-sass')
const css = require('@zeit/next-css')
const nextConfig =
webpack: function(config)
config.module.rules.push(
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use:
loader: 'url-loader',
options:
limit: 100000,
name: '[name].[ext]'
)
return config
module.exports = withPlugins([
[css],
[sass,
cssModules: true
]
], nextConfig)
module.exports =
env:
MONGO_URI = 'your uri'
。 1
我修改了它,将导出模块改成这样。
const nextConfig =
webpack: function(config)
config.module.rules.push(
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use:
loader: 'url-loader',
options:
limit: 100000,
name: '[name].[ext]'
)
return config
,
env:
MONGO_URI: "your uri"
2
然后我删除了第二个module.exports
【讨论】:
请阅读 common.js 模块是如何工作的。第二个module.exports
覆盖第一个。您的第一个 NextJS 配置实际上没有得到应用。以上是关于Next.js 全局 CSS 不能从自定义 <App> 以外的文件导入的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 _app.js (Next.js) 中声明的全局 css 文件中的 css 类
next.js 我不知道如何将全局 .container css 样式应用到其他页面
如何在 react 和 next js 中使用 Styled 组件创建全局样式,使用 css 文件和 styled 组件的组合是不是更好?