使用Sass进行React服务器端渲染

8

我进行了搜索,但没有找到任何相关/解决的问题,所以我想问一下...

当前技术栈: 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文档上?如果尝试使用<link>标签,浏览器将无法识别该文件。

1个回答

5
我最终通过创建另一个路由处理程序解决了这个问题。
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 文件可以访问,最终通过在服务器响应中提供下面的 <link> 标签来应用样式。
<link rel="stylesheet" href="../../public/styles.css">

如果还有其他更好的解决方案,我很乐意听取反馈。


1
谢谢@Ash,这就是我最终解决它的方法。我正在研究其他利用https://github.com/zeit/styled-jsx的解决方案,但你的解决方案更简单。 - jalbasri
1
很高兴你能解决它。还有另一种方式似乎更简单。通过webpack将你的CSS编译成自己的文件。并在React的“index.js”根目录中要求该文件。 - Ash
1
您还可以使用styled components,这将生成内联CSS,因此用户将节省用于CSS文件的请求。 - Blue Bot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接