Feat: Add react-hot-loader
Combine webpack and browser-sync on one portpull/10949/head
parent
d3f8757e92
commit
a6f9e95ed8
|
@ -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$/,
|
||||
|
|
Loading…
Reference in New Issue