next.js icon indicating copy to clipboard operation
next.js copied to clipboard

feat: stitch errors with react owner stack

Open huozhi opened this issue 1 year ago โ€ข 3 comments

What

When we're using experimental react, we'll leverage React's new experimental API captureOwnerStack to access the owner stack trace and then stitch it with the current error trace from the stack frame react-stack-bottom-frame.

As the API only existed on experimental channel of React, we only enable it when PPR is enabled right now. Could extend to when react experimental is used later. This feature is guard under a flag experimental.reactOwnerStack

Closes NDX-247

Why

In this way we'll provide more helpful stack trace for react errors, and users can easily tell how the error was triggered through the rendered component tree. This will directly help you locate the where error is exactly throwing from.

After Enabling the Flag

image

Before Enabling the Flag

image

huozhi avatar Sep 24 '24 09:09 huozhi

  • #71772 Graphite
  • #71716 Graphite
  • #70393 Graphite ๐Ÿ‘ˆ
  • #71632 Graphite
  • canary

This stack of pull requests is managed by Graphite. Learn more about stacking.

Join @huozhi and the rest of your teammates on Graphite Graphite

huozhi avatar Sep 24 '24 09:09 huozhi

Failing test suites

Commit: e20267b7566a00de85d5f3e94a4f0e304380f83f

pnpm test test/integration/amp-export-validation/test/index.test.js

  • AMP Validation on Export > production mode > should have shown errors during build
Expand output

โ— AMP Validation on Export โ€บ production mode โ€บ should have shown errors during build

expect(received).toMatch(expected)

Expected pattern: /error.*The mandatory attribute 'height' is missing in tag 'amp-video'\./
Received string:  "  โ–ฒ Next.js 15.0.2-canary.0ยท
   Checking validity of types ...
   Creating an optimized production build ...
 โœ“ Compiled successfully
   Collecting page data ...
   Generating static pages (0/8) ...
   Generating static pages (2/8)ยทยท
 โš  Linting is disabled.
Error occurred prerendering page \"/first\". Read more: https://nextjs.org/docs/messages/prerender-error
AssertionError: Assertion failed: WebAssembly is uninitialized

  at new module$contents$goog$asserts_AssertionError (../evalmachine.<anonymous>:102:1441)
  at module$contents$goog$asserts_doAssertFailure (../evalmachine.<anonymous>:103:354)
  at goog.asserts.assertExists (../evalmachine.<anonymous>:104:374)
  at Object.module$contents$amp$validator_validateString [as validateString] (../evalmachine.<anonymous>:2238:108)
  at Validator.validateString (../packages/next/dist/compiled/amphtml-validator/index.js:17:2057)
  at validateAmp (../packages/next/dist/export/routes/pages.js:92:34)
  at async exportPagesPage (../packages/next/dist/export/routes/pages.js:109:13)
  at async Span.traceAsyncFn (../packages/next/dist/trace/trace.js:157:20)
  at async exportPage (../packages/next/dist/export/worker.js:350:18)
  Export encountered an error on /first, exiting the build.
   โจฏ Static worker exited with code: 1 and signal: null
  "
  at Object.toMatch (integration/amp-export-validation/test/index.test.js:28:29)

Read more about building and testing Next.js in contributing.md.

ijjk avatar Sep 24 '24 11:09 ijjk

Stats from current PR

Default Build (Increase detected โš ๏ธ)
General Overall increase โš ๏ธ
vercel/next.js canary vercel/next.js 09-24-apply_stitch_errors Change
buildDuration 19.7s 16.5s N/A
buildDurationCached 15.4s 13.5s N/A
nodeModulesSize 373 MB 374 MB โš ๏ธ +97.6 kB
nextStartRea..uration (ms) 414ms 417ms N/A
Client Bundles (main, webpack) Overall increase โš ๏ธ
vercel/next.js canary vercel/next.js 09-24-apply_stitch_errors Change
2585.HASH.js gzip 169 B 169 B โœ“
7382-HASH.js gzip 5.27 kB 5.27 kB โœ“
850563de-HASH.js gzip 52.6 kB 52.6 kB N/A
9756-HASH.js gzip 44.6 kB 44.9 kB โš ๏ธ +331 B
framework-HASH.js gzip 57.4 kB 57.4 kB N/A
main-app-HASH.js gzip 232 B 233 B N/A
main-HASH.js gzip 32.8 kB 32.9 kB โš ๏ธ +134 B
webpack-HASH.js gzip 1.71 kB 1.71 kB N/A
Overall change 82.8 kB 83.3 kB โš ๏ธ +465 B
Legacy Client Bundles (polyfills)
vercel/next.js canary vercel/next.js 09-24-apply_stitch_errors Change
polyfills-HASH.js gzip 39.4 kB 39.4 kB โœ“
Overall change 39.4 kB 39.4 kB โœ“
Client Pages
vercel/next.js canary vercel/next.js 09-24-apply_stitch_errors Change
_app-HASH.js gzip 194 B 194 B โœ“
_error-HASH.js gzip 193 B 192 B N/A
amp-HASH.js gzip 511 B 510 B N/A
css-HASH.js gzip 343 B 341 B N/A
dynamic-HASH.js gzip 1.85 kB 1.84 kB N/A
edge-ssr-HASH.js gzip 264 B 266 B N/A
head-HASH.js gzip 363 B 361 B N/A
hooks-HASH.js gzip 392 B 390 B N/A
image-HASH.js gzip 4.41 kB 4.4 kB N/A
index-HASH.js gzip 268 B 268 B โœ“
link-HASH.js gzip 2.78 kB 2.78 kB N/A
routerDirect..HASH.js gzip 329 B 328 B N/A
script-HASH.js gzip 395 B 393 B N/A
withRouter-HASH.js gzip 324 B 325 B N/A
1afbb74e6ecf..834.css gzip 106 B 106 B โœ“
Overall change 568 B 568 B โœ“
Client Build Manifests
vercel/next.js canary vercel/next.js 09-24-apply_stitch_errors Change
_buildManifest.js gzip 746 B 750 B N/A
Overall change 0 B 0 B โœ“
Rendered Page Sizes
vercel/next.js canary vercel/next.js 09-24-apply_stitch_errors Change
index.html gzip 522 B 524 B N/A
link.html gzip 538 B 538 B โœ“
withRouter.html gzip 521 B 519 B N/A
Overall change 538 B 538 B โœ“
Edge SSR bundle Size
vercel/next.js canary vercel/next.js 09-24-apply_stitch_errors Change
edge-ssr.js gzip 128 kB 128 kB N/A
page.js gzip 187 kB 187 kB N/A
Overall change 0 B 0 B โœ“
Middleware size
vercel/next.js canary vercel/next.js 09-24-apply_stitch_errors Change
middleware-b..fest.js gzip 673 B 669 B N/A
middleware-r..fest.js gzip 155 B 156 B N/A
middleware.js gzip 31 kB 31 kB N/A
edge-runtime..pack.js gzip 844 B 844 B โœ“
Overall change 844 B 844 B โœ“
Next Runtimes Overall increase โš ๏ธ
vercel/next.js canary vercel/next.js 09-24-apply_stitch_errors Change
973-experime...dev.js gzip 322 B 322 B โœ“
973.runtime.dev.js gzip 314 B 314 B โœ“
app-page-exp...dev.js gzip 317 kB 317 kB โš ๏ธ +267 B
app-page-exp..prod.js gzip 121 kB 121 kB โœ“
app-page-tur..prod.js gzip 134 kB 134 kB โœ“
app-page-tur..prod.js gzip 129 kB 129 kB โœ“
app-page.run...dev.js gzip 307 kB 308 kB โš ๏ธ +264 B
app-page.run..prod.js gzip 117 kB 117 kB โœ“
app-route-ex...dev.js gzip 35.9 kB 35.9 kB โœ“
app-route-ex..prod.js gzip 24.4 kB 24.4 kB โœ“
app-route-tu..prod.js gzip 24.4 kB 24.4 kB โœ“
app-route-tu..prod.js gzip 24.2 kB 24.2 kB โœ“
app-route.ru...dev.js gzip 37.5 kB 37.5 kB โœ“
app-route.ru..prod.js gzip 24.2 kB 24.2 kB โœ“
pages-api-tu..prod.js gzip 9.61 kB 9.61 kB โœ“
pages-api.ru...dev.js gzip 11.4 kB 11.4 kB โœ“
pages-api.ru..prod.js gzip 9.61 kB 9.61 kB โœ“
pages-turbo...prod.js gzip 20.9 kB 20.9 kB โœ“
pages.runtim...dev.js gzip 26.5 kB 26.5 kB โœ“
pages.runtim..prod.js gzip 20.9 kB 20.9 kB โœ“
server.runti..prod.js gzip 58.4 kB 58.4 kB โœ“
Overall change 1.45 MB 1.46 MB โš ๏ธ +531 B
build cache Overall increase โš ๏ธ
vercel/next.js canary vercel/next.js 09-24-apply_stitch_errors Change
0.pack gzip 1.85 MB 1.85 MB โš ๏ธ +195 B
index.pack gzip 144 kB 143 kB N/A
Overall change 1.85 MB 1.85 MB โš ๏ธ +195 B
Diff details
Diff for page.js

Diff too large to display

Diff for middleware.js

Diff too large to display

Diff for edge-ssr.js

Diff too large to display

Diff for dynamic-HASH.js
@@ -1,7 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [2739],
   {
-    /***/ 9725: /***/ (
+    /***/ 1959: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -9,7 +9,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/dynamic",
         function () {
-          return __webpack_require__(5425);
+          return __webpack_require__(4291);
         },
       ]);
       if (false) {
@@ -18,7 +18,7 @@
       /***/
     },
 
-    /***/ 4979: /***/ (module, exports, __webpack_require__) => {
+    /***/ 9774: /***/ (module, exports, __webpack_require__) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -51,7 +51,7 @@
         __webpack_require__(6609)
       );
       const _loadablesharedruntime = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(2158)
+        __webpack_require__(2134)
       );
       const isServerSide = "object" === "undefined";
       // Normalize loader to return the module as form { default: Component } for `React.lazy`.
@@ -152,11 +152,7 @@
       /***/
     },
 
-    /***/ 9320: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
+    /***/ 81: /***/ (__unused_webpack_module, exports, __webpack_require__) => {
       "use strict";
       /* __next_internal_client_entry_do_not_use__  cjs */
       Object.defineProperty(exports, "__esModule", {
@@ -179,7 +175,7 @@
       /***/
     },
 
-    /***/ 2158: /***/ (
+    /***/ 2134: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -221,7 +217,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       const _react = /*#__PURE__*/ _interop_require_default._(
         __webpack_require__(6609)
       );
-      const _loadablecontextsharedruntime = __webpack_require__(9320);
+      const _loadablecontextsharedruntime = __webpack_require__(81);
       function resolve(obj) {
         return obj && obj.default ? obj.default : obj;
       }
@@ -456,7 +452,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       /***/
     },
 
-    /***/ 5425: /***/ (
+    /***/ 4291: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -471,7 +467,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(4744);
       /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(5937);
+        __webpack_require__(5904);
       /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_dynamic__WEBPACK_IMPORTED_MODULE_1__
@@ -480,12 +476,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       const DynamicHello = next_dynamic__WEBPACK_IMPORTED_MODULE_1___default()(
         () =>
           __webpack_require__
-            .e(/* import() */ 2585)
-            .then(__webpack_require__.bind(__webpack_require__, 2585))
+            .e(/* import() */ 5860)
+            .then(__webpack_require__.bind(__webpack_require__, 5860))
             .then((mod) => mod.Hello),
         {
           loadableGenerated: {
-            webpack: () => [/*require.resolve*/ 2585],
+            webpack: () => [/*require.resolve*/ 5860],
           },
         }
       );
@@ -512,12 +508,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       /***/
     },
 
-    /***/ 5937: /***/ (
+    /***/ 5904: /***/ (
       module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(4979);
+      module.exports = __webpack_require__(9774);
 
       /***/
     },
@@ -527,7 +523,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [2888, 9774, 179], () =>
-      __webpack_exec__(9725)
+      __webpack_exec__(1959)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for image-HASH.js
@@ -1,7 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [8358],
   {
-    /***/ 32: /***/ (
+    /***/ 6529: /***/ (
       __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
@@ -9,7 +9,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/image",
         function () {
-          return __webpack_require__(3299);
+          return __webpack_require__(9636);
         },
       ]);
       if (false) {
@@ -18,7 +18,7 @@
       /***/
     },
 
-    /***/ 9708: /***/ (module, exports, __webpack_require__) => {
+    /***/ 709: /***/ (module, exports, __webpack_require__) => {
       "use strict";
       /* __next_internal_client_entry_do_not_use__  cjs */
       Object.defineProperty(exports, "__esModule", {
@@ -40,17 +40,17 @@
         __webpack_require__(610)
       );
       const _head = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(5136)
+        __webpack_require__(9770)
       );
-      const _getimgprops = __webpack_require__(8064);
-      const _imageconfig = __webpack_require__(538);
-      const _imageconfigcontextsharedruntime = __webpack_require__(1780);
-      const _warnonce = __webpack_require__(2626);
-      const _routercontextsharedruntime = __webpack_require__(5197);
+      const _getimgprops = __webpack_require__(2298);
+      const _imageconfig = __webpack_require__(8401);
+      const _imageconfigcontextsharedruntime = __webpack_require__(947);
+      const _warnonce = __webpack_require__(8761);
+      const _routercontextsharedruntime = __webpack_require__(4785);
       const _imageloader = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(3204)
+        __webpack_require__(9836)
       );
-      const _usemergedref = __webpack_require__(7213);
+      const _usemergedref = __webpack_require__(8647);
       // This is replaced by webpack define plugin
       const configEnv = {
         deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
@@ -371,7 +371,7 @@
       /***/
     },
 
-    /***/ 7213: /***/ (module, exports, __webpack_require__) => {
+    /***/ 8647: /***/ (module, exports, __webpack_require__) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -432,7 +432,7 @@
       /***/
     },
 
-    /***/ 8064: /***/ (
+    /***/ 2298: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -448,9 +448,9 @@
           return getImgProps;
         },
       });
-      const _warnonce = __webpack_require__(2626);
-      const _imageblursvg = __webpack_require__(7001);
-      const _imageconfig = __webpack_require__(538);
+      const _warnonce = __webpack_require__(8761);
+      const _imageblursvg = __webpack_require__(34);
+      const _imageconfig = __webpack_require__(8401);
       const VALID_LOADING_VALUES =
         /* unused pure expression or super */ null && [
           "lazy",
@@ -824,7 +824,7 @@
       /***/
     },
 
-    /***/ 7001: /***/ (__unused_webpack_module, exports) => {
+    /***/ 34: /***/ (__unused_webpack_module, exports) => {
       "use strict";
       /**
        * A shared function, used on both client and server, to generate a SVG blur placeholder.
@@ -879,7 +879,7 @@
       /***/
     },
 
-    /***/ 4178: /***/ (
+    /***/ 2933: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -906,10 +906,10 @@
         },
       });
       const _interop_require_default = __webpack_require__(9608);
-      const _getimgprops = __webpack_require__(8064);
-      const _imagecomponent = __webpack_require__(9708);
+      const _getimgprops = __webpack_require__(2298);
+      const _imagecomponent = __webpack_require__(709);
       const _imageloader = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(3204)
+        __webpack_require__(9836)
       );
       function getImageProps(imgProps) {
         const { props } = (0, _getimgprops.getImgProps)(imgProps, {
@@ -941,7 +941,7 @@
       /***/
     },
 
-    /***/ 3204: /***/ (__unused_webpack_module, exports) => {
+    /***/ 9836: /***/ (__unused_webpack_module, exports) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -976,7 +976,7 @@
       /***/
     },
 
-    /***/ 3299: /***/ (
+    /***/ 9636: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -993,8 +993,8 @@
 
       // EXTERNAL MODULE: ./node_modules/.pnpm/[email protected]/node_modules/react/jsx-runtime.js
       var jsx_runtime = __webpack_require__(4744);
-      // EXTERNAL MODULE: ./node_modules/.pnpm/next@file+..+main-repo+packages+next+next-packed.tgz_react-dom@19.0.0-rc-45804af1-20241021_re_fqnwmzresl2hrinmjfrqg34ihq/node_modules/next/image.js
-      var next_image = __webpack_require__(7641);
+      // EXTERNAL MODULE: ./node_modules/.pnpm/next@file+..+diff-repo+packages+next+next-packed.tgz_react-dom@19.0.0-rc-45804af1-20241021_re_dcrk7anheu5balwwdvbhf3r7h4/node_modules/next/image.js
+      var next_image = __webpack_require__(3415);
       var image_default = /*#__PURE__*/ __webpack_require__.n(next_image); // CONCATENATED MODULE: ./pages/nextjs.png
       /* harmony default export */ const nextjs = {
         src: "/_next/static/media/nextjs.cae0b805.png",
@@ -1024,12 +1024,12 @@
       /***/
     },
 
-    /***/ 7641: /***/ (
+    /***/ 3415: /***/ (
       module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(4178);
+      module.exports = __webpack_require__(2933);
 
       /***/
     },
@@ -1039,7 +1039,7 @@
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [2888, 9774, 179], () =>
-      __webpack_exec__(32)
+      __webpack_exec__(6529)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for 9756-HASH.js

Diff too large to display

Diff for main-HASH.js

Diff too large to display

Diff for app-page-exp..ntime.dev.js

Diff too large to display

Diff for app-page.runtime.dev.js

Diff too large to display

Commit: e20267b7566a00de85d5f3e94a4f0e304380f83f

ijjk avatar Sep 24 '24 11:09 ijjk