Skip to content

Commit

Permalink
improved syntax for including styles
Browse files Browse the repository at this point in the history
  • Loading branch information
Erik Rasmussen committed Jul 31, 2015
1 parent 72cf1f8 commit 44f0d5d
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 82 deletions.
12 changes: 4 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,12 @@ if(__CLIENT__) {
This project uses [local styles](https://medium.com/seek-ui-engineering/the-end-of-global-css-90d2a4a06284) using [css-loader](https://github.com/webpack/css-loader). The way it works is that you import your stylesheet at the top of the class with your React Component, and then you use the classnames returned from that import. Like so:

```javascript
const styles = (function getStyle() {
if (__CLIENT__) {
return require('./App.scss');
}
const stats = require('../../webpack-stats.json');
return stats.css.modules[path.join(__dirname, './App.scss')];
})();
const styles = __CLIENT__ ?
require('./App.scss') :
requireServerCss(require.resolve('./App.scss'));
```

That's a little ugly, I know, but what it allows is very powerful.
Then you set the `className` of your element ot match one of the CSS classes in your SCSS file, and you're good to go!

```jsx
<div className={styles.mySection}> ... </div>
Expand Down
11 changes: 2 additions & 9 deletions src/components/InfoBar.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import path from 'path';
import React, {Component, PropTypes} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import * as infoActions from '../actions/infoActions';
import {relativeToSrc} from '../util';
import {requireServerCss} from '../util';

const styles = (function getStyle() {
if (__CLIENT__) {
return require('./InfoBar.scss');
}
const stats = require('../../webpack-stats.json');
return stats.css.modules[relativeToSrc(path.join(__dirname, './InfoBar.scss'))];
})();
const styles = __CLIENT__ ? require('./InfoBar.scss') : requireServerCss(require.resolve('./InfoBar.scss'));

class InfoBar extends Component {
static propTypes = {
Expand Down
53 changes: 27 additions & 26 deletions src/util.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,39 @@
import path from 'path';

const pathToSrc = path.resolve(__dirname, '.');
const readStats = () => {
// don't cache the `webpack-stats.json` on dev so we read the file on each request.
// on production, use simple `require` to cache the file
const stats = require('../webpack-stats.json');
if (__DEVELOPMENT__) {
delete require.cache[require.resolve('../webpack-stats.json')];
}
return stats;
}

export function relativeToSrc(value) {
return value.slice(pathToSrc.length);
export function requireServerCss(cssPath) {
if (__CLIENT__) {
throw new Error('image-resolver called on browser');
}
return readStats().css.modules[cssPath.slice(__dirname.length)];
}

export function requireServerImage(imagePath) {
if (!imagePath) {
return '';
}
if (__CLIENT__) {
throw new Error('image-resolver called on browser');
} else {
// Load images compiled from `webpack-stats`
// don't cache the `webpack-stats.json` on dev
// so we gonna read the file on each request
// on production, use simple `require` to cache the file
let images = require('../webpack-stats.json').images;
if (__DEVELOPMENT__) {
delete require.cache[require.resolve('../webpack-stats.json')];
}
if (!images) {
return '';
}
throw new Error('server-side only resolver called on client');
}
const images = readStats().images;
if (!images) {
return '';
}

// Find the correct image
const regex = new RegExp(`${imagePath}$`);
const image = images.find(img => regex.test(img.original));
// Find the correct image
const regex = new RegExp(`${imagePath}$`);
const image = images.find(img => regex.test(img.original));

// Serve image.
if (image) return image.compiled;
// Serve image.
if (image) return image.compiled;

// Serve a not-found asset maybe?
return '';
}
// Serve a not-found asset maybe?
return '';
}
11 changes: 3 additions & 8 deletions src/views/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,9 @@ import * as authActions from '../actions/authActions';
import {load as loadAuth} from '../actions/authActions';
import InfoBar from '../components/InfoBar';
import {createTransitionHook} from '../universalRouter';
import {relativeToSrc} from '../util';
import {requireServerCss} from '../util';

const styles = (function getStyle() {
if (__CLIENT__) {
return require('./App.scss');
}
const stats = require('../../webpack-stats.json');
return stats.css.modules[relativeToSrc(path.resolve(__dirname, './App.scss'))];
})();
const styles = __CLIENT__ ? require('./App.scss') : requireServerCss(require.resolve('./App.scss'));

class App extends Component {
static propTypes = {
Expand All @@ -43,6 +37,7 @@ class App extends Component {

render() {
const {user} = this.props;
debugger;

This comment has been minimized.

Copy link
@Markus-ipse

Markus-ipse Jul 31, 2015

Contributor

This should probably be removed?

This comment has been minimized.

Copy link
@erikras

erikras Jul 31, 2015

Owner

Hee hee. Already removed. :-)

return (
<div className={styles.app}>
<nav className="navbar navbar-default navbar-fixed-top">
Expand Down
11 changes: 2 additions & 9 deletions src/views/Home.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
import React, {Component} from 'react';
import path from 'path';
import CounterButton from '../components/CounterButton';
import GithubButton from '../components/GithubButton';
import {relativeToSrc, requireServerImage} from '../util';
import {requireServerCss, requireServerImage} from '../util';

const styles = (function getStyle() {
if (__CLIENT__) {
return require('./Home.scss');
}
const stats = require('../../webpack-stats.json');
return stats.css.modules[relativeToSrc(path.resolve(__dirname, './Home.scss'))];
})();
const styles = __CLIENT__ ? require('./Home.scss') : requireServerCss(require.resolve('./Home.scss'));

// require the logo image both from client and server
let logoImage = '';
Expand Down
11 changes: 2 additions & 9 deletions src/views/Login.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import path from 'path';
import React, {Component, PropTypes} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {isLoaded as isAuthLoaded} from '../reducers/auth';
import * as authActions from '../actions/authActions';
import {load as loadAuth} from '../actions/authActions';
import {relativeToSrc} from '../util';
import {requireServerCss} from '../util';

const styles = (function getStyle() {
if (__CLIENT__) {
return require('./Login.scss');
}
const stats = require('../../webpack-stats.json');
return stats.css.modules[relativeToSrc(path.join(__dirname, './Login.scss'))];
})();
const styles = __CLIENT__ ? require('./Login.scss') : requireServerCss(require.resolve('./Login.scss'));

class Login extends Component {
static propTypes = {
Expand Down
11 changes: 2 additions & 9 deletions src/views/Widgets.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import path from 'path';
import React, {Component, PropTypes} from 'react';
import {bindActionCreators} from 'redux';
import {isLoaded} from '../reducers/widgets';
import {connect} from 'react-redux';
import * as widgetActions from '../actions/widgetActions';
import {load as loadWidgets} from '../actions/widgetActions';
import {relativeToSrc} from '../util';
import {requireServerCss} from '../util';

const styles = (function getStyle() {
if (__CLIENT__) {
return require('./Widgets.scss');
}
const stats = require('../../webpack-stats.json');
return stats.css.modules[relativeToSrc(path.join(__dirname, './Widgets.scss'))];
})();
const styles = __CLIENT__ ? require('./Widgets.scss') : requireServerCss(require.resolve('./Widgets.scss'));

class Widgets extends Component {
static propTypes = {
Expand Down
9 changes: 5 additions & 4 deletions webpack/utils/writeStats.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,17 @@ module.exports = function writeStats(stats, env) {
if (env === 'prod') {
return /\.scss$/.test(m.name);
}

return m.name.slice(0, namePrefix.length) === namePrefix;
}).forEach(function(m) {
var name = path.resolve(__dirname, '../../', env === 'prod' ?
m.name.slice('./src'.length) :
m.name.slice(namePrefix.length + './src'.length));
//Resolve the e.g.:"C:\" issue on windows
if (name) {
const i = name.indexOf(":");
name = name.substring(i > -1 ? i + 1 : 0, name.length + 1);
// Resolve the e.g.: "C:\" issue on windows
const i = name.indexOf(':');
if (i >= 0) {
name = name.slice(i + 1);
}
}
//end
var regex = env === 'prod' ? /module\.exports = ((.|\n)+);/ : /exports\.locals = ((.|\n)+);/;
Expand Down

0 comments on commit 44f0d5d

Please sign in to comment.