From 8750e5b02c2af06aa537d74a881c142ef91061b7 Mon Sep 17 00:00:00 2001 From: Matt Marcello Date: Wed, 23 Sep 2015 18:27:10 -0400 Subject: [PATCH] initial commit --- .gitignore | 2 + app/containers/Application.css | 0 app/containers/Application.jsx | 13 +++ app/containers/Login.css | 0 app/containers/Login.jsx | 12 +++ app/redux/store.js | 31 +++++++ app/route-handlers/Application.jsx | 7 ++ app/route-handlers/Login.jsx | 6 ++ app/routes.jsx | 15 ++++ config/loadersByExtension.js | 28 +++++++ config/mainRenderer.jsx | 13 +++ index.html | 10 +++ make-webpack-config.js | 130 +++++++++++++++++++++++++++++ package.json | 40 +++++++++ webpack-dev-server.config.js | 4 + webpack-production.config.js | 5 ++ 16 files changed, 316 insertions(+) create mode 100644 .gitignore create mode 100644 app/containers/Application.css create mode 100644 app/containers/Application.jsx create mode 100644 app/containers/Login.css create mode 100644 app/containers/Login.jsx create mode 100644 app/redux/store.js create mode 100644 app/route-handlers/Application.jsx create mode 100644 app/route-handlers/Login.jsx create mode 100644 app/routes.jsx create mode 100644 config/loadersByExtension.js create mode 100644 config/mainRenderer.jsx create mode 100644 index.html create mode 100644 make-webpack-config.js create mode 100644 package.json create mode 100644 webpack-dev-server.config.js create mode 100644 webpack-production.config.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e2e84b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +node_modules/ diff --git a/app/containers/Application.css b/app/containers/Application.css new file mode 100644 index 0000000..e69de29 diff --git a/app/containers/Application.jsx b/app/containers/Application.jsx new file mode 100644 index 0000000..d216b46 --- /dev/null +++ b/app/containers/Application.jsx @@ -0,0 +1,13 @@ +import React from "react"; + +import styles from "./Application.css"; + +export default class Application extends React.Component { + render() { + return
+

This is an applidjfcation container

+ { this.props.children } +
+ } +} + diff --git a/app/containers/Login.css b/app/containers/Login.css new file mode 100644 index 0000000..e69de29 diff --git a/app/containers/Login.jsx b/app/containers/Login.jsx new file mode 100644 index 0000000..f399000 --- /dev/null +++ b/app/containers/Login.jsx @@ -0,0 +1,12 @@ +import React from "react"; + +import styles from "./Login.css"; + +export default class Login extends React.Component { + render() { + return
+

This is a login component

+
+ } +} + diff --git a/app/redux/store.js b/app/redux/store.js new file mode 100644 index 0000000..062b137 --- /dev/null +++ b/app/redux/store.js @@ -0,0 +1,31 @@ +import { createStore, applyMiddleware, compose } from 'redux'; + +//TODO: implement middleware for async actions +// import createMiddleware from './middleware/clientMiddleware'; + +export default function createApiClientStore(client, data) { + const middleware = createMiddleware(client); + let finalCreateStore; + if (__DEVELOPMENT__ && __CLIENT__ && __DEVTOOLS__) { + const { devTools, persistState } = require('redux-devtools'); + finalCreateStore = compose( + applyMiddleware(middleware), + devTools(), + persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)) + )(createStore); + } else { + finalCreateStore = applyMiddleware(middleware)(createStore); + } + + const reducer = require('./modules/reducer'); + const store = finalCreateStore(reducer, data); + store.client = client; + + if (__DEVELOPMENT__ && module.hot) { + module.hot.accept('./modules/reducer', () => { + store.replaceReducer(require('./modules/reducer')); + }); + } + + return store; +} diff --git a/app/route-handlers/Application.jsx b/app/route-handlers/Application.jsx new file mode 100644 index 0000000..367ae19 --- /dev/null +++ b/app/route-handlers/Application.jsx @@ -0,0 +1,7 @@ +import Application from "containers/Application"; + +//TODO: eventually we will want to connect to store using react-redux; +// export default connect(mapStateToProps)(Application) + +export default Application; + diff --git a/app/route-handlers/Login.jsx b/app/route-handlers/Login.jsx new file mode 100644 index 0000000..5bfe850 --- /dev/null +++ b/app/route-handlers/Login.jsx @@ -0,0 +1,6 @@ +import Login from "containers/Login"; + +//TODO: eventually we will want to connect to store using react-redux; +// export default connect(mapStateToProps)(Application) + +export default Login; diff --git a/app/routes.jsx b/app/routes.jsx new file mode 100644 index 0000000..9a5c62a --- /dev/null +++ b/app/routes.jsx @@ -0,0 +1,15 @@ +import React from "react"; +import { Route } from "react-router"; + +import Application from "route-handlers/Application"; +import Login from "route-handlers/Login"; + +//TODO: research necessity of Object.assign polyfill + +//TODO: switch to es6 export + +module.exports = ( + + + +) diff --git a/config/loadersByExtension.js b/config/loadersByExtension.js new file mode 100644 index 0000000..a5581ef --- /dev/null +++ b/config/loadersByExtension.js @@ -0,0 +1,28 @@ +function extsToRegExp(exts) { + return new RegExp("\\.(" + exts.map(function(ext) { + return ext.replace(/\./g, "\\."); + }).join("|") + ")(\\?.*)?$"); +} + +module.exports = function loadersByExtension(obj) { + var loaders = []; + Object.keys(obj).forEach(function(key) { + var exts = key.split("|"); + var value = obj[key]; + var entry = { + extensions: exts, + test: extsToRegExp(exts) + }; + if(Array.isArray(value)) { + entry.loaders = value; + } else if(typeof value === "string") { + entry.loader = value; + } else { + Object.keys(value).forEach(function(valueKey) { + entry[valueKey] = value[valueKey]; + }); + } + loaders.push(entry); + }); + return loaders; +}; diff --git a/config/mainRenderer.jsx b/config/mainRenderer.jsx new file mode 100644 index 0000000..50fa54d --- /dev/null +++ b/config/mainRenderer.jsx @@ -0,0 +1,13 @@ + +import React from "react"; +import { Router } from "react-router"; +import routes from "../app/routes"; + + +//TODO: will need to wrap in redux provider element +React.render(( + + { routes } + +), document.getElementById("content")); + diff --git a/index.html b/index.html new file mode 100644 index 0000000..e6a8728 --- /dev/null +++ b/index.html @@ -0,0 +1,10 @@ + + + + + + +
+ + + diff --git a/make-webpack-config.js b/make-webpack-config.js new file mode 100644 index 0000000..bc9dc24 --- /dev/null +++ b/make-webpack-config.js @@ -0,0 +1,130 @@ +var path = require("path"); +var webpack = require("webpack"); +var ExtractTextPlugin = require("extract-text-webpack-plugin"); +var StatsPlugin = require("stats-webpack-plugin"); + + +var loadersByExtension = require("./config/loadersByExtension"); + +module.exports = function(options) { + var entry = { + main: "./config/mainRenderer" + }; + var loaders = { + "jsx": options.hotComponents ? ["react-hot-loader", "babel-loader?stage=0"] : "babel-loader?stage=0", + "js": { + loader: "babel-loader?stage=0", + include: path.join(__dirname, "app") + }, + "json": "json-loader", + "json5": "json5-loader", + "txt": "raw-loader", + "png|jpg|jpeg|gif|svg": "url-loader?limit=10000", + "woff|woff2": "url-loader?limit=100000", + "ttf|eot": "file-loader", + "wav|mp3": "file-loader", + "html": "html-loader", + "md|markdown": ["html-loader", "markdown-loader"] + }; + var cssLoader = options.minimize ? "css-loader?module" : "css-loader?module&localIdentName=[path][name]---[local]---[hash:base64:5]"; + var stylesheetLoaders = { + "css": cssLoader, + "less": [cssLoader, "less-loader"], + "styl": [cssLoader, "stylus-loader"], + "scss|sass": [cssLoader, "sass-loader"] + }; + var additionalLoaders = [ + // { test: /some-reg-exp$/, loader: "any-loader" } + ]; + + var modulesDirectories = [ "node_modules" ]; + var extensions = ["", ".web.js", ".js", ".jsx"]; + + var root = path.join(__dirname, "app"); + var publicPath = options.devServer ? + "http://localhost:2992/_assets/" : + "/_assets/"; + var output = { + path: path.join(__dirname, "build", "public"), + publicPath: publicPath, + filename: "[name].js" + (options.longTermCaching ? "?[chunkhash]" : ""), + chunkFilename: (options.devServer ? "[id].js" : "[name].js") + (options.longTermCaching ? "?[chunkhash]" : ""), + sourceMapFilename: "debugging/[file].map", + pathinfo: options.debug + }; + + var excludeFromStats = [ + /node_modules[\\\/]react(-router)?[\\\/]/ + ]; + + var plugins = [ + new webpack.PrefetchPlugin("react"), + new webpack.PrefetchPlugin("react/lib/ReactComponentBrowserEnvironment"), + new StatsPlugin(path.join(__dirname, "build", "stats.json"), { + chunkModules: true, + exclude: excludeFromStats + }) + ]; + + if (options.commonsChunk) { + //TODO: investigate necesit of this, do i need commons entry? + plugins.push(new webpack.optimize.CommonsChunkPlugin( + "commons", "commons.js" + (options.longTermCaching ? "?[chunkhash]" : ""))); + } + + Object.keys(stylesheetLoaders).forEach(function(ext) { + var stylesheetLoader = stylesheetLoaders[ext]; + if(Array.isArray(stylesheetLoader)) stylesheetLoader = stylesheetLoader.join("!"); + if(options.separateStylesheet) { + stylesheetLoaders[ext] = ExtractTextPlugin.extract("style-loader", stylesheetLoader); + } else { + stylesheetLoaders[ext] = "style-loader!" + stylesheetLoader; + } + }); + + if(options.separateStylesheet) { + plugins.push(new ExtractTextPlugin("[name].css" + (options.longTermCaching ? "?[contenthash]" : ""))); + } + + //TODO this doesn't seem to be minfiying + if(options.minimize) { + plugins.push( + new webpack.optimize.UglifyJsPlugin({ + compressor: { + warnings: false + } + }), + new webpack.optimize.DedupePlugin(), + new webpack.DefinePlugin({ + "process.env": { + NODE_ENV: JSON.stringify("production") + } + }), + new webpack.NoErrorsPlugin() + ); + } + + return { + entry: entry, + output: output, + module: { + loaders: loadersByExtension(loaders).concat(loadersByExtension(stylesheetLoaders)).concat(additionalLoaders) + }, + debug: options.debug, + resolveLoader: { + root: path.join(__dirname, "node_modules") + }, + resolve: { + root: root, + modulesDirectories: modulesDirectories, + extensions: extensions + }, + plugins: plugins, + devServer: { + stats: { + cached: false, + exclude: excludeFromStats + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6fde38c --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "console", + "version": "0.0.0", + "description": "Coroner web client.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "dev-server": "webpack-dev-server --config webpack-dev-server.config.js --progress --colors --port 2992 --inline", + "hot-dev-server": "webpack-dev-server --config webpack-hot-dev-server.config.js --hot --progress --colors --port 2992 --inline", + "build": "webpack --config webpack-production.config.js --progress --profile --colors" + }, + "author": "Matt Marcelo", + "license": "ISC", + "dependencies": { + "babel-core": "^5.8.25", + "babel-loader": "^5.3.2", + "css-loader": "^0.19.0", + "extract-text-webpack-plugin": "^0.8.2", + "file-loader": "^0.8.4", + "html-loader": "^0.3.0", + "json-loader": "^0.5.3", + "json5": "^0.4.0", + "json5-loader": "^0.6.0", + "less": "^2.5.1", + "less-loader": "^2.2.1", + "markdown-loader": "^0.1.7", + "node-sass": "^3.3.3", + "raw-loader": "^0.5.1", + "react": "^0.13.3", + "react-hot-loader": "^1.3.0", + "react-router": "^1.0.0-rc1", + "redux": "^3.0.0", + "sass-loader": "^2.0.1", + "stats-webpack-plugin": "^0.2.1", + "style-loader": "^0.12.4", + "stylus-loader": "^1.3.0", + "url-loader": "^0.5.6", + "webpack": "^1.12.2" + } +} diff --git a/webpack-dev-server.config.js b/webpack-dev-server.config.js new file mode 100644 index 0000000..229489d --- /dev/null +++ b/webpack-dev-server.config.js @@ -0,0 +1,4 @@ +module.exports = require("./make-webpack-config")({ + devServer: true, + debug: true +}) diff --git a/webpack-production.config.js b/webpack-production.config.js new file mode 100644 index 0000000..b253a81 --- /dev/null +++ b/webpack-production.config.js @@ -0,0 +1,5 @@ +module.exports = require("./make-webpack-config")({ + longTermCaching: true, + seperateStylesheet: true, + minimize: true +})