From 8a497d4f887e08d64780786feae2b430ee0f5637 Mon Sep 17 00:00:00 2001 From: Mark Fayngersh Date: Sat, 12 Sep 2015 16:26:19 -0400 Subject: [PATCH] v0.3.0 --- .gitignore | 1 + CHANGELOG.md | 5 ++++ README.md | 1 + build/index.html | 1 + karma.config.js | 10 +++++-- karma.cross-browser.config.js | 10 +++++-- package.json | 10 +++++-- server.js | 10 +++++++ src/common/base.css | 50 +++++++++++++++++++++++++++++++++++ src/main.jsx | 3 +++ src/pages/home/page.jsx | 5 +++- src/pages/home/style.css | 8 ++++++ src/pages/landing/page.jsx | 11 ++++++-- src/pages/landing/style.css | 28 ++++++++++++++++++++ src/routers/logged_in.jsx | 4 +-- src/routers/logged_out.jsx | 4 +-- webpack.local.config.js | 22 +++++++++------ webpack.production.config.js | 17 +++++++++--- 18 files changed, 174 insertions(+), 26 deletions(-) create mode 100644 src/common/base.css create mode 100644 src/pages/home/style.css create mode 100644 src/pages/landing/style.css diff --git a/.gitignore b/.gitignore index 10b1e38..9a39fa7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Build build/app.js +build/style.css # Logs logs diff --git a/CHANGELOG.md b/CHANGELOG.md index d0173b3..fda8c2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v0.3.0 + +- Implemented [css-modules](https://github.com/css-modules/css-modules) with basic styling +- Bumped karma to 0.13.9 @claudiopro + # v0.2.5 ES6 cleanup with static class properties - @StevenLangbroek diff --git a/README.md b/README.md index 4e84fa0..4abdd93 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ A minimal skeleton for building testable React apps using ES6. - ES6 with polyfills for current browsers - Testability: ease of writing unit tests and generating code coverage - Minimize templates, compose DOM alongside components via JSX +- `require()` styles from css files - Session-driven routing using [react-router](https://github.com/rackt/react-router) with async data fetching ## Getting Started diff --git a/build/index.html b/build/index.html index 5b1c1a0..b3db001 100644 --- a/build/index.html +++ b/build/index.html @@ -2,6 +2,7 @@ Essential React Template +
diff --git a/karma.config.js b/karma.config.js index 7e285cc..c6f31a6 100644 --- a/karma.config.js +++ b/karma.config.js @@ -1,3 +1,5 @@ +var ExtractTextPlugin = require('extract-text-webpack-plugin'); + /** * This is the Karma configuration file. It contains information about this skeleton * that provides the test runner with instructions on how to run the tests and @@ -67,9 +69,13 @@ module.exports = function(config) { * that we can generate an accurate code coverage report. */ webpack: { + plugins: [ + new ExtractTextPlugin('style.css', { allChunks: true }) + ], module: { loaders: [ - { test: /\.jsx?$/, exclude: /node_modules/, loader: "babel-loader?stage=0"} + { test: /\.jsx?$/, exclude: /node_modules/, loader: "babel-loader?stage=0" }, + { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader') } ], postLoaders: [{ test: /\.jsx?$/, @@ -78,7 +84,7 @@ module.exports = function(config) { }] }, resolve: { - extensions: ['', '.js', '.jsx'] + extensions: ['', '.js', '.jsx', '.css'] } }, diff --git a/karma.cross-browser.config.js b/karma.cross-browser.config.js index dccaf97..82b5113 100644 --- a/karma.cross-browser.config.js +++ b/karma.cross-browser.config.js @@ -1,3 +1,5 @@ +var ExtractTextPlugin = require('extract-text-webpack-plugin'); + module.exports = function(config) { /** @@ -59,13 +61,17 @@ module.exports = function(config) { * The configuration for the karma-webpack plugin. */ webpack: { + plugins: [ + new ExtractTextPlugin('style.css', { allChunks: true }) + ], module: { loaders: [ - { test: /\.jsx?$/, exclude: /node_modules/, loader: "babel-loader?stage=0"} + { test: /\.jsx?$/, exclude: /node_modules/, loader: "babel-loader?stage=0" }, + { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader') } ] }, resolve: { - extensions: ['', '.js', '.jsx'] + extensions: ['', '.js', '.jsx', '.css'] } }, diff --git a/package.json b/package.json index 16aeb35..7765d32 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "essential-react", - "version": "0.2.5", + "version": "0.3.0", "description": "A minimal skeleton for building testable React apps using ES6.", "main": "src/main.jsx", "scripts": { @@ -44,11 +44,17 @@ "webpack-dev-server": "^1.7.0" }, "dependencies": { + "autoprefixer": "^6.0.2", "babel-core": "^5.4.7", "babel-loader": "^5.1.3", + "css-loader": "^0.18.0", "express": "^4.12.3", + "extract-text-webpack-plugin": "^0.8.2", + "postcss-loader": "^0.6.0", + "postcss-nested": "^1.0.0", "react": "^0.13.3", "react-router": "^0.13.3", - "webpack": "^1.9.6" + "style-loader": "^0.12.3", + "webpack": "^1.12.1" } } diff --git a/server.js b/server.js index b3dfe89..72c4a09 100644 --- a/server.js +++ b/server.js @@ -6,6 +6,7 @@ var app = express(); * * Express routes for: * - app.js + * - style.css * - index.html * * Sample endpoints to demo async data fetching: @@ -23,6 +24,15 @@ app.get('/app.js', function(req, res) { } }); +// Serve aggregate stylesheet depending on environment +app.get('/style.css', function(req, res) { + if (process.env.PRODUCTION) { + res.sendFile(__dirname + '/build/style.css'); + } else { + res.redirect('//localhost:9090/build/style.css'); + } +}); + // Serve index page app.get('*', function(req, res) { res.sendFile(__dirname + '/build/index.html'); diff --git a/src/common/base.css b/src/common/base.css new file mode 100644 index 0000000..4c57b9b --- /dev/null +++ b/src/common/base.css @@ -0,0 +1,50 @@ +* { + box-sizing: border-box; +} + +body { + margin: 0; + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; + font-weight: 300; + background-color: #f1f1f1; +} + +h1 { + margin: 0; + color: #F97F85; +} + +:global(#container) { + width: 100%; + + @media (min-width: 960px) { + width: 960px; + margin: 0 auto; + } + + :global(#navigation) { + padding: 10px 15px; + background-color: #F9E957; + + ul { + list-style: none; + margin: 0; + padding: 0; + + li { + display: inline-block; + font-size: 18px; + font-weight: bold; + + a { + color: #555; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + } + } + } +} diff --git a/src/main.jsx b/src/main.jsx index 0e5cf2b..a91f565 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -12,6 +12,9 @@ import Router from "react-router"; // Common utilities import Session from "./common/session"; +// Base styling +import "./common/base.css"; + // Routers import LoggedOutRouter from "./routers/logged_out"; import LoggedInRouter from "./routers/logged_in"; diff --git a/src/pages/home/page.jsx b/src/pages/home/page.jsx index 275fe14..2c59316 100644 --- a/src/pages/home/page.jsx +++ b/src/pages/home/page.jsx @@ -1,5 +1,7 @@ import React from "react"; import { getData } from "../../common/request"; +import styles from "./style.css"; + export default class HomePage extends React.Component { componentWillMount() { @@ -10,8 +12,9 @@ export default class HomePage extends React.Component { let { title } = this.props.data.home; return ( -
+

{title}

+

Thanks for joining!

); } diff --git a/src/pages/home/style.css b/src/pages/home/style.css new file mode 100644 index 0000000..5173e2a --- /dev/null +++ b/src/pages/home/style.css @@ -0,0 +1,8 @@ +.content { + margin-top: 20px; +} + +.welcomeText { + font-size: 20px; + color: #7F7F7F; +} diff --git a/src/pages/landing/page.jsx b/src/pages/landing/page.jsx index 3055c19..e94b153 100644 --- a/src/pages/landing/page.jsx +++ b/src/pages/landing/page.jsx @@ -1,5 +1,6 @@ import React from "react"; import { getData } from "../../common/request"; +import styles from "./style.css"; export default class LandingPage extends React.Component { @@ -11,12 +12,18 @@ export default class LandingPage extends React.Component { let { title } = this.props.data.landing; return ( -
-

{title}

+
+

{title}

+

Create an account to get started!

+
); } + signUp = (event) => { + alert("Sign Up!"); + } + static fetchData = function(params) { return getData("/landing"); } diff --git a/src/pages/landing/style.css b/src/pages/landing/style.css new file mode 100644 index 0000000..2d8a4db --- /dev/null +++ b/src/pages/landing/style.css @@ -0,0 +1,28 @@ +.content { + margin-top: 50px; +} + +.heading { + font-size: 10vw; +} + +.lead { + display: inline-block; + margin-right: 20px; + font-size: 3vw; +} + +.signUpButton { + display: inline-block; + padding: 1vw 2vw; + border: 0; + font-size: 2vw; + + background-color: #4B9DA3; + color: #f3f3f3; + + cursor: pointer; + border-radius: 2px; + text-shadow: 0px 1px 1px rgba(0,0,0,0.5); + box-shadow: 0px 5px 25px -5px rgba(0,0,0,0.5); +} diff --git a/src/routers/logged_in.jsx b/src/routers/logged_in.jsx index 84709dc..63f34f2 100644 --- a/src/routers/logged_in.jsx +++ b/src/routers/logged_in.jsx @@ -16,9 +16,7 @@ export default class LoggedInRouter extends React.Component {
-
- -
+
); } diff --git a/src/routers/logged_out.jsx b/src/routers/logged_out.jsx index 1789ee4..68a9ed6 100644 --- a/src/routers/logged_out.jsx +++ b/src/routers/logged_out.jsx @@ -8,9 +8,7 @@ export default class LoggedOutRouter extends React.Component { render() { return (
-
- -
+
); } diff --git a/webpack.local.config.js b/webpack.local.config.js index 6abde47..6e4cf32 100644 --- a/webpack.local.config.js +++ b/webpack.local.config.js @@ -1,4 +1,5 @@ var webpack = require('webpack'); +var ExtractTextPlugin = require('extract-text-webpack-plugin'); /** * This is the Webpack configuration file for local development. It contains @@ -33,22 +34,27 @@ module.exports = { // Necessary plugins for hot load plugins: [ new webpack.HotModuleReplacementPlugin(), - new webpack.NoErrorsPlugin() + new webpack.NoErrorsPlugin(), + new ExtractTextPlugin('style.css', { allChunks: true }) ], // Transform source code using Babel and React Hot Loader module: { loaders: [ - { - test: /\.jsx?$/, - exclude: /node_modules/, - loaders: ["react-hot", "babel-loader?stage=0"], - } + { test: /\.jsx?$/, exclude: /node_modules/, loaders: ["react-hot", "babel-loader?stage=0"] }, + { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader') } ] }, // Automatically transform files with these extensions resolve: { - extensions: ['', '.js', '.jsx'] - } + extensions: ['', '.js', '.jsx', '.css'] + }, + + // Additional plugins for CSS post processing using postcss-loader + postcss: [ + require('autoprefixer'), // Automatically include vendor prefixes + require('postcss-nested') // Enable nested rules, like in Sass + ] + } diff --git a/webpack.production.config.js b/webpack.production.config.js index 56ff3e9..8a03300 100644 --- a/webpack.production.config.js +++ b/webpack.production.config.js @@ -1,4 +1,5 @@ var webpack = require('webpack'); +var ExtractTextPlugin = require('extract-text-webpack-plugin'); /** * This is the Webpack configuration file for production. @@ -11,13 +12,23 @@ module.exports = { filename: "app.js" }, + plugins: [ + new ExtractTextPlugin('style.css', { allChunks: true }) + ], + module: { loaders: [ - { test: /\.jsx?$/, exclude: /node_modules/, loader: "babel-loader?stage=0" } + { test: /\.jsx?$/, exclude: /node_modules/, loader: "babel-loader?stage=0" }, + { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader') } ] }, resolve: { - extensions: ['', '.js', '.jsx'] - } + extensions: ['', '.js', '.jsx', '.css'] + }, + + postcss: [ + require('autoprefixer'), + require('postcss-nested') + ] }