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.jsran 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 &lt;App&gt; 组件中导入。

// 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 ) return @IndustryDesigns,尝试使用node-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 样式应用到其他页面

next js 中特定页面的全局样式

如何在 react 和 next js 中使用 Styled 组件创建全局样式,使用 css 文件和 styled 组件的组合是不是更好?

Next.JS:使用全局 scss 中的 SASS 变量

gradle / groovy:从自定义类调用“全局”函数