具有Material UI和自定义全局样式表的Nextjs

时间:2020-05-07 23:32:23

标签: material-ui next.js server-side-rendering

我使用带有export的Nextjs 9.3来生成静态站点。根据此参考实现(https://github.com/mui-org/material-ui/tree/master/examples/nextjs)设置了材料UI。

除了Material UI,我还有一个全局样式表style.css,根据文档(https://nextjs.org/docs/basic-features/built-in-css-support),该样式表imported_app.js中。

但是,在运行export之后,index.html仅包含Material UI中的styles.css中的CSS。 styles.css仅作为普通样式表加载,没有内联。还有什么方法可以将styles.css注入index.html以避免FOUC?

编辑 @Dekel要求的文件夹结构的相关部分:

├── pages
│   ├── _app.js
│   ├── _document.js
│   ├── index.js
├── public
└── src
    ├── components
    └── styles.css

1 个答案:

答案 0 :(得分:0)

如果您要查找的是通过以下方式将css文件连接并缩小到index.html中:

情况0

// index.html
...
<head>
  <style>
    <!-- your css concat + minified here -->
  </style>
</head>
...

而不是以这种方式

案例1

// index.html
<head>
  <link rel="stylesheet" href="path/to/bundle.min.css"/>
</head>

我认为您无法使用NextJS即用型解决方案“全局样式表的内置CSS支持”来实现这一目标。

在阅读9.2版(https://nextjs.org/blog/next-9-2#built-in-css-support-for-global-stylesheets)中的文档时说:

In production, all CSS files will be automatically concatenated into a single minified .css file. This CSS file will be loaded via a <link> tag and automatically injected into the default HTML markup Next.js generates.

因此,在我看来,您无法通过该解决方案实现Case 0


我遇到了FOUC的相同问题,这就是我通过Next管理SSR解决方案的方式:

  1. 帮助程序合并并缩小我需要的文件prepareInPageCss.js的功能,该文件保存了一个js模块,该模块返回带有捆绑的css的字符串,如下所示:
const minify = require('@node-minify/core');
const cleanCSS = require('@node-minify/clean-css');
const fs = require('fs');
const bootstrapOutPutPathName = './static/css/_tempBootstrap.min.js';
const commonOutPutPathName = './static/css/_tempCommon.min.js';
const outputnameCss = './static/css/InPageCssBundle.css';

(async () => {
 try {
   await minify({
     compressor: cleanCSS,
     input: './static/css/bootstrap.min.css',
     output: bootstrapOutPutPathName,
     options: {
       keepSpecialComments: '0'
     }
   });

   await minify({
     compressor: cleanCSS,
     input: './static/css/common.css',
     output: commonOutPutPathName,
     options: {
       keepSpecialComments: '0'
     }
   });

   let bootstrapTempCss = fs.readFileSync(bootstrapOutPutPathName, "utf-8");
   let commonTempCss = fs.readFileSync(commonOutPutPathName, "utf-8");

   fs.writeFileSync(outputnameCss, bootstrapTempCss + commonTempCss);
   fs.writeFileSync(outputname, "const bundledCss=String.raw`" + bootstrapTempCss + commonTempCss + "`; export default bundledCss;");
 } catch (e) {
   console.log(e);
 }
})()
  1. 在您项目的文件中,以这种方式完成的head结构在哪里:
   import commonCss from '../static/css/InPageCssBundle.js';
   const isDev = ENV === 'development';

   ...
    <title>{title}</title>
    <meta name='description' content={description}/>
    <meta charSet="utf-8"/>
    {isDev ? <>
       <link rel="stylesheet" href="/static/css/bootstrap.min.css"/>
       <link rel="stylesheet" href="/static/css/common.css"/>
     </> :
     <style>
       {commonCss}
     </style>
   }
   ...

每次创建新版本时,我都会运行node path/to/file/prepareInPageCss.js

现在,我不是100%肯定这是唯一的方法(我在9.0是Next时实现了这一点),但我还没有尝试静态导出,但是希望我至少给您一个后备解决方案。

欢呼