Skip to content

Instantly share code, notes, and snippets.

@genomics-geek
Last active September 9, 2021 23:11
Show Gist options
  • Save genomics-geek/81c6880ca862d99574c6f84dec81acb0 to your computer and use it in GitHub Desktop.
Save genomics-geek/81c6880ca862d99574c6f84dec81acb0 to your computer and use it in GitHub Desktop.

Revisions

  1. genomics-geek revised this gist May 11, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -278,7 +278,7 @@ config.output = {
    publicPath: 'http://0.0.0.0:3000/js/builds/',
    };

    config.module.rules[0].use[0].plugins = ['react-hot-loader/babel'];
    config.module.rules[0].use[0].options.plugins = ['react-hot-loader/babel'];

    config.plugins = [
    new webpack.HotModuleReplacementPlugin(),
  2. genomics-geek revised this gist May 11, 2017. 1 changed file with 55 additions and 37 deletions.
    92 changes: 55 additions & 37 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -136,7 +136,7 @@ Run `npm init` and follow the instructions. Just fill in the information for you
    These are webpack packages. To read more about Webpack visit [here](https://webpack.github.io/). For now, I am using Webpack v1 because Webpack v2 seems a bit unstable and has changed a bit.

    ```
    npm install --save-dev webpack@1 webpack-dev-server@1 webpack-bundle-tracker
    npm install --save-dev webpack webpack-dev-server webpack-bundle-tracker
    ```

    ### Install babel compiler and plugins
    @@ -173,7 +173,7 @@ ReactJS and Redux plugins:
    **NOTE**: Sticking with react-router@3 and react-router-redux@4 because new versions are in beta and unstable.

    ```
    npm install --save-dev prop-types react-bootstrap react-fontawesome react-router@3 react-router-redux@4 react-cookie redux-logger redux-thunk react-redux
    npm install --save-dev prop-types react-bootstrap react-fontawesome react-router@3 react-router-redux@4 react-cookie redux-logger redux-thunk react-redux semantic-ui-react
    ```

    To allow for hot reloading of React components:
    @@ -216,25 +216,40 @@ mkdir -p frontend/webpack/
    Create `frontend/webpack/webpack.base.config.js`. The contents should be:

    ```javascript
    var path = require('path');

    module.exports = {

    module: {
    loaders: [{
    test: /\.(js|jsx)$/,
    exclude: /node_modules/,
    loader: 'babel-loader',
    query: {
    presets: ['es2015', 'stage-2', 'react']
    rules: [
    {
    test: /\.(js|jsx)$/,
    exclude: /node_modules/,
    use: [
    {
    loader: 'babel-loader',
    options: {
    presets: [['es2015', { modules: false }], 'stage-2', 'react']
    }
    }
    ]
    },
    {
    test: /\.css$/,
    use: [
    'style-loader',
    'css-loader'
    ]
    }
    }, {
    test: /\.css$/,
    loader: 'style-loader!css-loader'
    }]
    ]
    },

    resolve: {
    modulesDirectories: ['node_modules'],
    extensions: ['', '.js', '.jsx']
    modules: [
    path.join(__dirname, 'frontend/js/src'),
    'node_modules'
    ],
    extensions: ['.js', '.jsx']
    }
    };
    ```
    @@ -249,20 +264,22 @@ var config = require('./webpack.base.config.js');

    config.entry = {
    main: [
    'react-hot-loader/patch',
    'webpack-dev-server/client?http://0.0.0.0:3000',
    'webpack/hot/only-dev-server',
    'react-hot-loader/patch',
    path.join(__dirname, '../js/src/main/index')
    ]
    };

    config.devtool = 'inline-sourcemap';
    config.devtool = 'eval';
    config.output = {
    path: path.join(__dirname, '../js/builds-dev/'),
    filename: '[name]-[hash].js',
    publicPath: 'http://0.0.0.0:3000/js/builds/',
    };

    config.module.rules[0].use[0].plugins = ['react-hot-loader/babel'];

    config.plugins = [
    new webpack.HotModuleReplacementPlugin(),
    new BundleTracker({ filename: './frontend/webpack/webpack-stats.dev.json' }),
    @@ -274,11 +291,8 @@ config.plugins = [
    })
    ];

    config.module.loaders[0].query.plugins = ['react-hot-loader/babel'];

    config.devServer = {
    inline: true,
    progress: true,
    hot: true,
    historyApiFallback: true,
    host: '0.0.0.0',
    @@ -311,17 +325,21 @@ config.output = {

    config.plugins = [
    new BundleTracker({ filename: './frontend/webpack/webpack-stats.production.json' }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.DefinePlugin({
    'process.env': {
    NODE_ENV: JSON.stringify('production'),
    BASE_URL: JSON.stringify('http://0.0.0.0/'),
    }
    }),
    new webpack.LoaderOptionsPlugin({
    minimize: true
    }),
    new webpack.optimize.UglifyJsPlugin({
    mangle: false,
    sourcemap: false
    sourcemap: true,
    compress: {
    warnings: true
    }
    })
    ];

    @@ -417,6 +435,9 @@ Create file `<project-name>/templates/react-base.html` and add the following con

    <!-- Google Fonts https://fonts.google.com/ -->
    <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">

    <!-- Semantic UI for React https://react.semantic-ui.com/usage -->
    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css">

    <!-- Project specific Stylesheets -->
    {% endblock stylesheets %}
    @@ -709,23 +730,20 @@ import configureStore from './Store';
    const store = configureStore();
    const history = syncHistoryWithStore(browserHistory, store);

    ReactDOM.render(
    <AppContainer>
    <Root store={store} history={history} />
    </AppContainer>,
    document.getElementById('react-root')
    );

    const render = (Component) => {
    ReactDOM.render(
    <AppContainer>
    <Component store={store} history={history} />
    </AppContainer>,
    document.getElementById('react-root')
    );
    };

    render(Root);

    if (module.hot) {
    module.hot.accept('./Root', () => {
    const Root = require('./Root').default;
    ReactDOM.render(
    <AppContainer>
    <Root store={store} history={history} />
    </AppContainer>,
    document.getElementById('react-root')
    );
    });
    module.hot.accept('./Root', () => { render(Root); });
    }
    ```

  3. genomics-geek revised this gist May 11, 2017. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -282,7 +282,8 @@ config.devServer = {
    hot: true,
    historyApiFallback: true,
    host: '0.0.0.0',
    port: 3000
    port: 3000,
    headers: { 'Access-Control-Allow-Origin': '*' }
    };

    module.exports = config;
  4. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -840,7 +840,7 @@ var testsContext = require.context('.', true, /.spec$/);
    testsContext.keys().forEach(testsContext);
    ```

    Create example test `frontend/js/src/test_index.js`. Contents:
    Create example test `frontend/js/src/example.spec.js`. Contents:

    ```javascript
    import expect from 'expect';
  5. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 20 additions and 0 deletions.
    20 changes: 20 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -831,4 +831,24 @@ module.exports = function (config) {
    }
    });
    };
    ```

    Create test index `frontend/js/src/test_index.js`. Contents:

    ```javascript
    var testsContext = require.context('.', true, /.spec$/);
    testsContext.keys().forEach(testsContext);
    ```

    Create example test `frontend/js/src/test_index.js`. Contents:

    ```javascript
    import expect from 'expect';


    describe('Something abstract', () => {
    it('works', () => {
    expect(1).toEqual(1);
    });
    });
    ```
  6. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -354,7 +354,7 @@ In `package.json` add the following to scripts:
    ```


    ## 4. Wireup Django/ReactJS
    ## 5. Wireup Django/ReactJS

    This will create a django template where ReactJS can inject into.

    @@ -456,7 +456,7 @@ url(r'^pages/(?P<route>.*)$', TemplateView.as_view(template_name='index.html')),
    ```


    ## 5. Create your React/Redux app
    ## 6. Create your React/Redux app

    This will set up your ReactJS project using Redux store to contain your application state. In addition, it will set up Hot Reloading and Redux DevTools :).

    @@ -758,7 +758,7 @@ export default routes;
    ```


    ## 6. Setup JS Unit testing
    ## 7. Setup JS Unit testing

    This will setup karma as the test runner.

  7. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 76 additions and 0 deletions.
    76 changes: 76 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -756,3 +756,79 @@ const routes = (

    export default routes;
    ```


    ## 6. Setup JS Unit testing

    This will setup karma as the test runner.

    Create file `frontend/webpack/karma.config.js`. It's contents should be:

    ```javascript
    var webpackConfig = require('./webpack.local.config.js');

    webpackConfig.entry = {};

    module.exports = function (config) {
    config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha'],

    // list of files / patterns to load in the browser
    files: [
    '../js/src/test_index.js'
    ],

    // list of files to exclude
    exclude: [],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    '../js/src/test_index.js': ['webpack', 'sourcemap'],
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,
    autoWatchBatchDelay: 300,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity,

    // Webpack
    webpack: webpackConfig,
    webpackServer: {
    noInfo: true
    }
    });
    };
    ```
  8. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -733,7 +733,8 @@ if (module.hot) {

    In `frontend/js/src/main/routes.jsx`, add the contents:

    **NOTE:** This will have a Hello World place holder!
    **NOTE:** This will have a Hello World place holder.
    **NOTE:** When running the application, edit Hello World and see it update in the browser automagically.

    ```javascript
    import React from 'react';
  9. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 0 additions and 4 deletions.
    4 changes: 0 additions & 4 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -680,12 +680,8 @@ In `frontend/js/src/main/reducers.js`, add the contents:
    import { combineReducers } from 'redux';
    import { routerReducer } from 'react-router-redux';

    // Import reducers here and place them into the reducers object
    import { reducers as homeReducers } from './Home';


    const rootReducer = combineReducers({
    searching: homeReducers.searchReducer,
    routing: routerReducer
    });

  10. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 13 additions and 0 deletions.
    13 changes: 13 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -340,6 +340,19 @@ touch frontend/builds/.gitkeep
    touch frontend/builds-dev/.gitkeep
    ```

    ### Create Node shortcuts

    In `package.json` add the following to scripts:

    ```json
    "scripts": {
    "build-development": "webpack --config frontend/webpack/webpack.local.config.js --progress --colors",
    "build-production": "webpack --config frontend/webpack/webpack.production.config.js --progress --colors",
    "watch": "webpack-dev-server --config frontend/webpack/webpack.local.config.js",
    "test": "./node_modules/karma/bin/karma start frontend/webpack/karma.config.js --log-level debug"
    }
    ```


    ## 4. Wireup Django/ReactJS

  11. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 28 additions and 0 deletions.
    28 changes: 28 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -718,3 +718,31 @@ if (module.hot) {
    });
    }
    ```


    ### Create client-side routing

    In `frontend/js/src/main/routes.jsx`, add the contents:

    **NOTE:** This will have a Hello World place holder!

    ```javascript
    import React from 'react';
    import { Route } from 'react-router';


    const HelloWorld = () =>
    <div>
    Hellow World!
    </div>;


    const routes = (
    <div>
    <Route path="/" component={HelloWorld} />
    </div>
    );


    export default routes;
    ```
  12. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 60 additions and 0 deletions.
    60 changes: 60 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -658,3 +658,63 @@ Root.propTypes = {
    export default Root;
    ```


    ### Create Redux combined reducers

    In `frontend/js/src/main/reducers.js`, add the contents:

    ```javascript
    import { combineReducers } from 'redux';
    import { routerReducer } from 'react-router-redux';

    // Import reducers here and place them into the reducers object
    import { reducers as homeReducers } from './Home';


    const rootReducer = combineReducers({
    searching: homeReducers.searchReducer,
    routing: routerReducer
    });


    export default rootReducer;
    ```


    ### Create React project entry point

    In `frontend/js/src/main/index.js`, add the contents:

    ```javascript
    import React from 'react';
    import ReactDOM from 'react-dom';
    import { AppContainer } from 'react-hot-loader';
    import { browserHistory } from 'react-router';
    import { syncHistoryWithStore } from 'react-router-redux';

    import Root from './Root';
    import configureStore from './Store';


    const store = configureStore();
    const history = syncHistoryWithStore(browserHistory, store);

    ReactDOM.render(
    <AppContainer>
    <Root store={store} history={history} />
    </AppContainer>,
    document.getElementById('react-root')
    );

    if (module.hot) {
    module.hot.accept('./Root', () => {
    const Root = require('./Root').default;
    ReactDOM.render(
    <AppContainer>
    <Root store={store} history={history} />
    </AppContainer>,
    document.getElementById('react-root')
    );
    });
    }
    ```
  13. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 100 additions and 0 deletions.
    100 changes: 100 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -556,5 +556,105 @@ export default configureStore;
    ```


    ### Create React Root

    Create files:

    ```
    touch frontend/js/src/main/Root/index.js
    touch frontend/js/src/main/Root/DevTools.jsx
    touch frontend/js/src/main/Root/Root.development.jsx
    touch frontend/js/src/main/Root/Root.production.js
    ```

    Contents of `index.js`:

    ```javascript
    if (process.env.NODE_ENV === 'production') {
    module.exports = require('./Root.production');
    } else {
    module.exports = require('./Root.development')
    }
    ```

    Contents of `DevTools.jsx`:

    ```javascript
    import React from 'react';
    import { createDevTools } from 'redux-devtools';
    import LogMonitor from 'redux-devtools-log-monitor';
    import DockMonitor from 'redux-devtools-dock-monitor';


    const DevTools = createDevTools(
    <DockMonitor toggleVisibilityKey="ctrl-h" changePositionKey="ctrl-w">
    <LogMonitor />
    </DockMonitor>
    );


    export default DevTools;
    ```

    Contents of `Root.development.jsx`:

    ```javascript
    import React from 'react';
    import { Provider } from 'react-redux';
    import { Router } from 'react-router';
    import PropTypes from 'prop-types';


    import DevTools from './DevTools';
    import routes from '../routes';


    const Root = ({ store, history }) => {
    return (
    <Provider store={store}>
    <div>
    <Router history={history} routes={routes} />
    <DevTools />
    </div>
    </Provider>
    );
    };

    Root.propTypes = {
    store: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
    };


    export default Root;
    ```

    Contents of `Root.production.jsx`:

    ```javascript
    import React from 'react';
    import { Provider } from 'react-redux';
    import { Router } from 'react-router';
    import PropTypes from 'prop-types';


    import routes from '../routes';


    const Root = ({ store, history }) => {
    return (
    <Provider store={store}>
    <Router history={history} routes={routes} />
    </Provider>
    );
    };

    Root.propTypes = {
    store: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
    };


    export default Root;
    ```

  14. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 114 additions and 0 deletions.
    114 changes: 114 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -442,5 +442,119 @@ url(r'^app/(?P<route>.*)$', TemplateView.as_view(template_name='index.html')),
    url(r'^pages/(?P<route>.*)$', TemplateView.as_view(template_name='index.html')),
    ```


    ## 5. Create your React/Redux app

    This will set up your ReactJS project using Redux store to contain your application state. In addition, it will set up Hot Reloading and Redux DevTools :).

    ### Create ReactJS project structure

    + main - Where the main app will live
    + Root - Where we will set up the main App component
    + Store - Where we will configure the Redux store
    + reducers.js - Where we will combine all application reducers for the Redux store
    + routes.jsx - Where we will establish the client side routing

    ```
    mkdir -p frontend/js/src/main/
    mkdir -p frontend/js/src/main/Root
    mkdir -p frontend/js/src/main/Store
    mkdir -p frontend/js/src/main/utils
    touch frontend/js/src/main/reducers.js
    touch frontend/js/src/main/routes.jsx
    ```

    ### Create Redux Store

    Create files:

    ```
    touch frontend/js/src/main/Store/index.js
    touch frontend/js/src/main/Store/ConfigureStore.development.js
    touch frontend/js/src/main/Store/ConfigureStore.production.js
    ```

    Contents of `index.js`:

    ```javascript
    if (process.env.NODE_ENV === 'production') {
    module.exports = require('./ConfigureStore.production');
    } else {
    module.exports = require('./ConfigureStore.development')
    }
    ```

    Contents of `ConfigureStore.development.js`:

    ```javascript
    import { browserHistory } from 'react-router';
    import { routerMiddleware } from 'react-router-redux';
    import { createStore, applyMiddleware, compose } from 'redux';
    import { createLogger } from 'redux-logger';
    import thunk from 'redux-thunk';


    import DevTools from '../Root/DevTools';
    import rootReducer from '../reducers';


    const enhancer = compose(
    // Middleware you want to use in development
    applyMiddleware(thunk, createLogger()),
    applyMiddleware(routerMiddleware(browserHistory)),
    // Required! Enable Redux DevTools with the monitors you chose
    DevTools.instrument()
    );

    // Function to call to configure Redux store
    const configureStore = (initialState) => {
    // Note: only Redux >= 3.1.0 supports passing enhancer as third argument
    // See: https://github.com/rackt/redux/releases/tag/v3.1.0
    const store = createStore(rootReducer, initialState, enhancer);

    // Hot Reload reducers
    // Note: Requires Webpack or Browserify HMR to be enabled
    if (module.hot) {
    module.hot.accept('../reducers', () =>
    store.replaceReducer(require('../reducers').default)
    );
    }
    return store;
    };


    export default configureStore;
    ```

    Contents of `ConfigureStore.production.js`:

    ```javascript
    import { browserHistory } from 'react-router';
    import { routerMiddleware } from 'react-router-redux';
    import { createStore, applyMiddleware, compose } from 'redux';
    import thunk from 'redux-thunk';


    import rootReducer from '../reducers';


    const enhancer = compose(
    // Middleware you want to use in production
    applyMiddleware(thunk),
    applyMiddleware(routerMiddleware(browserHistory)),
    );

    // Function to call to configure Redux store
    const configureStore = (initialState) => {
    // Note: only Redux >= 3.1.0 supports passing enhancer as third argument
    // See: https://github.com/rackt/redux/releases/tag/v3.1.0
    return createStore(rootReducer, initialState, enhancer);
    };


    export default configureStore;
    ```




  15. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 10 additions and 0 deletions.
    10 changes: 10 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -432,5 +432,15 @@ Create file `<project-name>/templates/react-base.html` and add the following con
    </html>
    ```

    ### Adjust main URLConf in Django

    We will adjust our Django urls to allow client-side routing. Add the following routes to your URLs:

    ```python
    url(r'^$', TemplateView.as_view(template_name='index.html')),
    url(r'^app/(?P<route>.*)$', TemplateView.as_view(template_name='index.html')),
    url(r'^pages/(?P<route>.*)$', TemplateView.as_view(template_name='index.html')),
    ```



  16. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 91 additions and 0 deletions.
    91 changes: 91 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -341,5 +341,96 @@ touch frontend/builds-dev/.gitkeep
    ```


    ## 4. Wireup Django/ReactJS

    This will create a django template where ReactJS can inject into.

    ### Create django templates

    Create file `<project-name>/templates/index.html` and add the following contents:

    ```html
    {% extends 'react-base.html' %}
    {% load staticfiles %}
    {% load render_bundle from webpack_loader %}

    {% block body %}
    <div id="react-root"></div>
    {% endblock body %}

    {% block javascript %}
    {% render_bundle 'main' %}
    {% endblock javascript %}
    ```

    Create file `<project-name>/templates/react-base.html` and add the following contents:

    **NOTE** This includes some goodies like google fonts, bootstrap, and font-awesome :). Feel free to remove them.

    ```html
    {% load staticfiles %}
    <html class="{% block html_class %}{% endblock html_class %}" lang="en">
    <head>
    <!-- Allows you to inject head elements here -->
    {% block head %}

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->

    <meta name="author" content="">
    <meta name="description" content="">
    <meta name="keywords" content="">

    <title>{% block head_title %}{% endblock head_title %}</title>

    <!-- Allows you to inject CCS here -->
    {% block stylesheets %}

    <!-- Third-party CSS libraries go here -->
    <!-- Latest compiled and minified Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

    <!-- Optional Bootstrap theme -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

    <!-- FontAwesome http://fontawesome.io/ -->
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">

    <!-- Animate CSS https://github.com/daneden/animate.css -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">

    <!-- Google Fonts https://fonts.google.com/ -->
    <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">

    <!-- Project specific Stylesheets -->
    {% endblock stylesheets %}

    <!-- Title Icon -->
    <!-- <link rel="shortcut icon" href=""> -->

    {% endblock head %}

    </head>
    <body class="{% block body_class %}{% endblock body_class %}">

    <!-- Allows you to inject body content here -->
    {% block body %}
    {% endblock body %}

    <!-- Project specific JavaScript -->
    <!-- Allows you to inject JavaScript here -->
    {% block javascript %}
    {% endblock javascript %}

    <!-- Google Analytics goes here -->
    {% block google_analytics %}
    {% endblock google_analytics %}

    </body>
    </html>
    ```



  17. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -97,7 +97,7 @@ In Production settings:
    # See: https://whitenoise.readthedocs.io/
    WHITENOISE_MIDDLEWARE = ['whitenoise.middleware.WhiteNoiseMiddleware', ]
    # CORS Needs to go first! See: https://github.com/ottoyiu/django-cors-headers#setup
    MIDDLEWARE = SECURITY_MIDDLEWARE + CORS_MIDDLEWARE + WHITENOISE_MIDDLEWARE + DJANGO_MIDDLEWARE
    MIDDLEWARE = SECURITY_MIDDLEWARE + CORS_MIDDLEWARE + WHITENOISE_MIDDLEWARE + DJANGO_MIDDLEWARE
    ```


  18. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 40 additions and 0 deletions.
    40 changes: 40 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -62,6 +62,46 @@ WEBPACK_LOADER = {
    }
    ```

    Add CORS middleware according to these [instructions](https://github.com/ottoyiu/django-cors-headers#setup). I personally split them up like below. This allows us to meet the criteria of both CORS and Whitenoise :).

    In Base settings:

    ```python
    # MIDDLEWARE CONFIGURATION
    # ------------------------------------------------------------------------------
    SECURITY_MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    ]

    # This is required to go first! See: https://github.com/ottoyiu/django-cors-headers#setup
    CORS_MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    ]

    DJANGO_MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

    MIDDLEWARE = SECURITY_MIDDLEWARE + CORS_MIDDLEWARE + DJANGO_MIDDLEWARE
    ```

    In Production settings:

    ```python
    # Use Whitenoise to serve static files
    # See: https://whitenoise.readthedocs.io/
    WHITENOISE_MIDDLEWARE = ['whitenoise.middleware.WhiteNoiseMiddleware', ]
    # CORS Needs to go first! See: https://github.com/ottoyiu/django-cors-headers#setup
    MIDDLEWARE = SECURITY_MIDDLEWARE + CORS_MIDDLEWARE + WHITENOISE_MIDDLEWARE + DJANGO_MIDDLEWARE
    ```




    ## 2. Adjust STATICFILES

  19. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -293,7 +293,7 @@ module.exports = config;
    ```
    mkdir -p frontend/js/src/main
    mkdir -p frontend/builds
    mkdir -p frontend/builds-development
    mkdir -p frontend/builds-dev
    touch frontend/js/src/main/index.jsx
    touch frontend/builds/.gitkeep
  20. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 12 additions and 0 deletions.
    12 changes: 12 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -288,6 +288,18 @@ module.exports = config;
    ```


    ### Create the entry point for our front-end project

    ```
    mkdir -p frontend/js/src/main
    mkdir -p frontend/builds
    mkdir -p frontend/builds-development
    touch frontend/js/src/main/index.jsx
    touch frontend/builds/.gitkeep
    touch frontend/builds-dev/.gitkeep
    ```




  21. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 129 additions and 0 deletions.
    129 changes: 129 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -160,5 +160,134 @@ npm install --save-dev eslint eslint-plugin-import eslint-plugin-jsx-a11y eslint
    npm install --save-dev karma mocha expect deepfreeze karma-mocha karma-webpack karma-sourcemap-loader karma-chrome-launcher karma-babel-preprocessor enzyme
    ```


    ## 4. Setup Webpack module bundler

    This will help us bundle and compile all of our front-end stuff. To read more, visit [here](https://webpack.github.io/). In short, it bundles all JavaScript, JSX, etc. code for our project and manages our codebase to be split into bundles to be loaded in in our different environments.

    ### Create our webpack dir

    ```
    mkdir -p frontend/webpack/
    ```

    ### Create our base webpack config

    Create `frontend/webpack/webpack.base.config.js`. The contents should be:

    ```javascript
    module.exports = {

    module: {
    loaders: [{
    test: /\.(js|jsx)$/,
    exclude: /node_modules/,
    loader: 'babel-loader',
    query: {
    presets: ['es2015', 'stage-2', 'react']
    }
    }, {
    test: /\.css$/,
    loader: 'style-loader!css-loader'
    }]
    },

    resolve: {
    modulesDirectories: ['node_modules'],
    extensions: ['', '.js', '.jsx']
    }
    };
    ```

    Create `frontend/webpack/webpack.local.config.js`. The contents should be:

    ```javascript
    var path = require('path');
    var BundleTracker = require('webpack-bundle-tracker');
    var webpack = require('webpack');
    var config = require('./webpack.base.config.js');

    config.entry = {
    main: [
    'webpack-dev-server/client?http://0.0.0.0:3000',
    'webpack/hot/only-dev-server',
    'react-hot-loader/patch',
    path.join(__dirname, '../js/src/main/index')
    ]
    };

    config.devtool = 'inline-sourcemap';
    config.output = {
    path: path.join(__dirname, '../js/builds-dev/'),
    filename: '[name]-[hash].js',
    publicPath: 'http://0.0.0.0:3000/js/builds/',
    };

    config.plugins = [
    new webpack.HotModuleReplacementPlugin(),
    new BundleTracker({ filename: './frontend/webpack/webpack-stats.dev.json' }),
    new webpack.DefinePlugin({
    'process.env': {
    NODE_ENV: JSON.stringify('development'),
    BASE_URL: JSON.stringify('http://0.0.0.0:8000/'),
    }
    })
    ];

    config.module.loaders[0].query.plugins = ['react-hot-loader/babel'];

    config.devServer = {
    inline: true,
    progress: true,
    hot: true,
    historyApiFallback: true,
    host: '0.0.0.0',
    port: 3000
    };

    module.exports = config;
    ```

    Create `frontend/webpack/webpack.production.config.js`. The contents should be:

    ```javascript
    var path = require('path');
    var webpack = require('webpack');
    var BundleTracker = require('webpack-bundle-tracker');
    var config = require('./webpack.base.config.js');

    config.entry = {
    main: [
    path.join(__dirname, '../js/src/main/index')
    ]
    };

    config.output = {
    path: path.join(__dirname, '../js/builds/'),
    filename: '[name]-[hash].min.js',
    publicPath: '/js/builds/'
    };

    config.plugins = [
    new BundleTracker({ filename: './frontend/webpack/webpack-stats.production.json' }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.DefinePlugin({
    'process.env': {
    NODE_ENV: JSON.stringify('production'),
    BASE_URL: JSON.stringify('http://0.0.0.0/'),
    }
    }),
    new webpack.optimize.UglifyJsPlugin({
    mangle: false,
    sourcemap: false
    })
    ];

    module.exports = config;
    ```





  22. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -111,9 +111,10 @@ npm install --save-dev babel-cli babel-core babel-loader babel-preset-es2015 bab

    + [axios](https://github.com/mzabriskie/axios) - Helpful to interact with an API
    + [lodash](https://lodash.com/) - Helpful extra methods that are missing in JS
    + [victory](http://formidable.com/open-source/victory/) - Amazing library for charting

    ```
    npm install --save-dev axios lodash
    npm install --save-dev axios lodash victory
    ```

    ### Install ReactJS and Redux and associated plugins
  23. genomics-geek revised this gist Apr 17, 2017. 1 changed file with 85 additions and 3 deletions.
    88 changes: 85 additions & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,8 @@

    This guide will help set up your django project to use ReactJS

    ## Install Python dependencies

    ## 1. Install Python dependencies

    ### Add pip requirements to our django project:

    @@ -61,7 +62,8 @@ WEBPACK_LOADER = {
    }
    ```

    ## Adjust STATICFILES

    ## 2. Adjust STATICFILES

    This where our ReactJS project will live.

    @@ -78,4 +80,84 @@ STATICFILES_DIRS = [
    str(APPS_DIR.path('static')),
    str(ROOT_DIR.path('frontend')),
    ]
    ```
    ```


    ## 3. Install Node dependencies

    This will install all the Javascript libraries we will use

    ### Setup Node

    Run `npm init` and follow the instructions. Just fill in the information for your project.

    ### Install webpack packages

    These are webpack packages. To read more about Webpack visit [here](https://webpack.github.io/). For now, I am using Webpack v1 because Webpack v2 seems a bit unstable and has changed a bit.

    ```
    npm install --save-dev webpack@1 webpack-dev-server@1 webpack-bundle-tracker
    ```

    ### Install babel compiler and plugins

    These are packages that allow us to write our code using new ES6 JS. To read more, visit [here](http://es6-features.org/#Constants).

    ```
    npm install --save-dev babel-cli babel-core babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-2 css-loader style-loader
    ```

    ### Install additionaly helpful libs

    + [axios](https://github.com/mzabriskie/axios) - Helpful to interact with an API
    + [lodash](https://lodash.com/) - Helpful extra methods that are missing in JS

    ```
    npm install --save-dev axios lodash
    ```

    ### Install ReactJS and Redux and associated plugins

    + [ReactJS](https://facebook.github.io/react/) is a JS lib for building UIs
    + [Redux](http://redux.js.org/) is a predictable state container for JS apps

    Main ReactJS and Redux:

    ```
    npm install --save-dev react react-dom redux
    ```

    ReactJS and Redux plugins:

    **NOTE**: Sticking with react-router@3 and react-router-redux@4 because new versions are in beta and unstable.

    ```
    npm install --save-dev prop-types react-bootstrap react-fontawesome react-router@3 react-router-redux@4 react-cookie redux-logger redux-thunk react-redux
    ```

    To allow for hot reloading of React components:

    ```
    npm install --save-dev react-hot-loader@next redux-devtools redux-devtools-dock-monitor redux-devtools-log-monitor
    ```

    ### Install ESLint packages

    I choose to use the airbnb JS standards, since they have clearly stated it [here](https://github.com/airbnb/javascript)

    ```
    npm install --save-dev eslint eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react eslint-config-airbnb babel-eslint
    ```

    ### Install Unit Testing packages

    + [Karma](https://karma-runner.github.io/1.0/index.html) - Test runner
    + [Mocha](https://mochajs.org/) - Testing framework
    + [expect](https://github.com/mjackson/expect) - lets you write better assertions

    ```
    npm install --save-dev karma mocha expect deepfreeze karma-mocha karma-webpack karma-sourcemap-loader karma-chrome-launcher karma-babel-preprocessor enzyme
    ```



  24. genomics-geek created this gist Apr 17, 2017.
    81 changes: 81 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    # Setting up ReactJS/Redux using Webpack for an existing Django project

    This guide will help set up your django project to use ReactJS

    ## Install Python dependencies

    ### Add pip requirements to our django project:

    + django-webpack-loader==0.4.1 ( Connects Django project with Webpack)
    + django-cors-headers==2.0.2 (Allows us to easily customize CORS settings)

    ### Add new dependencies to INSTALLED_APPS

    ```python
    INSTALLED_APPS = [
    ...
    'corsheaders',
    'webpack_loader',
    ...
    ]
    ```

    ### Adjust settings for new apps

    Add CORS settings in your base settings:

    ```python
    # CORS CONFIGURATION
    # ------------------------------------------------------------------------------
    # https://github.com/ottoyiu/django-cors-headers#configuration
    CORS_ORIGIN_ALLOW_ALL = True
    ```

    Add Webpack loader settings for local and production settings.

    Local:

    ```python
    # Webpack Loader by Owais Lane
    # ------------------------------------------------------------------------------
    # https://github.com/owais/django-webpack-loader
    WEBPACK_LOADER = {
    'DEFAULT': {
    'BUNDLE_DIR_NAME': 'builds-dev/',
    'STATS_FILE': os.path.join(str(ROOT_DIR), 'frontend', 'webpack', 'webpack-stats.dev.json')
    }
    }
    ```

    Production:

    ```python
    # Webpack Loader by Owais Lane
    # ------------------------------------------------------------------------------
    # https://github.com/owais/django-webpack-loader
    WEBPACK_LOADER = {
    'DEFAULT': {
    'BUNDLE_DIR_NAME': 'builds/',
    'STATS_FILE': os.path.join(ROOT_DIR, 'frontend', 'webpack', 'webpack-stats.production.json')
    }
    }
    ```

    ## Adjust STATICFILES

    This where our ReactJS project will live.

    ### Create a frontend directory

    ```
    mkdir -p frontend
    ```

    ### Add new path to STATICFILES_DIRS

    ```python
    STATICFILES_DIRS = [
    str(APPS_DIR.path('static')),
    str(ROOT_DIR.path('frontend')),
    ]
    ```