-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18 from tylercrosse/dev
Dev
- Loading branch information
Showing
47 changed files
with
1,706 additions
and
411 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,89 @@ | ||
# gitter-clone | ||
# Gitter-clone | ||
[![Build Status](https://semaphoreci.com/api/v1/tcrosse/gitter-clone/branches/master/badge.svg)](https://semaphoreci.com/tcrosse/gitter-clone) | ||
[![codecov](https://codecov.io/gh/tylercrosse/gitter-clone/branch/master/graph/badge.svg)](https://codecov.io/gh/tylercrosse/gitter-clone) | ||
|
||
Portfolio Project clone of gitter.im -- Hire me! | ||
|
||
Built with: | ||
- react | ||
- redux | ||
- jest | ||
- webpack | ||
- babel | ||
- express | ||
- mongodb | ||
- semaphore | ||
- digital ocean | ||
<div align="center"> | ||
</div> | ||
|
||
This is app was built as portfolio piece representing a subset of the features of Troupe Technology's wonderful chat app, [Gitter](https://gitter.im/). I'm currently looking for a new position - Hire me! | ||
|
||
--- | ||
### Demo | ||
|
||
You can test a fully working live demo at http://138.68.24.248:3333/ | ||
|
||
--- | ||
### Major features | ||
|
||
- MD / syntax highlighting support for messages | ||
- Messages grouped into bursts | ||
- Create Channels | ||
- Load previous messages in channel | ||
- Send Messages to all subscribed clients on channel | ||
|
||
--- | ||
### Built with | ||
|
||
##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/react.svg"> [React](https://facebook.github.io/react/) | ||
|
||
React makes it really easy to focus on the view in a declarative way. I like that it makes it easy to write composable, testable UI. Routing is handled by [react router](https://reacttraining.com/react-router/). | ||
|
||
##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/redux.svg"> [Redux](http://redux.js.org/) | ||
|
||
Redux is where the fun is at. Maintain a flat minimal state, with dictionary of normalized objects. I use [reselect](https://github.com/reactjs/reselect) to compute derived data. [Redux devtools](https://github.com/zalmoxisus/redux-devtools-extension) are also great, I kept it enabled on production for anyone wanting to easily take a look at the app's state. | ||
|
||
##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/webpack.svg"> [Webpack 2](https://webpack.js.org/) | ||
|
||
Fantastic code bundler once you get past the learning curve. I use it for a number of things including: transpile ES2015+ javascript to ES5 with [Babel](https://babeljs.io/), compile [Sass](http://sass-lang.com/) into css, optimize assets, hot reload code, build minimized split production code, + more. | ||
|
||
##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/express.svg"> [Express](https://expressjs.com/) | ||
|
||
It's nice to have JS everywhere. Express is fast and minimal. The backend is pretty simple with a router, a few controllers, and basic db interactions. Logging handled by [winston](https://github.com/winstonjs/winston). | ||
|
||
##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/mongodb.svg"> [MongoDB](https://www.mongodb.com/) | ||
|
||
This project doesn't currently require a ton of data persistence. MongoDB + [Mongoose](http://mongoosejs.com/) make it easy to quickly update the Schema. If the project continues to grow I will probably switch to a relational DB. Also Mongo is still trendy. | ||
|
||
##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/jest.svg"> [Jest](http://facebook.github.io/jest/) | ||
|
||
Unit tests run by Jest. If you haven't seen Jest recently, you should take another look. [Enzyme](https://github.com/airbnb/enzyme) is used for React support and [SuperTest](https://github.com/visionmedia/supertest) is used for HTTP assertions. [Enzyme-to-JSON](https://github.com/adriantoine/enzyme-to-json) is also great and worth checking out in conjunction with the other test utilities. | ||
|
||
##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/semaphor.svg"> [SemaphoreCI](https://semaphoreci.com/) | ||
|
||
Continuous integration handled by the super fast SemaphoreCI. Passing merges to master are auto deployed with help from [pm2](http://pm2.keymetrics.io/). | ||
|
||
##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/digitalocean.svg"> [Digital Ocean](https://www.digitalocean.com/) | ||
|
||
Application hosted on Ubuntu Digital Ocean droplet. SSH is fun! | ||
|
||
--- | ||
### Setup | ||
|
||
If you don't have [yarn](https://yarnpkg.com/en/) commands can be run with `npm`. First, clone and cd into the repo and install the dependencies. | ||
|
||
```sh | ||
$ git clone https://github.com/tylercrosse/gitter-clone.git | ||
$ cd gitter-clone | ||
$ yarn install | ||
``` | ||
|
||
Additional commands: | ||
##### `yarn dev` | ||
- Start development server on `127.0.0.1:3333` | ||
|
||
##### `yarn build` | ||
- Build a production version of the app. | ||
|
||
##### `yarn start` | ||
- Start production server on `127.0.0.1:3333` to serve built app. Requires the build command to have already been run. | ||
|
||
##### `yarn test` | ||
- Run all of the projects tests using jest. | ||
|
||
##### `yarn lint` | ||
- Lint all of the projects javascript files using eslint. | ||
|
||
--- | ||
### Contributing | ||
|
||
Thank you for your interest! Unfortunately, I'm not currently taking contributions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module.exports = { | ||
stirpPrefix: '/static/dist/', | ||
// replacePrefix: '/dist/', | ||
staticFileGlobs: [ | ||
'static/dist/manifest.json', | ||
'static/dist/**.js', | ||
'static/dist/**.min.css', | ||
], | ||
swFilePath: 'static/dist/serviceWorker.js' | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
const path = require('path'); | ||
const webpack = require('webpack'); | ||
|
||
module.exports = { | ||
output: { | ||
path: path.resolve(__dirname, '../static/dist'), | ||
filename: '[name].js', | ||
publicPath: '/dist/' | ||
}, | ||
resolve: { | ||
extensions: ['.js', '.jsx', '.json', '.scss'] | ||
}, | ||
plugins: [ | ||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), | ||
new webpack.optimize.CommonsChunkPlugin({ | ||
names: ['vendor', 'manifest'], | ||
minChunks: Infinity | ||
}) | ||
], | ||
module: { | ||
loaders: [ | ||
// Images | ||
// Inline base64 URLs for <=8k images, direct URLs for the rest | ||
{ | ||
test: /\.(png|jpg|jpeg|gif|svg)$/, | ||
loader: 'url-loader', | ||
query: { | ||
limit: 8192, | ||
} | ||
}, | ||
// Fonts | ||
{ | ||
test: /\.(woff|woff2|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/, | ||
loader: 'url-loader', | ||
query: { | ||
limit: 8192, | ||
} | ||
} | ||
] | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
const path = require('path'); | ||
const webpack = require('webpack'); | ||
const merge = require('webpack-merge'); | ||
const config = require('./webpack.config.base'); | ||
|
||
module.exports = merge(config, { | ||
devtool: 'source-map', | ||
entry: { | ||
application: [ | ||
'babel-polyfill', | ||
'webpack-hot-middleware/client', | ||
'./src/client/index.js' | ||
], | ||
vendor: [ | ||
'moment', | ||
'normalizr', | ||
'react', | ||
'react-dom', | ||
'react-modal', | ||
'react-router', | ||
'react-scroll', | ||
'react-redux', | ||
'react-router-redux', | ||
'redux', | ||
'redux-thunk', | ||
'redux-api-middleware', | ||
'redux-socket.io', | ||
'reselect', | ||
'socket.io-client', | ||
] | ||
}, | ||
plugins: [ | ||
new webpack.HotModuleReplacementPlugin(), | ||
new webpack.NoEmitOnErrorsPlugin(), | ||
new webpack.DefinePlugin({ | ||
'process.env': { | ||
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development') | ||
} | ||
}) | ||
], | ||
module: { | ||
loaders: [ | ||
{ | ||
test: /\.(js|jsx)?$/, | ||
loader: 'babel-loader', | ||
query: { | ||
plugins: [ | ||
[ | ||
'react-transform', { | ||
transforms: [ | ||
{ | ||
transform: 'react-transform-hmr', | ||
imports: ['react'], | ||
locals: ['module'] | ||
}, { | ||
transform: 'react-transform-catch-errors', | ||
imports: ['react', 'redbox-react'] | ||
} | ||
] | ||
} | ||
] | ||
] | ||
}, | ||
include: [path.resolve(__dirname, '../src')] | ||
}, { | ||
// test: /\.css?$/, | ||
// loaders: ['style-loader', 'raw-loader'] | ||
// }, { | ||
test: /\.scss$/, | ||
loaders : [ | ||
{ | ||
loader: 'style-loader' | ||
}, { | ||
loader: 'css-loader', | ||
}, { | ||
loader: 'postcss-loader', | ||
options: { | ||
plugins() { | ||
return [ | ||
require('autoprefixer') | ||
] | ||
} | ||
} | ||
}, { | ||
loader: 'resolve-url-loader' | ||
}, { | ||
loader: 'sass-loader', | ||
options: {sourceMap: true} | ||
} | ||
] | ||
} | ||
] | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; | ||
const path = require('path'); | ||
const webpack = require('webpack'); | ||
const merge = require('webpack-merge'); | ||
const CleanPlugin = require('clean-webpack-plugin'); | ||
const CopyWebpackPlugin = require('copy-webpack-plugin'); | ||
const ExtractTextPlugin = require('extract-text-webpack-plugin'); | ||
const config = require('./webpack.config.base'); | ||
|
||
module.exports = merge(config, { | ||
devtool: 'cheap-module-source-map', | ||
entry: { | ||
application: ['./src/client/index'], | ||
vendor: [ | ||
'moment', | ||
'normalizr', | ||
'react', | ||
'react-dom', | ||
'react-modal', | ||
'react-router', | ||
'react-scroll', | ||
'react-redux', | ||
'react-router-redux', | ||
'redux', | ||
'redux-thunk', | ||
'redux-api-middleware', | ||
'redux-socket.io', | ||
'reselect', | ||
'socket.io-client', | ||
] | ||
}, | ||
plugins: [ | ||
new CleanPlugin(['../static/dist'], {verbose: true}), | ||
new CopyWebpackPlugin([ | ||
{ | ||
from: path.join(__dirname, '../src/client/manifest.json'), | ||
to: 'manifest.json' | ||
} | ||
]), | ||
new webpack.DefinePlugin({ | ||
'process.env': { | ||
'NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production') | ||
} | ||
}), | ||
new webpack.optimize.UglifyJsPlugin({ | ||
compress: { | ||
warnings: false, | ||
'screw_ie8': true | ||
}, | ||
output: { | ||
comments: false | ||
}, | ||
sourceMap: false | ||
}), | ||
new webpack.LoaderOptionsPlugin({ | ||
minimize: true, | ||
debug: false | ||
}), | ||
new ExtractTextPlugin({ | ||
filename: 'style.min.css', | ||
allChunks: true | ||
}), | ||
// new BundleAnalyzerPlugin() | ||
], | ||
module: { | ||
noParse: /\.min\.js$/, | ||
loaders: [ | ||
{ | ||
test: /\.(js|jsx)?$/, | ||
use: 'babel-loader', | ||
include: [path.resolve(__dirname, '../src')] | ||
}, { | ||
test: /\.css?$/, | ||
loaders: ['style-loader', 'raw-loader'] | ||
}, { | ||
test: /\.scss$/, | ||
loader: ExtractTextPlugin.extract({ | ||
fallbackLoader: 'style-loader', | ||
use: [ | ||
{ | ||
loader: 'css-loader', | ||
}, { | ||
loader: 'postcss-loader', | ||
options: { | ||
plugins() { | ||
return [ | ||
require('autoprefixer') | ||
] | ||
} | ||
} | ||
}, { | ||
loader: 'resolve-url-loader' | ||
}, { | ||
loader: 'sass-loader', | ||
options: {sourceMap: true} | ||
} | ||
] | ||
}) | ||
} | ||
] | ||
} | ||
}); |
Oops, something went wrong.