├── .babelrc
├── .gitignore
├── README.md
├── data.js
├── package.json
├── src
├── components
│ ├── Button
│ │ ├── Button.js
│ │ └── styles.css
│ └── Head.js
├── router.js
├── routes.js
└── templates
│ ├── About.js
│ ├── Home.js
│ └── Main.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react"]
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /node_modules
3 | npm-debug.log
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Static React and CSS Modules
2 |
3 | A React, Webpack and CSS Modules project that generates static markup. All markup is generated in `/build` from `/src`. If you’re interested in learning more about the inner workings of this project you can check out the tutorial on CSS-Tricks:
4 |
5 | 📕 [CSS Modules and React](https://css-tricks.com/css-modules-part-3-react/) 📕
6 |
7 |
8 | ## Getting started
9 |
10 | Hop into the terminal:
11 |
12 | 1. `npm install`
13 | 2. `npm start`
14 |
15 | BrowserSync will then open up a new tab where you can start to make new components and templates as you see fit.
16 |
17 | ## Workflow
18 |
19 | React is used in this project not to build a complex web app but instead to organise bundles of CSS and JS in order to write maintainable code and create static markup. This is what our directory structure looks like:
20 |
21 | ```
22 | /src
23 | /components
24 | /Button
25 | Button.js
26 | styles.css
27 | /Title
28 | Title.js
29 | style.css
30 | ```
31 |
32 | So in `Button.js` we create a standard React component and we import its styles so that Webpack can generate custom classnames:
33 |
34 | ```
35 | import React from 'react'
36 | import btn from './styles.css'
37 |
38 | export default class CoolButton extends React.Component {
39 | render(){
40 | return (
41 |
42 | )
43 | }
44 | }
45 | ```
46 |
47 | And then we import that React component into one of the templates, such as `src/templates/Home.js`:
48 |
49 | ```
50 | import React from 'react'
51 | import CoolButton from '../components/Button/Button'
52 |
53 | export default class Home extends React.Component {
54 | render() {
55 | return (
56 |
57 |
Home page
58 |
This is a home page
59 |
60 |
61 | )
62 | }
63 | }
64 | ```
65 |
66 | This way we get to generate custom classnames like CSS Modules but we also get some of the templating benefits of React.
67 |
68 | ## Improvements
69 |
70 | Since this is a concept for how you might want to organise your markup and CSS, this project contains as few dependencies as possible. I haven’t added Sass or PostCSS loaders into the Webpack config, and this project doesn’t support image files either.
71 |
72 | ## Issues
73 |
74 | This is really just a proof of concept, but if you feel like there’s anything I’ve missed then don’t hesitate to open an issue.
75 |
--------------------------------------------------------------------------------
/data.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | routes: [
3 | '/',
4 | '/about'
5 | ]
6 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "css-tricks-modules",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server --progress --colors",
8 | "start": "webpack && npm run dev"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^6.7.4",
15 | "babel-loader": "^6.2.4",
16 | "babel-preset-es2015": "^6.6.0",
17 | "babel-preset-react": "^6.5.0",
18 | "browser-sync": "^2.12.8",
19 | "browser-sync-webpack-plugin": "^1.0.1",
20 | "css-loader": "^0.23.1",
21 | "extract-text-webpack-plugin": "^1.0.1",
22 | "react": "^15.0.2",
23 | "react-dom": "^15.0.2",
24 | "react-router": "^2.4.0",
25 | "static-site-generator-webpack-plugin": "^2.0.1",
26 | "webpack": "^1.12.14",
27 | "webpack-dev-server": "^1.14.1"
28 | },
29 | "dependencies": ""
30 | }
31 |
--------------------------------------------------------------------------------
/src/components/Button/Button.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import btn from './styles.css'
3 |
4 | export default class CoolButton extends React.Component {
5 | render(){
6 | return (
7 |
8 | )
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/components/Button/styles.css:
--------------------------------------------------------------------------------
1 | .red {
2 | font-size: 25px;
3 | background-color: blue;
4 | color: white;
5 | }
--------------------------------------------------------------------------------
/src/components/Head.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | class Head extends React.Component {
3 | render() {
4 | return (
5 |
6 | {this.props.title}
7 |
8 |
9 | )
10 | }
11 | }
12 |
13 | export default Head
--------------------------------------------------------------------------------
/src/router.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import ReactDOMServer from 'react-dom/server'
4 | import {Router, RouterContext, match, createMemoryHistory} from 'react-router'
5 | import routes from './routes'
6 | import Main from './templates/Main'
7 |
8 |
9 | module.exports = function(locals, callback){
10 | const history = createMemoryHistory();
11 | const location = history.createLocation(locals.path);
12 |
13 | return match({
14 | routes: routes,
15 | location: location
16 | }, function(error, redirectLocation, renderProps) {
17 | var html = ReactDOMServer.renderToStaticMarkup(
18 |
19 | );
20 | return callback(null, html);
21 | })
22 | }
23 |
--------------------------------------------------------------------------------
/src/routes.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Route, Redirect} from 'react-router'
3 | import Main from './templates/Main.js'
4 | import Home from './templates/Home.js'
5 | import About from './templates/About.js'
6 |
7 | module.exports = (
8 |
9 |
10 |
11 |
12 | )
13 |
--------------------------------------------------------------------------------
/src/templates/About.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default class About extends React.Component {
4 | render() {
5 | return (
6 |