使用 Sass 反应服务器端渲染

Posted

技术标签:

【中文标题】使用 Sass 反应服务器端渲染【英文标题】:React Server Side Rendering with Sass 【发布时间】:2018-10-02 05:33:54 【问题描述】:

正如我已经搜索过以前但找不到任何相关/已解决的问题,所以我问...

当前堆栈:React、express/node、Sass、Webpack、Sass。

在服务器将页面发送到浏览器之前,我有一个特定于页面样式的问题。

样式在浏览器中运行良好,我的意思是当通过浏览器路由器导航页面时,所有样式都可以正常工作。但是,我需要想办法在服务器将页面发送到浏览器之前将自定义 Sass 样式注入页面。

当前行为:我从浏览器访问任何页面,我会以正确的样式为页面提供服务,但是在页面上显示正确的样式有一点延迟。如果以慢动作查看,页面出现时没有样式(因为服务器发送的页面没有样式),然后浏览器以正确的样式接管。

我尝试过 webpack 在单独的文件中生成所有样式,但在服务器将其发送到浏览器之前,我似乎无法将此文件链接到页面。

任何帮助/反馈将不胜感激?

server.js(路由处理程序)

app.get('*', (req, res) => 
  const store = createStore();

  const promises = matchRoutes(Routes, req.path).map(( route ) => 
    return route.loadData ? route.loadData(store) : null;
);

Promise.all(promises)
.then(() => 
  const context = ;
  const content = renderer(req, store, context);

  if (context.notFound) res.status(404);

  res.send(content);
 );
);

const PORT = process.env.PORT || 3000;

renderer.js

import React from 'react';
import  renderToString  from 'react-dom/server';
import  StaticRouter, matchPath  from 'react-router-dom';
import  Provider  from 'react-redux';
import  renderRoutes  from 'react-router-config';
import serialize from 'serialize-javascript';
import Routes from '../client/Routes';

export default (req, store, context) => 

  // req.path is the url that the user is trying to access
  const content = renderToString(
  <Provider store=store>
   <StaticRouter location=req.path context=context>
    <div>
       renderRoutes(Routes) 
    </div>
   </StaticRouter>
 </Provider>
);

return `
  <html>
    <head>
      <link rel="stylesheet" href="../../public/styles.css">
    </head>
    <body>
      <div id='app'>$content</div>
      <script>
        window.INITIAL_STATE = $serialize(store.getState())
      </script>
      <script src="bundle.js"></script>
    </body>
  </html>
`;
;

webpack.config.js(我省略了其余的配置,因为它不相关)

const extractSass = new ExtractTextPlugin(
  filename: "styles.css",
  disable: process.env.NODE_ENV === "development"
);

module: 
rules: [
    test: /\.scss$/,
    use: extractSass.extract(
        use: [
            loader: "css-loader"
        , 
            loader: "sass-loader"
        ],
        // use style-loader in development
        fallback: "style-loader"
    )
  ]
,
plugins: [ extractSass ],

这在我的/build 文件夹中为我提供了一个styles.css 文件。我怎样才能将它链接到我的html。如果我尝试抛出 &lt;link&gt; 标签,浏览器将无法识别该文件。

【问题讨论】:

【参考方案1】:

我终于通过创建另一个路由处理程序解决了这个问题。

app.get('/styles.css', (req, res) => 
  res.sendFile(__dirname + "/" + "styles.css");
);

我的 webpack 编译了一个 styles.css 文件,该文件被放入 /public 文件夹中。请注意,我将 webpack 中样式文件的路径更改为:../public/styles.css

app.use(express.static('public'));

上述语句 ^^^ 使styles.css 文件可访问,最后通过在服务器对浏览器的响应中提供以下&lt;link&gt; 标记来应用样式。

<link rel="stylesheet" href="../../public/styles.css">

如果其他人有更好的解决方案,我很乐意得到反馈。

【讨论】:

感谢@Ash,这也是我最终解决它的方法。我正在研究使用 github.com/zeit/styled-jsx 的其他解决方案,但您的解决方案要简单得多。 很高兴你能弄明白。还有另一种方法似乎更简单一些。通过 webpack 将你的 css 编译成它自己的文件。并在你的反应根目录中要求该文件index.js 您也可以使用styled components,这将产生一个内联css,因此用户将保存css文件所需的请求

以上是关于使用 Sass 反应服务器端渲染的主要内容,如果未能解决你的问题,请参考以下文章

尽管所有反应路由器版本冲突,如何在反应中进行服务器端渲染?

如何在反应服务器端渲染中正确处理 window=undefined 错误

如何在服务器端做出反应来渲染图像?

反应服务器端渲染 - webpack的“样式加载器”失败

反应客户端和服务器端渲染

反应服务器端渲染SSR 2018 [关闭]