var styles = require('./index.css') raises obvious problem -- you can't use <div className={styles.myStyle} > in a component which renders server-side.
Up until now, when requiring css I used if (__BROWSER__) require('style.css') but to write <div className={( __BROWSER__ ? styles.myStyle : '')}> each time I think is too much.
This article suggests to use webpack to process backend but it suggests to use IgnorePlugin(/\.(css|less)$/) and I believe in case with Local scope won't work.
So is there any other option to use Local scope in isomorphic code without any weird hacks?
You should use webpack to compile your node app, then follow these instructions from the readme:
Note: For prerendering with extract-text-webpack-plugin you should use
css-loader/localsinstead ofstyle-loader!css-loaderin the prerendering bundle. It doesn't embed CSS but only exports the identifier mappings.
@markdalgleish thanks. I managed to compile my server side with webpack but it takes too long to recompile and run it when I make changes. Right now it feels like it's more reasonable not to use the local scope than use it and wait so long to recompile. Any tips on setting up the environment so it would recompile acceptably faster would be much appreciated.
On server-side you can put all node_modules into externals so they won't be included in the bundle. This way you only need to compile your code.
The link you posted gives instructions on how to achieve this.
@snegostup Can you please post a working example here?
I've tried it with css-loader/locals, but I always get the same error:
ERROR in ./app/components/Footer/Footer.scss
Module build failed: TypeError: undefined is not a function
at Object.<anonymous> (c:\workspace\guidelines.web\node_modules\extract-text-webpack-plugin\loader.js:97:11)
at Tapable.<anonymous> (c:\workspace\guidelines.web\node_modules\webpack\lib\Compiler.js:213:10)
at c:\workspace\guidelines.web\node_modules\webpack\lib\Compiler.js:401:12
at Tapable.next (c:\workspace\guidelines.web\node_modules\webpack\node_modules\tapable\lib\Tapable.js:67:11)
at Tapable.<anonymous> (c:\workspace\guidelines.web\node_modules\extract-text-webpack-plugin\loader.js:78:5)
at Tapable.next (c:\workspace\guidelines.web\node_modules\webpack\node_modules\tapable\lib\Tapable.js:69:14)
at Tapable.<anonymous> (c:\workspace\guidelines.web\node_modules\webpack\lib\CachePlugin.js:40:4)
at Tapable.applyPluginsAsync (c:\workspace\guidelines.web\node_modules\webpack\node_modules\tapable\lib\Tapable.js:71:13)
at Tapable.<anonymous> (c:\workspace\guidelines.web\node_modules\webpack\lib\Compiler.js:398:9)
at Tapable.<anonymous> (c:\workspace\guidelines.web\node_modules\webpack\lib\Compilation.js:561:13)
@ ./app/components/Footer/Footer.js 21:18-42
module: {
loaders: [{
test: /\.jsx?$/,
loaders: ['babel'],
include: appPath
}, {
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css/locals?module&localIdentName=[name]__[local]___[hash:base64:5]!sass'),
include: appPath
}]
},
@danielstefanovic
Note: For prerendering with extract-text-webpack-plugin you should use css-loader/locals instead of style-loader!css-loader in the prerendering bundle. It doesn't embed CSS but only exports the identifier mappings.
This only applies when you do prerender your app. css-loader/locals should only be used in the bundle that is used for prerendering. You don't use the ETP there.
// client bundle without prerendering
{
test: /\.scss$/,
loader: 'style!css?module&localIdentName=[name]__[local]___[hash:base64:5]!sass',
include: appPath
}
// client bundle with prerendering or optimized with separate css
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css?module&localIdentName=[name]__[local]___[hash:base64:5]!sass'),
include: appPath
}
// server bundle for prerendering
{
test: /\.scss$/,
loader: 'css/locals?module&localIdentName=[name]__[local]___[hash:base64:5]!sass',
include: appPath
}
Thanks for your detailed explanation! It works now.
I love local css but it's a killer having to compile my node app through webpack.
Are there any other options out there?
I like how node-jsx allows server side jsx requires. I'm thinking it could be applied to this situation like this.
require('node-local-css').install({
localIdentName: '[hash:base64:5]',
extension: '.local.css'
}),
Did anyone integrate this with angular2? I'm having trouble with angular's built-in view encapsulation. My main issue is this one: https://github.com/aspnet/JavaScriptServices/issues/132.
Most helpful comment
@danielstefanovic
Note: For prerendering with extract-text-webpack-plugin you should use css-loader/locals instead of style-loader!css-loader in the prerendering bundle. It doesn't embed CSS but only exports the identifier mappings.
This only applies when you do prerender your app.
css-loader/localsshould only be used in the bundle that is used for prerendering. You don't use the ETP there.