├── .eslintignore
├── .gitignore
├── src
├── client
│ └── jsguild.js
├── components
│ └── jsguild-home
│ │ └── jsguild-home.jsx
├── helpers
│ └── html.js
└── server.js
├── .eslintrc
├── .stylelintrc.js
├── README.md
├── webpack
├── webpack.server.config.js
└── webpack.browser.config.js
└── package.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | src/vendors
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .DS_Store
3 | build/
4 | static/baseUrl.js
5 | config/config.js
6 | src/stats.json
7 | dist/
8 | .vscode
9 | npm-debug*
10 |
--------------------------------------------------------------------------------
/src/client/jsguild.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery';
2 | import '../vendors/semantic.min.js';
3 |
4 | $(document).ready(function() {
5 | $('.ui.dropdown').dropdown();
6 | alert('Dom is ready!');
7 | });
8 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "id-length": 0,
5 | "func-names": 0,
6 | "no-dupe-keys": 0,
7 | "react/no-did-mount-set-state": 0,
8 | "no-unused-expressions": 0,
9 | "no-else-return": 0,
10 | "react/prop-types": 0,
11 | "no-fallthrough": 0,
12 | "guard-for-in": 0,
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.stylelintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'rules': {
3 | 'declaration-block-no-single-line': true,
4 | 'declaration-block-single-line-max-declarations': 1,
5 | 'selector-class-pattern': '^(?!js-).*',
6 | 'string-quotes': 'double',
7 | 'declaration-block-semicolon-newline-after': 'always',
8 | 'block-closing-brace-newline-after': 'always',
9 | 'block-closing-brace-newline-before': 'always',
10 | 'color-hex-case': 'lower',
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/components/jsguild-home/jsguild-home.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import '../../client/jsguild.js';
5 |
6 | export default class HomeContainer extends React.Component {
7 | constructor() {
8 | super();
9 | }
10 |
11 | componentDidMount() {
12 |
13 | }
14 |
15 | render() {
16 | return (
17 |
18 |
Hello World from maincontainer!
19 |
20 | );
21 | }
22 | }
23 |
24 | ReactDOM.render(
25 | ,
26 | document.getElementById('maincontainer')
27 | );
28 |
--------------------------------------------------------------------------------
/src/helpers/html.js:
--------------------------------------------------------------------------------
1 | import stats from '../stats.json';
2 |
3 | let jsGuildHomeSrc = stats.jsGuildHome.split('/');
4 | jsGuildHomeSrc = jsGuildHomeSrc[jsGuildHomeSrc.length - 1];
5 | let vendorsSrc = stats.vendors.split('/');
6 | vendorsSrc = vendorsSrc[vendorsSrc.length - 1];
7 |
8 | export function renderHomePage() {
9 | return `
10 |
11 |
12 |
13 | JS Guild
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | `;
24 | }
25 |
--------------------------------------------------------------------------------
/src/server.js:
--------------------------------------------------------------------------------
1 | import config from '../config/config.js';
2 |
3 | // Create express app
4 | import express from 'express';
5 | const app = express();
6 |
7 | // Adding caching for 30 days
8 | const cacheTime = 86400000 * 30;
9 |
10 | app.use('/js/?', express.static(__dirname + '/../build/js', { maxAge: cacheTime }));
11 | app.use('/css/?', express.static(__dirname + '/../dist/css'));
12 | app.use('/css/?', express.static(__dirname + '/../src/static/css'));
13 | app.use('/js/?', express.static(__dirname + '/../src/static/js', { maxAge: cacheTime }));
14 | app.use('/js/?', express.static(__dirname + '/../src/vendors', { maxAge: cacheTime }));
15 | app.use('/fonts/?', express.static(__dirname + '/../src/static/fonts', { maxAge: cacheTime }));
16 | app.use('/images/?', express.static(__dirname + '/../src/static/images', { maxAge: cacheTime }));
17 |
18 | import { renderHomePage } from './helpers/html.js';
19 |
20 | app.get('/', function(req, res) {
21 | res.send(renderHomePage());
22 | });
23 |
24 | const port = process.env.PORT || config.serverPort;
25 | app.listen(port, function() {
26 | console.log('Listening on ' + port);
27 | });
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Boilerplate
2 |
3 | SPA build with:
4 | * Express server
5 | * ReactJs as view library
6 | * Webpack as module bundler
7 |
8 | ###Setting up the project
9 |
10 | * Install nvm
11 | ```
12 | curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash
13 | ```
14 |
15 | * Install required node version
16 | ```
17 | nvm install 4.4.0
18 | ```
19 |
20 | * Install the `webpack` command for the terminal.
21 | ```
22 | npm install -g webpack
23 | ```
24 |
25 | * Install all the node packages
26 | ```
27 | npm install
28 | ```
29 |
30 | * Install pm2
31 | ```
32 | npm install pm2 -g
33 | ```
34 |
35 | ###Deploying
36 |
37 | * For devs
38 |
39 | First Time
40 | ```
41 | npm run build && pm2 start dist/main.js
42 | ```
43 |
44 | Next times - It will automatically start a local server and open the localhost.
45 | ```
46 | npm run serve
47 | ```
48 |
49 | * For production
50 | ```
51 | npm run serve-prod
52 | ```
53 |
54 | ### Nginix config
55 |
56 | ```server {
57 | set $server_uri 127.0.0.1:8142;
58 | server_name jsguild.practo.local;
59 | listen 80;
60 |
61 | access_log /var/log/nginx/app.access.log;
62 | error_log /var/log/nginx/app.error.log;
63 | location = /robots.txt {
64 | echo "User-agent: *\nDisallow: /\n";
65 | }
66 | location / {
67 | proxy_pass http://$server_uri;
68 | include proxy_params;
69 | }
70 | }```
71 |
--------------------------------------------------------------------------------
/webpack/webpack.server.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var fs = require('fs');
3 | var path = require('path');
4 |
5 | var nodeModules = {};
6 | var ExtractTextPlugin = require('extract-text-webpack-plugin');
7 |
8 | fs.readdirSync('node_modules')
9 | .filter(function(x) {
10 | return ['.bin'].indexOf(x) === -1;
11 | })
12 | .forEach(function(mod) {
13 | nodeModules[mod] = 'commonjs ' + mod;
14 | });
15 |
16 |
17 | module.exports =
18 | {
19 | name: 'server',
20 | target: 'node',
21 | entry: './src/server.js',
22 | output: {
23 | path: './dist/',
24 | publicPath: 'dist/',
25 | filename: "[name].js",
26 | },
27 | node: {
28 | __dirname: false,
29 | },
30 | externals: nodeModules,
31 | module: {
32 | preLoaders: [{
33 | test: /(\.js$|\.jsx$)/,
34 | exclude: /node_modules/,
35 | loader: "eslint-loader"
36 | },
37 | { test: /\.(sass|scss)$/, loader: 'stylelint' }
38 | ],
39 | loaders: [
40 | {
41 | test: /(\.js$|\.jsx$)/,
42 | exclude: /node_modules/,
43 | loader: "babel-loader",
44 | },{
45 | test: /\.json?$/,
46 | exclude: /node_modules/,
47 | loader: "json-loader",
48 | },{
49 | test: /\.scss$/,
50 | exclude: /node_modules/,
51 | loader: ExtractTextPlugin.extract(
52 | "style",
53 | "css!sass"
54 | )
55 | },{
56 | test: /\.css$/,
57 | exclude: /node_modules/,
58 | loader: ExtractTextPlugin.extract(
59 | "style-loader",
60 | "css-loader"
61 | )
62 | },{
63 | test: /\.(ttf|eot|woff(2)?)(\?[a-z0-9]+)?$/, exclude: /node_modules/,
64 | exclude: /node_modules/,
65 | loader : 'file-loader'
66 | },{
67 | test: /\.(png|jpg|svg)$/,
68 | exclude: /node_modules/,
69 | loader: 'url-loader?limit=8192'
70 | }
71 | ]
72 | },
73 | stylelint: {
74 | configFile: path.join(__dirname, '../.stylelintrc.js'),
75 | },
76 | plugins: [
77 | new ExtractTextPlugin('css/[name].css', {allChunks: false}),
78 | ]
79 | };
80 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jsguild",
3 | "version": "1.0.0",
4 | "description": "Application to host all JS Guild stuff @ practo",
5 | "main": "index.js",
6 | "scripts": {
7 | "eslint": "./node_modules/.bin/eslint --config=.eslintrc ./src/**/.jsx",
8 | "build": "npm run webpack-client-build && npm run webpack-server-build",
9 | "webpack-server-build": "rm -rf ./dist/* && ./node_modules/webpack/bin/webpack.js --config ./webpack/webpack.server.config.js",
10 | "webpack-client-build": "./node_modules/webpack/bin/webpack.js --config ./webpack/webpack.browser.config.js",
11 | "serve": "npm run build && pm2 stop all && pm2 start ./dist/main.js",
12 | "build-prod": "npm run webpack-client-build-prod && npm run webpack-server-build-prod",
13 | "webpack-server-build-prod": "rm -rf ./dist/* && ./node_modules/webpack/bin/webpack.js --config ./webpack/webpack.server.config.js -p",
14 | "webpack-client-build-prod": "./node_modules/webpack/bin/webpack.js --config ./webpack/webpack.browser.config.js -p",
15 | "serve-prod": "npm run build-prod && pm2 stop all && pm2 start ./dist/main.js"
16 | },
17 | "keywords": [
18 | "guild",
19 | "javascript",
20 | "js",
21 | "libraries"
22 | ],
23 | "author": "Arpit Bhayani",
24 | "license": "ISC",
25 | "dependencies": {
26 | "express": "^4.13.4",
27 | "extract-text-webpack-plugin": "^1.0.1",
28 | "history": "^2.0.1",
29 | "jquery": "^2.2.2",
30 | "json-loader": "^0.5.4",
31 | "raw-loader": "^0.5.1",
32 | "react": "^0.14.7",
33 | "react-dom": "^0.14.7",
34 | "react-router": "^2.0.1",
35 | "superagent": "^1.8.1"
36 | },
37 | "devDependencies": {
38 | "babel-core": "^5.8.25",
39 | "babel-eslint": "^4.1.3",
40 | "babel-loader": "^5.3.2",
41 | "chalk": "^1.1.1",
42 | "clean-webpack-plugin": "^0.1.8",
43 | "css-loader": "^0.20.1",
44 | "eslint": "^1.7.3",
45 | "eslint-config-airbnb": "^0.1.0",
46 | "eslint-loader": "^1.1.0",
47 | "eslint-plugin-react": "^3.6.3",
48 | "file-loader": "^0.8.4",
49 | "imports-loader": "^0.6.5",
50 | "node-sass": "^3.3.3",
51 | "sass-loader": "^3.0.0",
52 | "style-loader": "^0.13.0",
53 | "stylelint": "^4.2.0",
54 | "stylelint-loader": "^0.2.0",
55 | "url-loader": "^0.5.6",
56 | "webpack": "^1.12.2"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/webpack/webpack.browser.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var path = require('path');
3 | var CleanWebpackPlugin = require('clean-webpack-plugin');
4 | module.exports = {
5 | name: "client",
6 | entry: {
7 | jsGuildHome: "./src/components/jsguild-home/jsguild-home.jsx",
8 | vendors: [
9 | 'react',
10 | 'react-dom',
11 | 'react-router',
12 | 'history'
13 | ]
14 | },
15 | output: {
16 | filename: "./js/[name]-[chunkhash].js",
17 | path: "build",
18 | },
19 | module: {
20 | preLoaders: [{
21 | test: /(\.js$|\.jsx$)/,
22 | exclude: /node_modules/,
23 | loader: "eslint-loader"
24 | }
25 | ],
26 | loaders : [
27 | {
28 | test: /vendors\/.+\.(jsx|js)$/,
29 | loader: 'imports?jQuery=jquery,$=jquery,this=>window'
30 | },
31 | {
32 | test: /client\/.+\.(jsx|js)$/,
33 | loader: 'imports?jQuery=jquery,$=jquery,this=>window'
34 | },
35 | {
36 | test: /(\.js$|\.jsx$)/,
37 | exclude: /node_modules/,
38 | loader: "babel-loader",
39 | },{
40 | test: /\.json?$/,
41 | exclude: /node_modules/,
42 | loader: "json-loader",
43 | },{
44 | test: /\.scss?$/,
45 | exclude: /node_modules/,
46 | loaders: ["style", "css", "sass"],
47 | },{
48 | test: /\.css$/,
49 | exclude: /node_modules/,
50 | loader: 'style-loader!css-loader'
51 | },{
52 | test: /\.(png|jpg|svg)$/,
53 | exclude: /node_modules/,
54 | loader: 'url-loader?limit=8192'
55 | },{
56 | test : /\.(ttf|eot|woff(2)?)(\?[a-z0-9]+)?$/,
57 | exclude: /node_modules/,
58 | loader : 'file-loader'
59 | }
60 | ]
61 | },
62 | eslint: {
63 | configFile: '.eslintrc'
64 | },
65 | plugins: [
66 | new webpack.optimize.CommonsChunkPlugin('vendors', './js/vendors-[chunkhash].js', Infinity),
67 | function() {
68 | this.plugin("done", function(stats) {
69 | require("fs").writeFileSync(
70 | path.join(__dirname, "..", "src", "stats.json"),
71 | JSON.stringify(stats.toJson().assetsByChunkName));
72 | });
73 | },
74 | new CleanWebpackPlugin(['dist', 'build'], {
75 | verbose: true,
76 | dry: false,
77 | root: path.join(__dirname, '..'),
78 | })
79 | ]
80 | }
81 |
--------------------------------------------------------------------------------