Closed Conrad777 closed 8 years ago
The easiest way to do this is to wrap CSS require
s in a conditional. Something like:
if (window)
require('module.css');
Slightly cleaner would be to use Webpack.DefinePlugin()
to set process.env.CLIENT
to true, then use that.
There might be a better way of doing it, because I know this seems a little messy. There is probably a way of telling babel not to process certain requires, I just don’t know it :)
Yeah, I did exactly that and it at least does half the job by loading chunks of css only when necessary. The only issue with this is that it doesn't make it possible to then do inline styling like this:
let styles = require('module.css')
...
render() {
return (
<div className={styles.container} />
...
But for now I guess this will have to do until I can find a better way of doing it. I will dig a little into babel and see if I can find something there.
Thanks for your reply!
@Conrad777, webpack-isomorphic-tools will do what you want, the only downside is that it requires a lot of configuration and that configuration makes the code look uglier, but it works. I use it in my own project.
Awesome!! This is perfect... Thanks @Dattaya!!
Alternatively, there is https://github.com/gajus/react-css-modules but I think webpack-isomorphic-tools
is the easiest path. There was an attempt to integrate react-css-modules
into react-redux-universal-hot-example
, see erikras/react-redux-universal-hot-example#655 but chrisblossom had some trouble with hot reloading and error handling.
Let me know if you have any trouble with integrating it. Well, with this current setup—one express server for everything—you most likely will. If you want to stick with it, you'll need to add the following code in your index.js
// Since one express server serves the app and dev assets,
// workaround is needed (in the dev mode) for webpack-isomorphic-tools
if (process.env.NODE_ENV !== 'production') {
var fs = require('fs');
fs.closeSync(fs.openSync(path.join(__dirname, '..', 'webpack-assets.json'), 'w'));
}
I have plans to create a separate branch in my fork of this repository with wepack-isomorphic-tools
integrated, it's already on my todo list. I can speed this process up in case it takes you too long to properly configure it.
In my previous post I believe I confused react-css-modules
with css-modules-require-hook
@Dattaya I will need help with this after all! It might just be a really silly rookie thing, but I don't have the level of expertise to even know where to start looking. So I apologise in advance if the code below makes you lose all hope for humanity!!
webpack.dev.js
...
var WebpackIsomorphicTools = require('webpack-isomorphic-tools');
var Webpack_isomorphic_tools_plugin = require('webpack-isomorphic-tools/plugin')
var webpack_isomorphic_tools_plugin = new Webpack_isomorphic_tools_plugin(require('./webpack-isomorphic-tools-configuration'))
...
export default function(app) {
const config = Object.assign(prodCfg, {
...
context: path.resolve(__dirname, '..'),
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.scss$/,
loader: 'style!css?modules&importLoaders=2&sourceMap&localIdentName=[local]___[hash:base64:5]!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap'
},
...
},
plugins: [
webpack_isomorphic_tools_plugin.development(),
...
webpack.prod.config.js
var WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin');
var webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require('./webpack-isomorphic-tools-configuration'));
...
module: {
loaders: [
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style-loader', 'css?modules&importLoaders=2&sourceMap!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true')
},
...
plugins: [
webpackIsomorphicToolsPlugin
...
webpack-isomorphic-tools-configuration.js (I basically just copied this from here)
var WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin');
module.exports = {
assets: {
images: {
extensions: ['jpeg','jpg','png','gif'],
parser: WebpackIsomorphicToolsPlugin.url_loader_parser
},
fonts: {
extensions: ['woff','woff2','ttf','eot'],
parser: WebpackIsomorphicToolsPlugin.url_loader_parser
},
svg: {
extension: 'svg',
parser: WebpackIsomorphicToolsPlugin.url_loader_parser
},
style_modules: {
extensions: ['scss'],
filter: function(module, regex, options, log) {
if (options.development) {
return WebpackIsomorphicToolsPlugin.style_loader_filter(module, regex, options, log);
} else {
return regex.test(module.name);
}
},
path: function(module, options, log) {
if (options.development) {
return WebpackIsomorphicToolsPlugin.style_loader_path_extractor(module, options, log);
} else {
return module.name;
}
},
parser: function(module, options, log) {
if (options.development) {
return WebpackIsomorphicToolsPlugin.css_modules_loader_parser(module, options, log);
} else {
// in production mode there's Extract Text Loader which extracts CSS text away
return module.source;
}
}
}
}
}
index.js
if (process.env.NODE_ENV !== 'production') {
var fs = require('fs');
fs.closeSync(fs.openSync(path.join(__dirname, '..', 'webpack-assets.json'), 'w'));
}
var Webpack_isomorphic_tools = require('webpack-isomorphic-tools')
var project_base_path = path.resolve(__dirname, '..');
global.webpack_isomorphic_tools = new Webpack_isomorphic_tools(require('./webpack-isomorphic-tools-configuration'))
.development(process.env.NODE_ENV !== 'production')
.server(project_base_path, function() {
var server = require('./server')
const PORT = process.env.PORT || 3000;
server.listen(PORT, function() {
console.log('Listening on port %s...', PORT);
})
})
viewComponent.js
let styles = require('./homeView.scss');
@Dattaya I will need help with this after all! It might just be a really silly rookie thing, but I don't have the level of expertise to even know where to start looking. So I apologise in advance if the code below makes you lose all hope for humanity!!
ha ha, no way is it going to happen (I'm talking about hope for humanity) :smiley: I'm also kind of a rookie with this stuff too, because I didn't want to delve into this library too much, so I copied some config files from react-redux-universal-hot-example
as you did :).
{Object.keys(assets.styles).map((style, i) => ...
take a look at this file.context: path.resolve(__dirname, '..'),
and this path.resolve(__dirname, '..')
context
is the path to resolve your entries, so in your case for ./client
file it would be 'path_where_dev_config_is_located' + '..' + '/client'. If you use this project as a boilerplate, you need to remove '..' in both.var server = require('./server')
=> var server = require('./server').default;
(this is how babel 6 works)app.use( (req, res) => {
if (process.env.NODE_ENV !== 'production') {
global.webpackIsomorphicTools.refresh();
}
const location = createLocation(req.url);
const reducer = combineReducers(reducers);
const store = applyMiddleware(promiseMiddleware)(createStore)(reducer);
...
5 let styles = require('./homeView.scss');
–I think it doesn't work globally so ensure it's inside render
method.
I hope it helps.
@Dattaya I added all these changes (except for 1. but I think it should still work without it) and still not resolving the css. I forked this repo and made the changes to it quickly... Would you mind looking at it real quick and let me know what I am missing?
https://github.com/Conrad777/isomorphic-redux
I would understand if you are a bit busy, so only if you can please!
@Conrad777 take a look at this branch https://github.com/Dattaya/isomorphic-redux/tree/integrate-iso-tools , it should work nicely, the only thing missing is # 1 from the list—iterating over assets.
btw, I gave the code not completely suitable for this project fs.closeSync(fs.openSync(path.join(__dirname, '..', 'webpack-assets.json'), 'w'));
—redundant ..
again, oops...
@Dattaya This is perfect! # 1 was pretty quick to implement as well. Thank you for all your help... it is much appreciated!!
@Dattaya , i saw your repository. It does help me to setup the css as well. But the only question is. The css are not able to run on production server.
i found a way to fix it. under webpack.prod.config.js
new ExtractTextPlugin('[name].css', {allChunks: true}),
under server.js
<body>
<div id="react-view">${componentHTML}</div>
<link rel='stylesheet' type='text/css' href='/main.css' />
<script type="application/javascript" src="/bundle.js"></script>
</body>
Hey, first off I want to thank you for this article... It really helped me to understand universal web apps a lot better. I do however have a question:
How do I add the css loader in Webpack so that it will work on the server as well?
So what I did was I installed and added the loaders inside
webpack.dev.js
like this:Then when I import the file into my
Home.jsx
like thisimport 'css/style.css';
It returns this error when running
npm run dev
:It works when I import the css on the
client/index.jsx
file, cause then the server doesn't have to deal with it at all. Problem with this is that I want to make the styles modular and add only the necessary styles to their components. My aim is to move towards using CSS Modules... But before I can I need to know why and how to add loaders to the setup.I would truly appreciate you're help...