hot-dev-client.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = connect;
  6. var _interop_require_default = require("@swc/helpers/lib/_interop_require_default.js").default;
  7. var _client = require("next/dist/compiled/@next/react-dev-overlay/dist/client");
  8. var _stripAnsi = _interop_require_default(require("next/dist/compiled/strip-ansi"));
  9. var _websocket = require("./websocket");
  10. var _formatWebpackMessages = _interop_require_default(require("./format-webpack-messages"));
  11. function connect() {
  12. (0, _client).register();
  13. (0, _websocket).addMessageListener((event)=>{
  14. if (event.data.indexOf('action') === -1) return;
  15. try {
  16. processMessage(event);
  17. } catch (ex) {
  18. console.warn('Invalid HMR message: ' + event.data + '\n', ex);
  19. }
  20. });
  21. return {
  22. subscribeToHmrEvent (handler) {
  23. customHmrEventHandler = handler;
  24. },
  25. onUnrecoverableError () {
  26. hadRuntimeError = true;
  27. }
  28. };
  29. }
  30. // This alternative WebpackDevServer combines the functionality of:
  31. // https://github.com/webpack/webpack-dev-server/blob/webpack-1/client/index.js
  32. // https://github.com/webpack/webpack/blob/webpack-1/hot/dev-server.js
  33. // It only supports their simplest configuration (hot updates on same server).
  34. // It makes some opinionated choices on top, like adding a syntax error overlay
  35. // that looks similar to our console output. The error overlay is inspired by:
  36. // https://github.com/glenjamin/webpack-hot-middleware
  37. window.__nextDevClientId = Math.round(Math.random() * 100 + Date.now());
  38. let hadRuntimeError = false;
  39. let customHmrEventHandler;
  40. // Remember some state related to hot module replacement.
  41. var isFirstCompilation = true;
  42. var mostRecentCompilationHash = null;
  43. var hasCompileErrors = false;
  44. function clearOutdatedErrors() {
  45. // Clean up outdated compile errors, if any.
  46. if (typeof console !== 'undefined' && typeof console.clear === 'function') {
  47. if (hasCompileErrors) {
  48. console.clear();
  49. }
  50. }
  51. }
  52. // Successful compilation.
  53. function handleSuccess() {
  54. clearOutdatedErrors();
  55. const isHotUpdate = !isFirstCompilation || window.__NEXT_DATA__.page !== '/_error' && isUpdateAvailable();
  56. isFirstCompilation = false;
  57. hasCompileErrors = false;
  58. // Attempt to apply hot updates or reload.
  59. if (isHotUpdate) {
  60. tryApplyUpdates(function onSuccessfulHotUpdate(hasUpdates) {
  61. // Only dismiss it when we're sure it's a hot update.
  62. // Otherwise it would flicker right before the reload.
  63. onFastRefresh(hasUpdates);
  64. });
  65. }
  66. }
  67. // Compilation with warnings (e.g. ESLint).
  68. function handleWarnings(warnings) {
  69. clearOutdatedErrors();
  70. const isHotUpdate = !isFirstCompilation;
  71. isFirstCompilation = false;
  72. hasCompileErrors = false;
  73. function printWarnings() {
  74. // Print warnings to the console.
  75. const formatted = (0, _formatWebpackMessages).default({
  76. warnings: warnings,
  77. errors: []
  78. });
  79. if (typeof console !== 'undefined' && typeof console.warn === 'function') {
  80. for(let i = 0; i < formatted.warnings.length; i++){
  81. if (i === 5) {
  82. console.warn('There were more warnings in other files.\n' + 'You can find a complete log in the terminal.');
  83. break;
  84. }
  85. console.warn((0, _stripAnsi).default(formatted.warnings[i]));
  86. }
  87. }
  88. }
  89. printWarnings();
  90. // Attempt to apply hot updates or reload.
  91. if (isHotUpdate) {
  92. tryApplyUpdates(function onSuccessfulHotUpdate(hasUpdates) {
  93. // Only dismiss it when we're sure it's a hot update.
  94. // Otherwise it would flicker right before the reload.
  95. onFastRefresh(hasUpdates);
  96. });
  97. }
  98. }
  99. // Compilation with errors (e.g. syntax error or missing modules).
  100. function handleErrors(errors) {
  101. clearOutdatedErrors();
  102. isFirstCompilation = false;
  103. hasCompileErrors = true;
  104. // "Massage" webpack messages.
  105. var formatted = (0, _formatWebpackMessages).default({
  106. errors: errors,
  107. warnings: []
  108. });
  109. // Only show the first error.
  110. (0, _client).onBuildError(formatted.errors[0]);
  111. // Also log them to the console.
  112. if (typeof console !== 'undefined' && typeof console.error === 'function') {
  113. for(var i = 0; i < formatted.errors.length; i++){
  114. console.error((0, _stripAnsi).default(formatted.errors[i]));
  115. }
  116. }
  117. // Do not attempt to reload now.
  118. // We will reload on next success instead.
  119. if (process.env.__NEXT_TEST_MODE) {
  120. if (self.__NEXT_HMR_CB) {
  121. self.__NEXT_HMR_CB(formatted.errors[0]);
  122. self.__NEXT_HMR_CB = null;
  123. }
  124. }
  125. }
  126. let startLatency = undefined;
  127. function onFastRefresh(hasUpdates) {
  128. (0, _client).onBuildOk();
  129. if (hasUpdates) {
  130. (0, _client).onRefresh();
  131. }
  132. if (startLatency) {
  133. const endLatency = Date.now();
  134. const latency = endLatency - startLatency;
  135. console.log(`[Fast Refresh] done in ${latency}ms`);
  136. (0, _websocket).sendMessage(JSON.stringify({
  137. event: 'client-hmr-latency',
  138. id: window.__nextDevClientId,
  139. startTime: startLatency,
  140. endTime: endLatency
  141. }));
  142. if (self.__NEXT_HMR_LATENCY_CB) {
  143. self.__NEXT_HMR_LATENCY_CB(latency);
  144. }
  145. }
  146. }
  147. // There is a newer version of the code available.
  148. function handleAvailableHash(hash) {
  149. // Update last known compilation hash.
  150. mostRecentCompilationHash = hash;
  151. }
  152. // Handle messages from the server.
  153. function processMessage(e) {
  154. const obj = JSON.parse(e.data);
  155. switch(obj.action){
  156. case 'building':
  157. {
  158. startLatency = Date.now();
  159. console.log('[Fast Refresh] rebuilding');
  160. break;
  161. }
  162. case 'built':
  163. case 'sync':
  164. {
  165. if (obj.hash) {
  166. handleAvailableHash(obj.hash);
  167. }
  168. const { errors , warnings } = obj;
  169. const hasErrors = Boolean(errors && errors.length);
  170. if (hasErrors) {
  171. (0, _websocket).sendMessage(JSON.stringify({
  172. event: 'client-error',
  173. errorCount: errors.length,
  174. clientId: window.__nextDevClientId
  175. }));
  176. return handleErrors(errors);
  177. }
  178. const hasWarnings = Boolean(warnings && warnings.length);
  179. if (hasWarnings) {
  180. (0, _websocket).sendMessage(JSON.stringify({
  181. event: 'client-warning',
  182. warningCount: warnings.length,
  183. clientId: window.__nextDevClientId
  184. }));
  185. return handleWarnings(warnings);
  186. }
  187. (0, _websocket).sendMessage(JSON.stringify({
  188. event: 'client-success',
  189. clientId: window.__nextDevClientId
  190. }));
  191. return handleSuccess();
  192. }
  193. case 'serverComponentChanges':
  194. {
  195. (0, _websocket).sendMessage(JSON.stringify({
  196. event: 'server-component-reload-page',
  197. clientId: window.__nextDevClientId
  198. }));
  199. return window.location.reload();
  200. }
  201. default:
  202. {
  203. if (customHmrEventHandler) {
  204. customHmrEventHandler(obj);
  205. break;
  206. }
  207. break;
  208. }
  209. }
  210. }
  211. // Is there a newer version of this code available?
  212. function isUpdateAvailable() {
  213. /* globals __webpack_hash__ */ // __webpack_hash__ is the hash of the current compilation.
  214. // It's a global variable injected by Webpack.
  215. return mostRecentCompilationHash !== __webpack_hash__;
  216. }
  217. // Webpack disallows updates in other states.
  218. function canApplyUpdates() {
  219. return module.hot.status() === 'idle';
  220. }
  221. function afterApplyUpdates(fn) {
  222. if (canApplyUpdates()) {
  223. fn();
  224. } else {
  225. function handler(status) {
  226. if (status === 'idle') {
  227. module.hot.removeStatusHandler(handler);
  228. fn();
  229. }
  230. }
  231. module.hot.addStatusHandler(handler);
  232. }
  233. }
  234. // Attempt to update code on the fly, fall back to a hard reload.
  235. function tryApplyUpdates(onHotUpdateSuccess) {
  236. if (!module.hot) {
  237. // HotModuleReplacementPlugin is not in Webpack configuration.
  238. console.error('HotModuleReplacementPlugin is not in Webpack configuration.');
  239. // window.location.reload();
  240. return;
  241. }
  242. if (!isUpdateAvailable() || !canApplyUpdates()) {
  243. (0, _client).onBuildOk();
  244. return;
  245. }
  246. function handleApplyUpdates(err, updatedModules) {
  247. if (err || hadRuntimeError || !updatedModules) {
  248. if (err) {
  249. console.warn('[Fast Refresh] performing full reload\n\n' + "Fast Refresh will perform a full reload when you edit a file that's imported by modules outside of the React rendering tree.\n" + 'You might have a file which exports a React component but also exports a value that is imported by a non-React component file.\n' + 'Consider migrating the non-React component export to a separate file and importing it into both files.\n\n' + 'It is also possible the parent component of the component you edited is a class component, which disables Fast Refresh.\n' + 'Fast Refresh requires at least one parent function component in your React tree.');
  250. } else if (hadRuntimeError) {
  251. console.warn('[Fast Refresh] performing full reload because your application had an unrecoverable error');
  252. }
  253. performFullReload(err);
  254. return;
  255. }
  256. const hasUpdates = Boolean(updatedModules.length);
  257. if (typeof onHotUpdateSuccess === 'function') {
  258. // Maybe we want to do something.
  259. onHotUpdateSuccess(hasUpdates);
  260. }
  261. if (isUpdateAvailable()) {
  262. // While we were updating, there was a new update! Do it again.
  263. tryApplyUpdates(hasUpdates ? _client.onBuildOk : onHotUpdateSuccess);
  264. } else {
  265. (0, _client).onBuildOk();
  266. if (process.env.__NEXT_TEST_MODE) {
  267. afterApplyUpdates(()=>{
  268. if (self.__NEXT_HMR_CB) {
  269. self.__NEXT_HMR_CB();
  270. self.__NEXT_HMR_CB = null;
  271. }
  272. });
  273. }
  274. }
  275. }
  276. // https://webpack.js.org/api/hot-module-replacement/#check
  277. module.hot.check(/* autoApply */ true).then((updatedModules)=>{
  278. handleApplyUpdates(null, updatedModules);
  279. }, (err)=>{
  280. handleApplyUpdates(err, null);
  281. });
  282. }
  283. function performFullReload(err) {
  284. const stackTrace = err && (err.stack && err.stack.split('\n').slice(0, 5).join('\n') || err.message || err + '');
  285. (0, _websocket).sendMessage(JSON.stringify({
  286. event: 'client-full-reload',
  287. stackTrace
  288. }));
  289. window.location.reload();
  290. }
  291. if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
  292. Object.defineProperty(exports.default, '__esModule', { value: true });
  293. Object.assign(exports.default, exports);
  294. module.exports = exports.default;
  295. }
  296. //# sourceMappingURL=hot-dev-client.js.map