From 8d78d69e3958a5c6ce76c362d8a6cd4fe5d63cbc Mon Sep 17 00:00:00 2001 From: Byung Jun Park Date: Sun, 23 Jul 2017 23:40:48 +0900 Subject: [PATCH] Dev Tools --- config/webpack/webpack.config.base.js | 1 + config/webpack/webpack.config.dev.js | 32 +++++++++++++-- package.json | 9 ++++- src/ts/@overflow/app/index.tsx | 57 ++++++++++++++++++++++++--- src/ts/@overflow/app/redux/store.ts | 34 ++++++++++++++-- 5 files changed, 118 insertions(+), 15 deletions(-) diff --git a/config/webpack/webpack.config.base.js b/config/webpack/webpack.config.base.js index 34cae75..3155c2a 100644 --- a/config/webpack/webpack.config.base.js +++ b/config/webpack/webpack.config.base.js @@ -6,6 +6,7 @@ module.exports = { target: 'web', entry: { app: [ + 'react-hot-loader/patch', Path.resolve(__dirname, '../../src/ts/@overflow/app/index.tsx') ], vendor: Object.keys(packages.dependencies) diff --git a/config/webpack/webpack.config.dev.js b/config/webpack/webpack.config.dev.js index bed2205..de2ccca 100644 --- a/config/webpack/webpack.config.dev.js +++ b/config/webpack/webpack.config.dev.js @@ -2,6 +2,7 @@ const Path = require('path'); const Webpack = require('webpack'); const WebpackMerge = require('webpack-merge'); const HtmlWebpackPlugin = require('html-webpack-plugin'); +const WebpackDashboardPlugin = require('webpack-dashboard/plugin'); const configBase = require('./webpack.config.base.js'); module.exports = WebpackMerge(configBase, { @@ -46,21 +47,44 @@ module.exports = WebpackMerge(configBase, { Path.resolve(__dirname, '../../node_modules/') ] }, + // { + // test: /\.tsx?$/, + // loaders: [ + // 'awesome-typescript-loader' + // ], + // exclude: [ + // Path.resolve(__dirname, '../../node_modules/') + // ], + // include: [ + // Path.resolve(__dirname, '../../src/') + // ] + // }, { test: /\.tsx?$/, - loaders: [ - 'awesome-typescript-loader' - ], exclude: [ Path.resolve(__dirname, '../../node_modules/') ], include: [ Path.resolve(__dirname, '../../src/') - ] + ], + use: [ + { + loader: 'react-hot-loader/webpack' + }, + { + loader: 'awesome-typescript-loader', + options: { + transpileOnly: true, + useTranspileModule: false, + sourceMap: true, + }, + }, + ], }, ] }, plugins: [ + new WebpackDashboardPlugin(), new Webpack.HotModuleReplacementPlugin(), new Webpack.NamedModulesPlugin(), new Webpack.NoEmitOnErrorsPlugin(), diff --git a/package.json b/package.json index 190e6e7..a83069b 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,12 @@ "clean": "./node_modules/.bin/rimraf ./dist", "prepublish": "yarn run build", "postpublish": "./node_modules/.bin/greenkeeper-postpublish", - "start": "set NODE_ENV=development && ./node_modules/.bin/webpack-dev-server --open --progress --config ./config/webpack/webpack.config.dev.js", + "start": "set NODE_ENV=development && ./node_modules/.bin/webpack-dashboard -- ./node_modules/.bin/webpack-dev-server --open --progress --config ./config/webpack/webpack.config.dev.js", "test": "yarn run jest", "test:watch": "yarn run jest -- --watch", "jest": "PWD=$(pwd) NODE_ENV=test ./node_modules/.bin/jest -w 1 --coverage", "prebuild": "./node_modules/.bin/check-dependencies && yarn run clean", - "build": "set NODE_ENV=production && ./node_modules/.bin/webpack --progress --profile --colors --config ./config/webpack/webpack.config.prod.js", + "build": "set NODE_ENV=production && ./node_modules/.bin/webpack-dashboard -m -- ./node_modules/.bin/webpack --progress --profile --colors --config ./config/webpack/webpack.config.prod.js", "lint": "./node_modules/.bin/tslint -c tslint.json 'src/ts/**/*.{ts,tsx}' && ./node_modules/.bin/sass-lint 'src/**/*.scss'", "stats": "set NODE_ENV=production && webpack --progress --config ./config/webpack/webpack.config.stats.js --profile --json > ./config/webpack/stats/stats.json" }, @@ -27,6 +27,7 @@ "@types/react": "^15.0.38", "@types/react-addons-test-utils": "^0.14.19", "@types/react-dom": "^15.5.1", + "@types/react-hot-loader": "^3.0.3", "@types/react-redux": "^4.4.46", "@types/react-router": "^4.0.14", "@types/react-router-dom": "^4.0.7", @@ -48,6 +49,9 @@ "postcss-loader": "^2.0.5", "raw-loader": "^0.5.1", "react-addons-test-utils": "^15.5.1", + "react-hot-loader": "next", + "redux-devtools-extension": "^2.13.2", + "redux-logger": "^3.0.6", "rimraf": "^2.6.1", "sass-lint": "^1.10.2", "sass-loader": "^6.0.5", @@ -58,6 +62,7 @@ "tslint-react": "^3.0.0", "typescript": "^2.4.1", "webpack": "^2.6.1", + "webpack-dashboard": "^0.4.0", "webpack-dev-server": "^2.5.0", "webpack-merge": "^4.1.0", "webpack-visualizer-plugin": "^0.1.11" diff --git a/src/ts/@overflow/app/index.tsx b/src/ts/@overflow/app/index.tsx index 7e28aec..7126f59 100644 --- a/src/ts/@overflow/app/index.tsx +++ b/src/ts/@overflow/app/index.tsx @@ -4,6 +4,7 @@ import { Provider, Store } from 'react-redux'; import { ConnectedRouter } from 'react-router-redux'; import createSagaMiddleware, { SagaMiddleware } from 'redux-saga'; import { History } from 'history'; +import { AppContainer } from 'react-hot-loader'; import * as injectTapEventPlugin from 'react-tap-event-plugin'; @@ -22,8 +23,7 @@ import App from './views/App'; injectTapEventPlugin(); -const rpcURL = 'ws://127.0.0.1:18081/rpc'; - +const isProduction:boolean = process.env.NODE_ENV === 'production' ? true : false; class Application { private config: Config; @@ -41,9 +41,9 @@ class Application { this.history = history; } - public static async Run(): Promise { + public static Run(): void { let application = new Application(); - return application.start(); + application.start(); } private async start(): Promise { @@ -88,7 +88,11 @@ class Application { return rpcClient; } - private initSagaEffect(): Promise { + private initRedux(): Promise { + // state tree + // reducer + // middleware + // saga const rpcClient = new Promise(resolve => { this.sagaMiddleware.run(sagas); resolve(); @@ -97,6 +101,14 @@ class Application { return rpcClient; } + private initSagaEffect(): Promise { + const rpcClient = new Promise(resolve => { + this.sagaMiddleware.run(sagas); + resolve(); + }); + + return rpcClient; + } private displayLoading(): void { ReactDOM.render( @@ -132,6 +144,9 @@ class Application { private displayApp(): void { + isProduction ? this.displayProductionApp() : this.displayDebugApp(); + } + private displayProductionApp(): void { ReactDOM.render( @@ -141,6 +156,38 @@ class Application { this.container, ); } + private displayDebugApp(): void { + if (module.hot) { + // app + module.hot.accept('./views/App', async () => { + // const NextApp = require('./app').App; + const NextApp = (await import('./views/App')).default; + ReactDOM.render( + + + + + + + + , + this.container, + ); + }); + } + + ReactDOM.render( + + + + + + + + , + this.container, + ); + } } diff --git a/src/ts/@overflow/app/redux/store.ts b/src/ts/@overflow/app/redux/store.ts index 1665dbc..6e07a57 100644 --- a/src/ts/@overflow/app/redux/store.ts +++ b/src/ts/@overflow/app/redux/store.ts @@ -1,19 +1,45 @@ -import { applyMiddleware, compose, createStore, Store } from 'redux'; +import { + applyMiddleware, + compose, + createStore, + Store, +} from 'redux'; import { routerMiddleware } from 'react-router-redux'; -import createSagaMiddleware, { SagaMiddleware } from 'redux-saga'; -import { createHashHistory, History } from 'history'; +import createSagaMiddleware, { + SagaMiddleware, +} from 'redux-saga'; +import { + createHashHistory, + History, +} from 'history'; + +import { + EnhancerOptions, + composeWithDevTools, +} from 'redux-devtools-extension/logOnlyInProduction'; + +import reduxLogger from 'redux-logger'; import reducer from './reducer'; import State from './state'; +const useReduxDevTools = window.devToolsExtension && process.env.NODE_ENV !== 'production' ? true : false; + + const history = createHashHistory(); const sagaMiddleware: SagaMiddleware = createSagaMiddleware(); const middlewares = [sagaMiddleware, routerMiddleware(history)]; const store: Store = createStore( reducer, - applyMiddleware(...middlewares), + useReduxDevTools ? + compose( + applyMiddleware(...middlewares), + window.devToolsExtension(), + ) + : + applyMiddleware(...middlewares), ); export {