使用 Sass 响应服务器端渲染
React Server Side Rendering with Sass
因为我已经搜索过之前的内容,但找不到任何相关/已解决的问题,所以我问...
当前堆栈:React,express/node,Sass,Webpack,Sass。
我有一个特定于服务器将页面发送到浏览器之前的页面样式的问题。
样式在浏览器中运行良好,我的意思是当页面通过浏览器路由器导航时,所有样式都有效。但是,我需要想办法在服务器将页面发送到浏览器之前将自定义 Sass 样式注入页面。
当前行为:我从浏览器访问任何页面,我得到了具有正确样式的页面,但是在页面上显示正确的样式时会有一个小的延迟。如果以慢动作查看,则页面显示没有样式(因为服务器发送的页面没有样式),然后浏览器以正确的样式接管。
我尝试过 webpack 在单独的文件中生成所有样式,但我似乎无法 link 在服务器将其发送到浏览器之前将此文件分页。
任何帮助/反馈将不胜感激?
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
文件。我如何 link 将此发送给我的 html。如果我尝试抛出 <link>
标签,浏览器无法识别该文件。
我终于通过创建另一个路由处理程序解决了这个问题。
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">
如果其他人有更好的解决方案,我很乐意得到反馈。
因为我已经搜索过之前的内容,但找不到任何相关/已解决的问题,所以我问...
当前堆栈:React,express/node,Sass,Webpack,Sass。
我有一个特定于服务器将页面发送到浏览器之前的页面样式的问题。
样式在浏览器中运行良好,我的意思是当页面通过浏览器路由器导航时,所有样式都有效。但是,我需要想办法在服务器将页面发送到浏览器之前将自定义 Sass 样式注入页面。
当前行为:我从浏览器访问任何页面,我得到了具有正确样式的页面,但是在页面上显示正确的样式时会有一个小的延迟。如果以慢动作查看,则页面显示没有样式(因为服务器发送的页面没有样式),然后浏览器以正确的样式接管。
我尝试过 webpack 在单独的文件中生成所有样式,但我似乎无法 link 在服务器将其发送到浏览器之前将此文件分页。
任何帮助/反馈将不胜感激?
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
文件。我如何 link 将此发送给我的 html。如果我尝试抛出 <link>
标签,浏览器无法识别该文件。
我终于通过创建另一个路由处理程序解决了这个问题。
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">
如果其他人有更好的解决方案,我很乐意得到反馈。