As i have searched through the previous but could not find any relevant / solved issues on this so I ask...
Current stack: React, express/node, Sass, Webpack, Sass.
I have a question specific to the Styling of pages before server sends them to the browser.
Styling is working perfectly in the browser and by I mean when the pages are being navigated via browser router, all the styling works. However, I need to figure out a way to inject custom Sass styles to the page before the Server sends the page to the browser.
Current behavior: I access any page from the browser, I get serve the page with correct styling BUT there is a minor delay to get the correct styling in place to appear on the page. If view in slow motion, page appears without styling (because the server sent the page with no styling) and then browser takes over with correct styling.
I have tried webpack to generate all styles in a separate file but I can't seem to link this file to page before server sends it to the browser.
Any help / feedback will be appreciated?
server.js(route handler)
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 (I omitted the rest of config since its not relevant)
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 ],
This gives me a styles.css
file in my /build
folder. How can i link this to my html. If i try to throw a <link>
tag the browser does not recognize the file.
As i have searched through the previous but could not find any relevant / solved issues on this so I ask...
Current stack: React, express/node, Sass, Webpack, Sass.
I have a question specific to the Styling of pages before server sends them to the browser.
Styling is working perfectly in the browser and by I mean when the pages are being navigated via browser router, all the styling works. However, I need to figure out a way to inject custom Sass styles to the page before the Server sends the page to the browser.
Current behavior: I access any page from the browser, I get serve the page with correct styling BUT there is a minor delay to get the correct styling in place to appear on the page. If view in slow motion, page appears without styling (because the server sent the page with no styling) and then browser takes over with correct styling.
I have tried webpack to generate all styles in a separate file but I can't seem to link this file to page before server sends it to the browser.
Any help / feedback will be appreciated?
server.js(route handler)
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 (I omitted the rest of config since its not relevant)
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 ],
This gives me a styles.css
file in my /build
folder. How can i link this to my html. If i try to throw a <link>
tag the browser does not recognize the file.
1 Answer
Reset to default 6I finally solved this issue by creating another route handler.
app.get('/styles.css', (req, res) => {
res.sendFile(__dirname + "/" + "styles.css");
});
My webpack piles a styles.css
file which gets put in the /public
folder. Please note i changed the path of my styles file in webpack to this: ../public/styles.css
app.use(express.static('public'));
Above statement ^^^ makes the styles.css
file accessible and finally styles are applied by supplying the below <link>
tag in the response of server to the browser.
<link rel="stylesheet" href="../../public/styles.css">
If anyone else have a better solution, I would love to get feedback.