NextJS 组件级 SASS 样式

Posted

技术标签:

【中文标题】NextJS 组件级 SASS 样式【英文标题】:NextJS component level SASS styling 【发布时间】:2020-06-30 07:23:26 【问题描述】:

我正在开发一个简单的 NextJS 应用程序,但在使用 SASS/SCSS 进行组件级样式设置时遇到了问题。当用户第一次登陆页面时一切看起来都很好,但是当用户导航到页面 /about 或从 /about/ 时,组件样式没有得到渲染,用户需要刷新页面查看样式????

⚙️ 设置

./package.json

"dependencies": 
  "@zeit/next-css": "1.0.1",
  "@zeit/next-sass": "1.0.1",
  "autoprefixer": "^9.7.0",
  "next": "^9.3.1",
  "node-sass": "4.13.1",
  "react": "^16.13.0",
  "react-dom": "^16.13.0",
  "webpack": "^4.42.0"

./next.config.js

const webpack = require('webpack');
const withSass = require('@zeit/next-sass');
const withCss = require('@zeit/next-css');

module.exports = withCss(
  withSass(
    webpack(config) 
      config.module.rules.push(
        test: /\.(eot|woff?2|ttf|otf|svg|png|jpe?g|gif)$/,
        use: 
          loader: 'url-loader',
          options: 
            limit: 100000,
          ,
        ,
      );
      return config;
    ,
  ),
);

./postcss.config.js

const autoprefixer = require('autoprefixer');

module.exports = 
  plugins: [autoprefixer],
;

???? 页数

./pages/index.js

import React from 'react';
import Layout from '../components/Layout';
import Home from '../components/Home';

class Index extends React.PureComponent 
  render() 
    <Layout>
      <Home />
    </Layout>
  


export default Index;

./pages/about.js

import React from 'react';
import Layout from '../components/Layout';
import Company from '../components/Company';

class About extends React.PureComponent 
  render() 
    <Layout>
      <Company />
    </Layout>
  


export default About;

???? 组件

./components/Layout.js

import React from 'react';
import AppBar from '../AppBar/AppBar';
import './Layout.scss';

class Layout extends React.PureComponent 
  render() 
    const  children  = this.props;

    return (
      <>
        <AppBar />
        <main className="Layout">
          children
        </main>
      </>
    );
  


export default Layout;

./components/Layout.scss

.Layout 
  background: #f00;

./components/AppBar.js

import Link from 'next/link';
import './AppBar.scss';

export default () => (
  <header className="AppBar">
    <Link href="/">
      <a>Home</a>
    </Link>
    <Link href="/about">
      <a>About</a>
    </Link>
  </header>
)

./components/AppBar.scss

.AppBar 
  background: #0f0;

./components/Home.js

import './Home.scss';

export default () => (
  <div className="Home">Home</div>
)

./components/Home.scss

.Home 
  background: #00f;

./components/Company.js

import './Company.scss';

export default () => (
  <div className="Company">Company</div>
)

./components/Company.scss

.Company 
  background: #ff0;

【问题讨论】:

你能看到请求文件的“网络”标签吗? 用户从a导航到b时,没有css请求,但是当用户刷新页面时,有http://localhost:3000/_next/static/css/styles.chunk.css?ts=158...的css请求???? 认为您应该将其作为“变量”导入,然后调用它,如下所示:import css from "../styles.scss" export default () =&gt; &lt;div className=css.example&gt;Hello World!&lt;/div&gt; 我尝试将它作为一个模块 &lt;Component className=styles.Name /&gt;/,同样的问题正在发生。另外,在我的一个 SCSS 中,我正在导入模块 CCSS。 ?????? 【参考方案1】:

这就是我解决问题的方法。 ?

随着 Next.js 9.3 的发布,不再需要 @zeit/next-sass@zeit/next-css。 ? 我还执行以下操作:

styled-jsx-plugin-sass node-sassa 添加为 dev-dep 创建一个.babelrc 文件并添加以下内容:

  "presets": [
    [
      "next/babel",
      
        "styled-jsx": 
          "plugins": ["styled-jsx-plugin-sass"]
        
      
    ]
  ]

所以我有两种选择:

&lt;style jsx&gt; 上添加我的 sass/scss 将我的组件 sass/scss 文件重命名为 &lt;ComponentName&gt;.module.scss

第二个选项是A的一个痛点,你需要import styles from './ComponentName.module.scss并将元素类添加为className=styles.ComponentNameclassName=styles['ComponentName-button']。 ?

【讨论】:

是的,这很好,但是如果我想同时使用 CSS 框架类和自定义组件类,例如。 className="col-sm-4 bg-success mycomponent__custom-class" 好吧,既然col-sm-4 bg-success 是全球性的,你可以这样做className='col-sm-4 bg-success $styles['ComponentName-custom']' ? 我同意导入 .module.scss 文件并将 classNames 添加到所有内容中很痛苦。你知道你是否可以像 Create-React-App 这样配置 NextJS,你所要做的就是导入 .scss 文件?我宁愿只使用 .scss 文件而不是 .module.scss 或 styled-jsx。 Nextjs repo 本身就有这个 issue 的票,你可以定期查看更新?github.com/vercel/next.js/discussions/14672【参考方案2】:

对于在 nextjs 11 之后寻找有效答案的任何人。您可以参考此repo,或阅读此article 中的完整详细信息

这是我使用过的完整的下一个配置代码

const withTM = require('next-transpile-modules')([]);

const withPlugins = require('next-compose-plugins');

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = withPlugins([withTM], 
  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(
        // Options similar to the same options in webpackOptions.output
        // both options are optional
        filename: 'static/chunks/pages/[contenthash].css',
        chunkFilename: 'static/chunks/pages/[contenthash].css',
      ),
    );

    config.module.rules.push(
      test: /\.(sa|sc|c)ss$/i,
      use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
    );

    config.module.rules.push(
      test: /\.tsx/,
      use: [defaultLoaders.babel],
    );

    return config;
  ,
);

【讨论】:

以上是关于NextJS 组件级 SASS 样式的主要内容,如果未能解决你的问题,请参考以下文章

Angular2 模块级样式表

NextJs - 导出使用样式组件的应用程序时出错

带有样式组件的 Nextjs 不通过主题

当浏览器样式与 nextjs 中带有情感样式组件的服务器不同时,样式不适用于第一个客户端渲染(也不是之后)

如何使用样式化组件和 SASS 设置材质 ui 下一个组件的样式

如何使用来自@mui/material 的样式使情感组件选择器在 nextjs 应用程序中工作?