Skip to content
Permalink
18061b9716
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
875 lines (693 sloc) 29.9 KB
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
var _map = require('babel-runtime/core-js/map');
var _map2 = _interopRequireDefault(_map);
var _set = require('babel-runtime/core-js/set');
var _set2 = _interopRequireDefault(_set);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _getIterator2 = require('babel-runtime/core-js/get-iterator');
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _path = require('path');
var _webpackDevMiddleware = require('webpack-dev-middleware');
var _webpackDevMiddleware2 = _interopRequireDefault(_webpackDevMiddleware);
var _webpackHotMiddleware = require('webpack-hot-middleware');
var _webpackHotMiddleware2 = _interopRequireDefault(_webpackHotMiddleware);
var _onDemandEntryHandler = require('./on-demand-entry-handler');
var _onDemandEntryHandler2 = _interopRequireDefault(_onDemandEntryHandler);
var _webpack = require('webpack');
var _webpack2 = _interopRequireDefault(_webpack);
var _webpack3 = require('./build/webpack');
var _webpack4 = _interopRequireDefault(_webpack3);
var _clean = require('./build/clean');
var _clean2 = _interopRequireDefault(_clean);
var _config = require('./config');
var _config2 = _interopRequireDefault(_config);
var _uuid = require('uuid');
var _uuid2 = _interopRequireDefault(_uuid);
var _utils = require('./utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var HotReloader = function () {
function HotReloader(dir) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
quiet = _ref.quiet,
conf = _ref.conf;
(0, _classCallCheck3.default)(this, HotReloader);
this.dir = dir;
this.quiet = quiet;
this.middlewares = [];
this.webpackDevMiddleware = null;
this.webpackHotMiddleware = null;
this.initialized = false;
this.stats = null;
this.compilationErrors = null;
this.prevAssets = null;
this.prevChunkNames = null;
this.prevFailedChunkNames = null;
this.prevChunkHashes = null;
// Here buildId could be any value.
// Our router accepts any value in the dev mode.
// But for the webpack-compiler and for the webpack-dev-server
// it should be the same value.
this.buildId = _uuid2.default.v4();
this.config = (0, _config2.default)(dir, conf);
}
(0, _createClass3.default)(HotReloader, [{
key: 'run',
value: function () {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(req, res) {
var _this = this;
var _addCorsSupport, preflight, _loop, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, fn;
return _regenerator2.default.wrap(function _callee$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
// Usually CORS support is not needed for the hot-reloader (this is dev only feature)
// With when the app runs for multi-zones support behind a proxy,
// the current page is trying to access this URL via assetPrefix.
// That's when the CORS support is needed.
_addCorsSupport = (0, _utils.addCorsSupport)(req, res), preflight = _addCorsSupport.preflight;
if (!preflight) {
_context2.next = 3;
break;
}
return _context2.abrupt('return');
case 3:
_loop = /*#__PURE__*/_regenerator2.default.mark(function _loop(fn) {
return _regenerator2.default.wrap(function _loop$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return new _promise2.default(function (resolve, reject) {
fn(req, res, function (err) {
if (err) return reject(err);
resolve();
});
});
case 2:
case 'end':
return _context.stop();
}
}
}, _loop, _this);
});
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
_context2.prev = 7;
_iterator = (0, _getIterator3.default)(this.middlewares);
case 9:
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
_context2.next = 15;
break;
}
fn = _step.value;
return _context2.delegateYield(_loop(fn), 't0', 12);
case 12:
_iteratorNormalCompletion = true;
_context2.next = 9;
break;
case 15:
_context2.next = 21;
break;
case 17:
_context2.prev = 17;
_context2.t1 = _context2['catch'](7);
_didIteratorError = true;
_iteratorError = _context2.t1;
case 21:
_context2.prev = 21;
_context2.prev = 22;
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
case 24:
_context2.prev = 24;
if (!_didIteratorError) {
_context2.next = 27;
break;
}
throw _iteratorError;
case 27:
return _context2.finish(24);
case 28:
return _context2.finish(21);
case 29:
case 'end':
return _context2.stop();
}
}
}, _callee, this, [[7, 17, 21, 29], [22,, 24, 28]]);
}));
function run(_x2, _x3) {
return _ref2.apply(this, arguments);
}
return run;
}()
}, {
key: 'start',
value: function () {
var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
var configs, compiler, buildTools;
return _regenerator2.default.wrap(function _callee2$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_context3.next = 2;
return (0, _clean2.default)(this.dir);
case 2:
_context3.next = 4;
return _promise2.default.all([(0, _webpack4.default)(this.dir, { dev: true, isServer: false, config: this.config }), (0, _webpack4.default)(this.dir, { dev: true, isServer: true, config: this.config })]);
case 4:
configs = _context3.sent;
compiler = (0, _webpack2.default)(configs);
_context3.next = 8;
return this.prepareBuildTools(compiler);
case 8:
buildTools = _context3.sent;
this.assignBuildTools(buildTools);
_context3.next = 12;
return this.waitUntilValid();
case 12:
this.stats = _context3.sent.stats[0];
case 13:
case 'end':
return _context3.stop();
}
}
}, _callee2, this);
}));
function start() {
return _ref3.apply(this, arguments);
}
return start;
}()
}, {
key: 'stop',
value: function () {
var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(webpackDevMiddleware) {
var middleware;
return _regenerator2.default.wrap(function _callee3$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
middleware = webpackDevMiddleware || this.webpackDevMiddleware;
if (!middleware) {
_context4.next = 3;
break;
}
return _context4.abrupt('return', new _promise2.default(function (resolve, reject) {
middleware.close(function (err) {
if (err) return reject(err);
resolve();
});
}));
case 3:
case 'end':
return _context4.stop();
}
}
}, _callee3, this);
}));
function stop(_x4) {
return _ref4.apply(this, arguments);
}
return stop;
}()
}, {
key: 'reload',
value: function () {
var _ref5 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4() {
var configs, compiler, buildTools, oldWebpackDevMiddleware;
return _regenerator2.default.wrap(function _callee4$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
this.stats = null;
_context5.next = 3;
return (0, _clean2.default)(this.dir);
case 3:
_context5.next = 5;
return _promise2.default.all([(0, _webpack4.default)(this.dir, { dev: true, isServer: false, config: this.config }), (0, _webpack4.default)(this.dir, { dev: true, isServer: true, config: this.config })]);
case 5:
configs = _context5.sent;
compiler = (0, _webpack2.default)(configs);
_context5.next = 9;
return this.prepareBuildTools(compiler);
case 9:
buildTools = _context5.sent;
_context5.next = 12;
return this.waitUntilValid(buildTools.webpackDevMiddleware);
case 12:
this.stats = _context5.sent;
oldWebpackDevMiddleware = this.webpackDevMiddleware;
this.assignBuildTools(buildTools);
_context5.next = 17;
return this.stop(oldWebpackDevMiddleware);
case 17:
case 'end':
return _context5.stop();
}
}
}, _callee4, this);
}));
function reload() {
return _ref5.apply(this, arguments);
}
return reload;
}()
}, {
key: 'assignBuildTools',
value: function assignBuildTools(_ref6) {
var webpackDevMiddleware = _ref6.webpackDevMiddleware,
webpackHotMiddleware = _ref6.webpackHotMiddleware,
onDemandEntries = _ref6.onDemandEntries;
this.webpackDevMiddleware = webpackDevMiddleware;
this.webpackHotMiddleware = webpackHotMiddleware;
this.onDemandEntries = onDemandEntries;
this.middlewares = [webpackDevMiddleware, webpackHotMiddleware, onDemandEntries.middleware()];
}
}, {
key: 'prepareBuildTools',
value: function () {
var _ref7 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee5(compiler) {
var _this2 = this;
var ignored, webpackDevMiddlewareConfig, webpackDevMiddleware, webpackHotMiddleware, onDemandEntries;
return _regenerator2.default.wrap(function _callee5$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
// This flushes require.cache after emitting the files. Providing 'hot reloading' of server files.
compiler.compilers.forEach(function (singleCompiler) {
singleCompiler.plugin('after-emit', function (compilation, callback) {
var assets = compilation.assets;
if (_this2.prevAssets) {
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = (0, _getIterator3.default)((0, _keys2.default)(assets)), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var f = _step2.value;
deleteCache(assets[f].existsAt);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = (0, _getIterator3.default)((0, _keys2.default)(_this2.prevAssets)), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var _f = _step3.value;
if (!assets[_f]) {
deleteCache(_this2.prevAssets[_f].existsAt);
}
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
}
_this2.prevAssets = assets;
callback();
});
});
compiler.compilers[0].plugin('done', function (stats) {
var compilation = stats.compilation;
var chunkNames = new _set2.default(compilation.chunks.map(function (c) {
return c.name;
}).filter(function (name) {
return _utils.IS_BUNDLED_PAGE.test(name);
}));
var failedChunkNames = new _set2.default(compilation.errors.map(function (e) {
return e.module.reasons;
}).reduce(function (a, b) {
return a.concat(b);
}, []).map(function (r) {
return r.module.chunks;
}).reduce(function (a, b) {
return a.concat(b);
}, []).map(function (c) {
return c.name;
}));
var chunkHashes = new _map2.default(compilation.chunks.filter(function (c) {
return _utils.IS_BUNDLED_PAGE.test(c.name);
}).map(function (c) {
return [c.name, c.hash];
}));
if (_this2.initialized) {
// detect chunks which have to be replaced with a new template
// e.g, pages/index.js <-> pages/_error.js
var added = diff(chunkNames, _this2.prevChunkNames);
var removed = diff(_this2.prevChunkNames, chunkNames);
var succeeded = diff(_this2.prevFailedChunkNames, failedChunkNames);
// reload all failed chunks to replace the templace to the error ones,
// and to update error content
var failed = failedChunkNames;
var rootDir = (0, _path.join)('bundles', 'pages');
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = (0, _getIterator3.default)(new _set2.default([].concat((0, _toConsumableArray3.default)(added), (0, _toConsumableArray3.default)(removed), (0, _toConsumableArray3.default)(failed), (0, _toConsumableArray3.default)(succeeded)))), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var n = _step4.value;
var route = toRoute((0, _path.relative)(rootDir, n));
_this2.send('reload', route);
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4.return) {
_iterator4.return();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
var _iteratorNormalCompletion5 = true;
var _didIteratorError5 = false;
var _iteratorError5 = undefined;
try {
for (var _iterator5 = (0, _getIterator3.default)(chunkHashes), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
var _ref8 = _step5.value;
var _ref9 = (0, _slicedToArray3.default)(_ref8, 2);
var _n = _ref9[0];
var hash = _ref9[1];
if (!_this2.prevChunkHashes.has(_n)) continue;
if (_this2.prevChunkHashes.get(_n) === hash) continue;
var route = toRoute((0, _path.relative)(rootDir, _n));
// notify change to recover from runtime errors
_this2.send('change', route);
}
} catch (err) {
_didIteratorError5 = true;
_iteratorError5 = err;
} finally {
try {
if (!_iteratorNormalCompletion5 && _iterator5.return) {
_iterator5.return();
}
} finally {
if (_didIteratorError5) {
throw _iteratorError5;
}
}
}
}
_this2.initialized = true;
_this2.stats = stats;
_this2.compilationErrors = null;
_this2.prevChunkNames = chunkNames;
_this2.prevFailedChunkNames = failedChunkNames;
_this2.prevChunkHashes = chunkHashes;
});
ignored = [/(^|[/\\])\../, // .dotfiles
/node_modules/];
webpackDevMiddlewareConfig = {
publicPath: '/_next/webpack/',
noInfo: true,
quiet: true,
clientLogLevel: 'warning',
watchOptions: { ignored: ignored }
};
if (this.config.webpackDevMiddleware) {
console.log('> Using "webpackDevMiddleware" config function defined in ' + this.config.configOrigin + '.');
webpackDevMiddlewareConfig = this.config.webpackDevMiddleware(webpackDevMiddlewareConfig);
}
webpackDevMiddleware = (0, _webpackDevMiddleware2.default)(compiler, webpackDevMiddlewareConfig);
webpackHotMiddleware = (0, _webpackHotMiddleware2.default)(compiler.compilers[0], {
path: '/_next/webpack-hmr',
log: false,
heartbeat: 2500
});
onDemandEntries = (0, _onDemandEntryHandler2.default)(webpackDevMiddleware, compiler.compilers, (0, _extends3.default)({
dir: this.dir,
dev: true,
reload: this.reload.bind(this)
}, this.config.onDemandEntries));
return _context6.abrupt('return', {
webpackDevMiddleware: webpackDevMiddleware,
webpackHotMiddleware: webpackHotMiddleware,
onDemandEntries: onDemandEntries
});
case 9:
case 'end':
return _context6.stop();
}
}
}, _callee5, this);
}));
function prepareBuildTools(_x5) {
return _ref7.apply(this, arguments);
}
return prepareBuildTools;
}()
}, {
key: 'waitUntilValid',
value: function waitUntilValid(webpackDevMiddleware) {
var middleware = webpackDevMiddleware || this.webpackDevMiddleware;
return new _promise2.default(function (resolve) {
middleware.waitUntilValid(resolve);
});
}
}, {
key: 'getCompilationErrors',
value: function () {
var _ref10 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee6() {
var _stats$compilation, compiler, errors, _iteratorNormalCompletion6, _didIteratorError6, _iteratorError6, _iterator6, _step6, err, _iteratorNormalCompletion7, _didIteratorError7, _iteratorError7, _iterator7, _step7, r, _iteratorNormalCompletion8, _didIteratorError8, _iteratorError8, _iterator8, _step8, c, path, _errors;
return _regenerator2.default.wrap(function _callee6$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
_context7.next = 2;
return this.onDemandEntries.waitUntilReloaded();
case 2:
if (this.compilationErrors) {
_context7.next = 73;
break;
}
this.compilationErrors = new _map2.default();
if (!this.stats.hasErrors()) {
_context7.next = 73;
break;
}
_stats$compilation = this.stats.compilation, compiler = _stats$compilation.compiler, errors = _stats$compilation.errors;
_iteratorNormalCompletion6 = true;
_didIteratorError6 = false;
_iteratorError6 = undefined;
_context7.prev = 9;
_iterator6 = (0, _getIterator3.default)(errors);
case 11:
if (_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done) {
_context7.next = 59;
break;
}
err = _step6.value;
_iteratorNormalCompletion7 = true;
_didIteratorError7 = false;
_iteratorError7 = undefined;
_context7.prev = 16;
_iterator7 = (0, _getIterator3.default)(err.module.reasons);
case 18:
if (_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done) {
_context7.next = 42;
break;
}
r = _step7.value;
_iteratorNormalCompletion8 = true;
_didIteratorError8 = false;
_iteratorError8 = undefined;
_context7.prev = 23;
for (_iterator8 = (0, _getIterator3.default)(r.module.chunks); !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
c = _step8.value;
// get the path of the bundle file
path = (0, _path.join)(compiler.outputPath, c.name);
_errors = this.compilationErrors.get(path) || [];
this.compilationErrors.set(path, _errors.concat([err]));
}
_context7.next = 31;
break;
case 27:
_context7.prev = 27;
_context7.t0 = _context7['catch'](23);
_didIteratorError8 = true;
_iteratorError8 = _context7.t0;
case 31:
_context7.prev = 31;
_context7.prev = 32;
if (!_iteratorNormalCompletion8 && _iterator8.return) {
_iterator8.return();
}
case 34:
_context7.prev = 34;
if (!_didIteratorError8) {
_context7.next = 37;
break;
}
throw _iteratorError8;
case 37:
return _context7.finish(34);
case 38:
return _context7.finish(31);
case 39:
_iteratorNormalCompletion7 = true;
_context7.next = 18;
break;
case 42:
_context7.next = 48;
break;
case 44:
_context7.prev = 44;
_context7.t1 = _context7['catch'](16);
_didIteratorError7 = true;
_iteratorError7 = _context7.t1;
case 48:
_context7.prev = 48;
_context7.prev = 49;
if (!_iteratorNormalCompletion7 && _iterator7.return) {
_iterator7.return();
}
case 51:
_context7.prev = 51;
if (!_didIteratorError7) {
_context7.next = 54;
break;
}
throw _iteratorError7;
case 54:
return _context7.finish(51);
case 55:
return _context7.finish(48);
case 56:
_iteratorNormalCompletion6 = true;
_context7.next = 11;
break;
case 59:
_context7.next = 65;
break;
case 61:
_context7.prev = 61;
_context7.t2 = _context7['catch'](9);
_didIteratorError6 = true;
_iteratorError6 = _context7.t2;
case 65:
_context7.prev = 65;
_context7.prev = 66;
if (!_iteratorNormalCompletion6 && _iterator6.return) {
_iterator6.return();
}
case 68:
_context7.prev = 68;
if (!_didIteratorError6) {
_context7.next = 71;
break;
}
throw _iteratorError6;
case 71:
return _context7.finish(68);
case 72:
return _context7.finish(65);
case 73:
return _context7.abrupt('return', this.compilationErrors);
case 74:
case 'end':
return _context7.stop();
}
}
}, _callee6, this, [[9, 61, 65, 73], [16, 44, 48, 56], [23, 27, 31, 39], [32,, 34, 38], [49,, 51, 55], [66,, 68, 72]]);
}));
function getCompilationErrors() {
return _ref10.apply(this, arguments);
}
return getCompilationErrors;
}()
}, {
key: 'send',
value: function send(action) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
this.webpackHotMiddleware.publish({ action: action, data: args });
}
}, {
key: 'ensurePage',
value: function () {
var _ref11 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee7(page) {
return _regenerator2.default.wrap(function _callee7$(_context8) {
while (1) {
switch (_context8.prev = _context8.next) {
case 0:
_context8.next = 2;
return this.onDemandEntries.ensurePage(page);
case 2:
case 'end':
return _context8.stop();
}
}
}, _callee7, this);
}));
function ensurePage(_x6) {
return _ref11.apply(this, arguments);
}
return ensurePage;
}()
}]);
return HotReloader;
}();
exports.default = HotReloader;
function deleteCache(path) {
delete require.cache[path];
}
function diff(a, b) {
return new _set2.default([].concat((0, _toConsumableArray3.default)(a)).filter(function (v) {
return !b.has(v);
}));
}
function toRoute(file) {
var f = _path.sep === '\\' ? file.replace(/\\/g, '/') : file;
return ('/' + f).replace(/(\/index)?\.js$/, '') || '/';
}