Next.js: Hot Reloading not working in Next.js 9 using custom routing, styled components and withApollo example

Created on 21 Aug 2020  路  14Comments  路  Source: vercel/next.js

Bug report

We are running "dev": "cross-env NODE_ENV=development babel-node src/server.js", to start nextjs in dev mode from our server.js file

We see the compiled successfully message when making changes to the pages/components folder
image

but we do not see any changes or renders on the page until we refresh the page

import express from "express";
import "isomorphic-fetch";
import next from "next";
import projectConfig from "./config";

import { initializeApollo } from "./lib/nextApollo";
import gql from "graphql-tag";

const compression = require("compression");
const apiHost = projectConfig.apiHost;
const currentHost = projectConfig.host;
const env = projectConfig.env;

// export interface Global extends NodeJS.Global {
//   document: Document;
//   window: Window;
//   DEVELOPMENT: any;
//   FOLDER: any;
// }

// declare var global: Global;

global.DEVELOPMENT = projectConfig.env == "DEV" ? true : false;
const dev = global.DEVELOPMENT ? true : false;
const folder = global.DEVELOPMENT ? "src" : "dist";

console.log("IS DEVELOPMENT", dev, "FOLDER", folder);

const app = next({ dev, dir: folder });

const handle = app.getRequestHandler();
const server = express();

server.use(compression());

Describe the bug

Next.js, not rerendering page when changes are made to the app.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Run app
  2. Go to page in a browser
  3. Make a change on page
  4. See compiled successfully but no rerender

Expected behavior

Hot reloading should rerender the page

System information

  • OS: Mac and windows
  • Browser all Browsers
  • Version of Next.js: 9.3 and 9.5
  • Version of Node.js: 12

Code Example

export const resolvers = {
    Mutation: {
        setGlobalVolume: (_, { volume }, { cache }) => {
            // cache.writeData({ data: { globalVolume: volume } });
            return null;
        },
        setGlobalSrc: (_, { id }, { cache }) => {
            // cache.writeData({ data: { globalSrcId: id } });
            return null;
        },
    },
};

const authLink = setContext((_, { headers }) => {
    if (projectConfig.env === "DEV") {
        // get the authentication token from local storage if it exists
        const token = isBrowser
            ? window.localStorage
                ? window.localStorage.getItem("jwt")
                : ""
            : "";

        // return the headers to the context so httpLink can read them
        return {
            headers: {
                ...headers,
                authorization: token ? `Bearer ${token}` : "",
            },
        };
    } else {
        return {
            headers: {
                ...headers,
            },
        };
    }
});

// https://www.apollographql.com/docs/react/caching/cache-configuration/
const apolloCache = new InMemoryCache({
    dataIdFromObject(responseObject) {
        switch (responseObject.__typename) {
            case "Bite":
                return `Bite:${responseObject._id}`;
            case "Playlist":
                return `Playlist:${responseObject._id}`;
            case "Category":
                return `Category:${responseObject._id}`;
            case "User":
                return `User:${responseObject._id}`;
            default:
                return defaultDataIdFromObject(responseObject);
        }
    },
    typePolicies: {
        Bite: {
            fields: {
                audio: {
                    original: {
                        merge(existing, incoming, { mergeObjects }) {
                            return existing._id;
                        },
                    },
                },
            },
        },
        Query: {
            queryType: true,
            fields: {
                web: {
                    merge: true,
                    queryType: true,
                },
                twitch: {
                    merge: true,
                    queryType: true,
                },
            },
        },
    },
});

export function initializeApollo(initialState = {}) {
    const _apolloClient = apolloClient || createApolloClient();

    // If your page has Next.js data fetching methods that use Apollo Client, the initial state
    // gets hydrated here
    if (initialState) {
        // Get existing cache, loaded during client side data fetching
        const existingCache = _apolloClient.extract();
        // Restore the cache using the data passed from getStaticProps/getServerSideProps
        // combined with the existing cached data
        _apolloClient.cache.restore({ ...existingCache, ...initialState });
    }
    // For SSG and SSR always create a new Apollo Client
    if (typeof window === "undefined") return _apolloClient;
    // Create the Apollo Client once in the client
    if (!apolloClient) apolloClient = _apolloClient;

    return _apolloClient;
}

export function useApollo(initialState) {
    const store = useMemo(() => initializeApollo(initialState), [initialState]);
    return store;
}

_app.js

import React from "react";
import { ApolloProvider } from "@apollo/client";
import { useApollo } from "../lib/nextApollo";
import * as ReactGA from "react-ga";

import { Helmet } from "react-helmet";

import { Themes } from "@blerp/design";
import { colors } from "../components/theme/Theme";
import { ThemeProvider } from "styled-components";

// https://github.com/vercel/next.js/tree/canary/examples/with-apollo For apollo + nextjs example
export default function App({ Component, pageProps }) {
    const apolloClient = useApollo(pageProps.initialApolloState);

    return (
        <ApolloProvider client={apolloClient}>
            <ThemeProvider
                theme={{
                    ...Themes.mainTheme,
                    colors: colors,
                    mode: "light",
                }}
            >
                <>
                    <Helmet defaultTitle='Blerp' titleTemplate='%s' />
                    <Component {...pageProps} />
                </>
            </ThemeProvider>
        </ApolloProvider>
    );
}

_documents.js

    static async getInitialProps(ctx) {
        const sheet = new ServerStyleSheet();
        const originalRenderPage = ctx.renderPage;
        try {
            ctx.renderPage = () =>
                originalRenderPage({
                    enhanceApp: App => props =>
                        sheet.collectStyles(<App {...props} />),
                });

            const initialProps = await Document.getInitialProps(ctx);
            return {
                ...initialProps,
                styles: (
                    <>
                        {initialProps.styles}
                        {sheet.getStyleElement()}
                    </>
                ),
            };
        } finally {
            sheet.seal();
        }
    }

good first issue

Most helpful comment

Following. We're having a similar issue.

All 14 comments

A complete reproduction repository is required to investigate.

@timneutkens https://github.com/blerp/website here you go!

Any hints would be much appreciated!! @timneutkens

I marked it as good first issue.

Following. We're having a similar issue.

I'm facing a similar issue, but only in SSG pages.

I confirm this issue. Also I noticed the following messages in browser console:
[Fast Refresh] rebuilding [Fast Refresh] done
And triangular indicator of updating at right bottom corner of screen appears and disappears, but nothing happened - changes do not apply.

I got same error.. I use class components only in _app.tsx and _document.tsx

I have a few select components in my application that will not only not hot reload but won't reload on a full refresh either. I need to run a completely new build to see reflected changes .. any quick thought on why this might be? The only thing that jumps out is that I'm doing a dynamic import in the parent component with ssr: false however commenting this component out does nothing. I'm also getting no 'Fast Refresh' indication in the console.

Okay.. so for me it was a very silly issue - I had a component nested in a folder controls but I was referencing it from another component as from ./Controls. The casing was the issue - however, everything was rendering / displaying as normal (just no fast refresh), and there were no warnings in the console. I received a warning only after I took a child component in controls and rendered it directly from the component further up the tree. I understand these are separate issues, but just in case someone stumbles across this: casing matters for Fast Refresh (but not always for the build), and if it's nested - it may swallow the warning.

I might be experiencing the same issue... but I did not fully understand the explanation. I understood it is an issue with casing, but where? i.e. what casing needs to match which one?

@JoseFMP for me it was the casing of a folder that I was referencing within my app. There was a folder with all lowercase, and I was referencing it in a file as capitalized. The app still built (and deployed) but Fast Refresh wouldn't work (or any refresh). As soon as I fixed the casing, Fast Refresh returned. For this example, the only (perhaps unhelpful) help I can offer is to scrupulously check all your file imports and make sure they match. Understand that my comment does not wholly reflect the open issue, just what I experienced.

i have similar issue, i lost cache data after the [Fast Refresh] done

I have the same issue

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lixiaoyan picture lixiaoyan  路  3Comments

sospedra picture sospedra  路  3Comments

flybayer picture flybayer  路  3Comments

wagerfield picture wagerfield  路  3Comments

jesselee34 picture jesselee34  路  3Comments