Feat: Add react-hot-loader
Combine webpack and browser-sync on one port
This commit is contained in:
		| @@ -28,8 +28,8 @@ import { | ||||
|  | ||||
| const isDev = Rx.config.longStackSupport = debug.enabled('fcc:*'); | ||||
| const log = debug('fcc:client'); | ||||
| const hotReloadTimeout = 5000; | ||||
| const csrfToken = window.__fcc__.csrf.token; | ||||
| const hotReloadTimeout = 2000; | ||||
| const { csrf: { csrfToken } = {} } = window.__fcc__; | ||||
| const DOMContainer = document.getElementById('fcc'); | ||||
| const initialState = isColdStored() ? | ||||
|   getColdStorage() : | ||||
| @@ -37,7 +37,8 @@ const initialState = isColdStored() ? | ||||
| initialState.app.csrfToken = csrfToken; | ||||
| initialState.toasts = flashToToast(window.__fcc__.flash); | ||||
|  | ||||
| delete window.__fcc__; | ||||
| // make empty object so hot reload works | ||||
| window.__fcc__ = {}; | ||||
|  | ||||
| const serviceOptions = { xhrPath: '/services', context: { _csrf: csrfToken } }; | ||||
|  | ||||
| @@ -69,7 +70,10 @@ createApp({ | ||||
|   }) | ||||
|   .doOnNext(({ store }) => { | ||||
|     if (module.hot && typeof module.hot.accept === 'function') { | ||||
|       module.hot.accept('../common/app', function() { | ||||
|       module.hot.accept(err => { | ||||
|         if (err) { console.error(err); } | ||||
|         log('saving state and refreshing.'); | ||||
|         log('ignore react ssr warning.'); | ||||
|         saveToColdStorage(store.getState()); | ||||
|         setTimeout(() => window.location.reload(), hotReloadTimeout); | ||||
|       }); | ||||
|   | ||||
							
								
								
									
										103
									
								
								gulpfile.js
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								gulpfile.js
									
									
									
									
									
								
							| @@ -25,12 +25,13 @@ var Rx = require('rx'), | ||||
|   // react app | ||||
|   webpack = require('webpack'), | ||||
|   webpackStream = require('webpack-stream'), | ||||
|   WebpackDevServer = require('webpack-dev-server'), | ||||
|   webpackDevMiddleware = require('webpack-dev-middleware'), | ||||
|   webpackHotMiddleware = require('webpack-hot-middleware'), | ||||
|   webpackConfig = require('./webpack.config.js'), | ||||
|  | ||||
|   // server process | ||||
|   nodemon = require('gulp-nodemon'), | ||||
|   sync = require('browser-sync'), | ||||
|   browserSync = require('browser-sync'), | ||||
|  | ||||
|   // css | ||||
|   less = require('gulp-less'), | ||||
| @@ -48,10 +49,18 @@ var Rx = require('rx'), | ||||
|   tapSpec = require('tap-spec'); | ||||
|  | ||||
| Rx.config.longStackSupport = true; | ||||
| var sync = browserSync.create('fcc-sync-server'); | ||||
| var reload = sync.reload.bind(sync); | ||||
|  | ||||
| // user definable | ||||
| var __DEV__ = !yargs.argv.p; | ||||
| var reloadDelay = 1000; | ||||
| var reload = sync.reload; | ||||
| var port = yargs.argv.port || process.env.PORT || '3001'; | ||||
| var syncPort = yargs.argv['sync-port'] || process.env.SYNC_PORT || '3000'; | ||||
| // make sure sync ui port does not interfere with proxy port | ||||
| var syncUIPort = yargs.argv['sync-ui-port'] || | ||||
|   process.env.SYNC_UI_PORT || | ||||
|   parseInt(syncPort, 10) + 2; | ||||
|  | ||||
| var paths = { | ||||
|   server: './server/server.js', | ||||
|   serverIgnore: [ | ||||
| @@ -171,25 +180,20 @@ gulp.task('serve', function(cb) { | ||||
|     exec: path.join(__dirname, 'node_modules/.bin/babel-node'), | ||||
|     env: { | ||||
|       NODE_ENV: process.env.NODE_ENV || 'development', | ||||
|       DEBUG: process.env.DEBUG || 'fcc:*' | ||||
|       DEBUG: process.env.DEBUG || 'fcc:*', | ||||
|       PORT: port | ||||
|     } | ||||
|   }) | ||||
|     .on('start', function() { | ||||
|       if (!called) { | ||||
|         called = true; | ||||
|         setTimeout(function() { | ||||
|           cb(); | ||||
|         }, reloadDelay); | ||||
|         cb(); | ||||
|       } | ||||
|     }) | ||||
|     .on('restart', function(files) { | ||||
|       if (files) { | ||||
|         debug('Files that changes: ', files); | ||||
|         debug('Nodemon will restart due to changes in: ', files); | ||||
|       } | ||||
|       setTimeout(function() { | ||||
|         debug('Restarting browsers'); | ||||
|         reload(); | ||||
|       }, reloadDelay); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| @@ -199,14 +203,34 @@ var syncDepenedents = [ | ||||
|   'less' | ||||
| ]; | ||||
|  | ||||
| gulp.task('sync', syncDepenedents, function() { | ||||
| gulp.task('dev-server', syncDepenedents, function() { | ||||
|   webpackConfig.entry.bundle = [ | ||||
|     'webpack/hot/dev-server', | ||||
|     'webpack-hot-middleware/client' | ||||
|   ].concat(webpackConfig.entry.bundle); | ||||
|  | ||||
|   var bundler = webpack(webpackConfig); | ||||
|   sync.init(null, { | ||||
|     proxy: 'http://localhost:3000', | ||||
|     ui: { | ||||
|       port: syncUIPort | ||||
|     }, | ||||
|     proxy: { | ||||
|       target: `http://localhost:${port}`, | ||||
|       reqHeaders: ({ url: { hostname } }) => ({ | ||||
|         host: `${hostname}:${syncPort}` | ||||
|       }) | ||||
|     }, | ||||
|     logLeval: 'debug', | ||||
|     files: paths.syncWatch, | ||||
|     port: 3001, | ||||
|     port: syncPort, | ||||
|     open: false, | ||||
|     reloadDelay: reloadDelay | ||||
|     middleware: [ | ||||
|       webpackDevMiddleware(bundler, { | ||||
|         publicPath: webpackConfig.output.publicPath, | ||||
|         stats: 'errors-only' | ||||
|       }), | ||||
|       webpackHotMiddleware(bundler) | ||||
|     ] | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| @@ -273,46 +297,6 @@ gulp.task('clean-webpack-manifest', cleanDeps, function() { | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| var webpackCalled = false; | ||||
| gulp.task('webpack-dev-server', function(cb) { | ||||
|   if (webpackCalled) { | ||||
|     console.log('webpack dev server already runnning'); | ||||
|     return cb(); | ||||
|   } | ||||
|   var devServerOptions = { | ||||
|     headers: { | ||||
|       'Access-Control-Allow-Credentials': 'true' | ||||
|     }, | ||||
|     hot: true, | ||||
|     noInfo: true, | ||||
|     contentBase: false, | ||||
|     publicPath: '/js' | ||||
|   }; | ||||
|   webpackConfig.entry.bundle = [ | ||||
|     'webpack-dev-server/client?http://localhost:2999/', | ||||
|     'webpack/hot/dev-server' | ||||
|   ].concat(webpackConfig.entry.bundle); | ||||
|  | ||||
|   var compiler = webpack(webpackConfig); | ||||
|   var devServer = new WebpackDevServer(compiler, devServerOptions); | ||||
|   devServer.use(function(req, res, next) { | ||||
|     res.setHeader('Access-Control-Allow-Origin', req.headers.origin || '*'); | ||||
|     next(); | ||||
|   }); | ||||
|   return devServer.listen('2999', 'localhost', function(err) { | ||||
|       if (err) { | ||||
|         throw new gutil.PluginError('webpack-dev-server', err); | ||||
|       } | ||||
|  | ||||
|       if (!webpackCalled) { | ||||
|         gutil.log('[webpack-dev-server]', 'webpack init completed'); | ||||
|         webpackCalled = true; | ||||
|         cb(); | ||||
|       } | ||||
|  | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| gulp.task('less', function() { | ||||
|   var manifestName = 'css-manifest.json'; | ||||
|   var dest = paths.css; | ||||
| @@ -435,7 +419,7 @@ var watchDependents = [ | ||||
|   'less', | ||||
|   'js', | ||||
|   'serve', | ||||
|   'sync' | ||||
|   'dev-server' | ||||
| ]; | ||||
|  | ||||
| gulp.task('reload', function() { | ||||
| @@ -453,9 +437,8 @@ gulp.task('watch', watchDependents, function() { | ||||
| gulp.task('default', [ | ||||
|   'less', | ||||
|   'serve', | ||||
|   'webpack-dev-server', | ||||
|   'watch', | ||||
|   'sync' | ||||
|   'dev-server' | ||||
| ]); | ||||
|  | ||||
| gulp.task('test', function() { | ||||
|   | ||||
| @@ -156,13 +156,15 @@ | ||||
|     "loopback-component-explorer": "^2.1.1", | ||||
|     "merge-stream": "^1.0.0", | ||||
|     "proxyquire": "^1.7.10", | ||||
|     "react-hot-loader": "^1.3.0", | ||||
|     "rev-del": "^1.0.5", | ||||
|     "sinon": "^1.17.3", | ||||
|     "sort-keys": "^1.1.1", | ||||
|     "tap-spec": "^4.1.1", | ||||
|     "tape": "^4.2.2", | ||||
|     "webpack": "^1.9.12", | ||||
|     "webpack-dev-server": "^1.14.0", | ||||
|     "webpack-dev-middleware": "^1.8.3", | ||||
|     "webpack-hot-middleware": "^2.12.2", | ||||
|     "webpack-manifest-plugin": "^1.0.0", | ||||
|     "webpack-stream": "^3.1.0", | ||||
|     "yargs": "^5.0.0" | ||||
|   | ||||
| @@ -6,9 +6,7 @@ let trusted = [ | ||||
|  | ||||
| if (process.env.NODE_ENV !== 'production') { | ||||
|   trusted = trusted.concat([ | ||||
|     'ws://localhost:3001', | ||||
|     'http://localhost:2999', | ||||
|     'ws://localhost:2999' | ||||
|     'ws://localhost:3000' | ||||
|   ]); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,4 @@ | ||||
| import manifest from '../rev-manifest'; | ||||
| /* eslint-disable import/default */ | ||||
| import config from '../../webpack.config'; | ||||
| /* eslint-enable import/default */ | ||||
|  | ||||
| let chunkManifest; | ||||
| try { | ||||
| @@ -30,16 +27,9 @@ function removeOldTerms(str = '') { | ||||
|   return str.replace(challengesRegex, ''); | ||||
| } | ||||
|  | ||||
| function getBundleLocation() { | ||||
|   return __DEV__ ? | ||||
|     config.output.publicPath + '/bundle.js' : | ||||
|     rev('/js', 'bundle.js'); | ||||
| } | ||||
|  | ||||
| export default function jadeHelpers() { | ||||
|   return function jadeHelpersMiddleware(req, res, next) { | ||||
|     res.locals.removeOldTerms = removeOldTerms; | ||||
|     res.locals.getBundleLocation = getBundleLocation; | ||||
|     res.locals.rev = rev; | ||||
|     // static data | ||||
|     res.locals.user = req.user; | ||||
|   | ||||
| @@ -12,4 +12,4 @@ html(lang='en') | ||||
|     script. | ||||
|       window.webpackManifest = !{JSON.stringify(chunkManifest || {})}; | ||||
|     script(src=rev('/js', 'vendor-challenges.js')) | ||||
|     script(src=getBundleLocation()) | ||||
|     script(src=rev('/js', 'bundle.js')) | ||||
|   | ||||
| @@ -23,7 +23,7 @@ module.exports = { | ||||
|       'bundle-[name].js' : | ||||
|       'bundle-[name]-[chunkhash].js', | ||||
|     path: path.join(__dirname, '/public/js'), | ||||
|     publicPath: __DEV__ ? 'http://localhost:2999/js' : '/js' | ||||
|     publicPath: '/js' | ||||
|   }, | ||||
|   module: { | ||||
|     loaders: [ | ||||
| @@ -33,9 +33,7 @@ module.exports = { | ||||
|           path.join(__dirname, 'client/'), | ||||
|           path.join(__dirname, 'common/') | ||||
|         ], | ||||
|         loaders: [ | ||||
|           'babel-loader' | ||||
|         ] | ||||
|         loaders: __DEV__ ? ['react-hot', 'babel'] : [ 'babel' ] | ||||
|       }, | ||||
|       { | ||||
|         test: /\.json$/, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user