[email protected]
[email protected]
I started seeing a pretty magic bug in production recently and am writing to share the results of my investigation. Here's what was showing up in the browser's console during some of the page loads:
TypeError: Cannot read property 'default' of undefined
at http://localhost:3000/_next/static/bc4f7954-f656-4e9e-af24-a4404cecb3c7/pages/_app.js:1:4762
at r (http://localhost:3000/_next/static/runtime/main-68ba217b0c0184534eba.js:9:96586)
at e.value (http://localhost:3000/_next/static/runtime/main-68ba217b0c0184534eba.js:9:96973)
at http://localhost:3000/_next/static/runtime/main-68ba217b0c0184534eba.js:1:1034
at Array.forEach (<anonymous>)
at Object.110 (http://localhost:3000/_next/static/runtime/main-68ba217b0c0184534eba.js:1:991)
at l (http://localhost:3000/_next/static/runtime/webpack-7dba61e9b6510e660c00.js:1:520)
at Object.105 (http://localhost:3000/_next/static/runtime/main-68ba217b0c0184534eba.js:1:156)
at l (http://localhost:3000/_next/static/runtime/webpack-7dba61e9b6510e660c00.js:1:520)
at Object.104 (http://localhost:3000/_next/static/runtime/main-68ba217b0c0184534eba.js:1:103)
This was followed by no JavaScript working on the client. However, if the exception was somehow avoided on the first page load, all subsequent Next.js pages were working well as long as they were loaded dynamically via <Link/>. The same exception never showed up in development.
After removing pretty much any bit from my app (馃槄) and testing various hypotheses, I was able to craft an MWE where the exception was reproduced pretty stably. All you need to do is to install next-css, create pages/_app.js and import a CSS file there:
import App, { Container } from "next/app";
import React from "react";
import "../styles/index.css"; // 馃槺
export default class MyApp extends App {
render() {
const { Component, pageProps } = this.props;
return (
<Container>
<Component {...pageProps} />
</Container>
);
}
}
Interestingly, the exception was only occurring in Chrome and not Firefox and could disappear when I varied the size and the complexity of a page. However, with pages/index.jsx being just export default () => <div>hello</div>; the exception appeared every time.
Here's how adding import "../styles/index.css"; to _app.jsx affects the HTML in production:
<!DOCTYPE html>
<html>
<head>
<meta charSet="utf-8" class="next-head" />
<link rel="preload" href="/_next/static/HASH/pages/index.js" as="script" />
<link rel="preload" href="/_next/static/HASH/pages/_app.js" as="script" />
<link rel="preload" href="/_next/static/HASH/pages/_error.js" as="script" />
<link rel="preload" href="/_next/static/runtime/webpack-HASH.js" as="script" />
<link rel="preload" href="/_next/static/chunks/HASH.js" as="script" />
<link rel="preload" href="/_next/static/runtime/main-HASH.js" as="script" />
+ <link rel="preload" href="/_next/static/chunks/HASH.js" as="script" />
+ <link rel="stylesheet" href="/_next/static/css/styles.HASH.chunk.css" />
</head>
<body>
<div id="__next">
<div>hello</div>
</div>
<div id="__next-error"></div>
<script>
__NEXT_DATA__ = { "props": { "pageProps": {} }, "page": "/", "pathname": "/", "query": {}, "buildId": "HASH" }
module = {}
__NEXT_LOADED_PAGES__ = []
__NEXT_REGISTER_PAGE = function (route, fn) {
__NEXT_LOADED_PAGES__.push({ route: route, fn: fn })
}
</script>
<script async="" id="__NEXT_PAGE__/" src="/_next/static/HASH/pages/index.js"></script>
<script async="" id="__NEXT_PAGE__/_app" src="/_next/static/HASH/pages/_app.js"></script>
<script async="" id="__NEXT_PAGE__/_error" src="/_next/static/HASH/pages/_error.js"></script>
<script src="/_next/static/runtime/webpack-HASH.js" async=""></script>
<script src="/_next/static/chunks/HASH.js" async=""></script>
<script src="/_next/static/runtime/main-HASH.js" async=""></script>
+ <script src="/_next/static/chunks/HASH.js" async=""></script>
</body>
</html>
As you can see, importing a stylesheet in _app.js not just adds a link to a CSS file, but also produces a new JS chunk. This JS file does not contain anything really:
(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{220:function(n,w,o){}}]);
/_next/static/HASH/pages/_app.js changes a bit too and my suspicion is that it is trying to import a module from the extra JS chunk before that one is loaded. This race condition does not happen on any page because the size of its server-rendered content may affect the order in which Chrome loads the JS files and bootstraps the client-side app.
Getting rid of the bug was pretty simple. I just moved the CSS import into the page HOC in my real app (pages/index.js in the MWE) and the exception never showed up again.
What can we do to save others from the same trap? It took me more than half a day to detect the bug and to investigate it 馃槄
Hi
Facing the same issue here.
index.js:2178 Error was not caught TypeError: Cannot read property 'default' of undefined
at external "dll_919418fa44275dfcfdb1":1
at register (page-loader.js:124)
at PageLoader.registerPage (page-loader.js:162)
at index.js:82
at Array.forEach (<anonymous>)
at Object../node_modules/next/dist/client/index.js (index.js:79)
at __webpack_require__ (bootstrap:789)
at fn (bootstrap:150)
at Object../node_modules/next/dist/client/next-dev.js (next-dev.js:7)
at __webpack_require__ (bootstrap:789)
Using:
"next": "^7.0.0-canary.7",
"@zeit/next-css": "^0.2.1-canary.2",
"@zeit/next-sass": "^0.2.1-canary.2",
"next-optimized-images": "^1.4.1",
OS: Ubuntu 18.04
Crashed in Chrome (Version 68.0.3440.84)
Works in Firefox (61.0.1)
next.config.js
const withOptimizedImages = require('next-optimized-images');
const withCSS = require('@zeit/next-css');
const withSass = require('@zeit/next-sass');
module.exports = withSass(
withCSS(
withOptimizedImages({
webpack: (config) => {
// Fixes npm packages that depend on `fs` module
// eslint-disable-next-line no-param-reassign
config.node = {
fs: 'empty',
};
return config;
},
}),
),
);
_app.js
import React from 'react';
import App, { Container } from 'next/app';
import 'react-dates/initialize';
import 'react-dates/lib/css/_datepicker.css'; //Crashed here
import '../assets/ff-bootstrap.scss'; //Crashed here (if above line commented)
import Head from '../components/Head';
import initFontAwesome from '../fe-utils/init-font-awesome';
initFontAwesome();
export default class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps };
}
render() {
const { Component, pageProps } = this.props;
return (
<Container>
<Head />
<Component {...pageProps} />
</Container>
);
}
}
+1
Happening in Mac chrome too.
I can confirm that as well, firefox works, chrome fail. Console is clean so its only browser issue!
Confirming as well but for sass.
Going to debug this in the morning.
This issue will be fixed when #5115 lands. Thanks for the clear minimal reproduction @kachkaev, it's now part of the Next.js test suite 馃憤:pray:
Most helpful comment
Going to debug this in the morning.