vercel / next.js

The React Framework
https://nextjs.org
MIT License
125.83k stars 26.85k forks source link

HMR not working #5429

Closed prathameshnetake closed 5 years ago

prathameshnetake commented 6 years ago

Bug report

Hot module reload as well as refresh server on changes stops working if project directory name contain dots e.g. username.github.io

System information

Replicated on Windows and linux Ubuntu

timneutkens commented 6 years ago

What version of Next.js are you on?

prathameshnetake commented 6 years ago

My package.json looks like this

{ "dependencies": { "@material-ui/core": "^3.1.1", "@material-ui/icons": "^3.0.1", "next": "latest", "react": "latest", "react-dom": "latest", "react-jss": "latest" }, "scripts": { "dev": "next", "build": "next build && next export && rm -rf _next && cp -r out/* . && rm -rf out", "start": "next start", "help": "next export -h" }, "devDependencies": { "babel-eslint": "^8.2.1", "eslint": "^4.17.0", "eslint-loader": "^1.9.0", "eslint-plugin-react": "^7.6.1" }, "name": "prathameshnetake.github.io", "version": "1.0.0", "main": "index.js", "repository": "https://prathameshnetake@github.com/prathameshnetake/prathameshnetake.github.io", "author": "Prathamesh prathamesh.netake@gmail.com", "license": "MIT" }

vinpac commented 6 years ago

I've tested on next 7.0.2 and it seems HMR doesn't work when warnings are thrown

image

When I removed the code that was causing the warnings, the HMR started working again.

I consider this an error for 2 reasons:

  1. These warning don't are wrong. Because the 2 interfaces are being exported. (Maybe a mistake from my part configuring babel? I don't know yet. But it worked fine in next 6 )
  2. If it's blocking the update it should be an error not a warning.
OutThisLife commented 6 years ago

I get this too, anything scoped beneath _app.tsx fails to reload any changes.

jagaapple commented 6 years ago

What @vinpac saying is true. When some warnings are thrown, HMR is blocked. In particular, TypeScript developers not using isolatedModules flag cannot avoid these warnings, I think we should not make them to errors and add an option to disable these warnings.

https://github.com/zeit/next.js/blob/b1c4f3aec4ca2d51b0ed849914cc8fc97805740a/packages/next/client/dev-error-overlay/format-webpack-messages.js#L115

prathameshnetake commented 6 years ago

@jagaapple True. Warnings also come if you use material UI with next.js. You can also suppress them. My concern is if you initiate whole whole project into directory and that directory name contains multiple dots e.g. abc.abc.abc then HMR breaks.

timneutkens commented 6 years ago

We only ignore these paths for HMR: https://github.com/zeit/next.js/blob/canary/packages/next/server/hot-reloader.js#L313-L317

ritz078 commented 6 years ago

Same was the error for me. Nothing happened even if changed something. I remove . from my directory name and everything started working perfectly.

to-var commented 5 years ago

I also noticed HMR not working since version 7.0.0

OS, Node, and NPM info:

- Using: MacOS Mojave
- Node version: v10.12.0
- NPM version: 6.4.1

Package.json:

  "dependencies": {
    "next": "^7.0.2",
    "react": "^16.5.2",
    "react-dom": "^16.5.2",
  },
  "devDependencies": {}

There are no warnings on neither terminal or devtools.

I've tried using those same dependencies with Next version 6.1.2 and worked fine.

guivr commented 5 years ago

+1. Warnings

elmasse commented 5 years ago

Hello guys,

I found myself trap by this bug too. I tested a lot of project names:

None of them works, you can see a pattern there. I finally found a workaround by overriding the watchOptions in the next.config.js:

module.exports = {
  webpackDevMiddleware(config) {
    config.watchOptions = {
      ignored: [
        /\.git\//,
        /\.next\//,
        /node_modules/
      ]
    }
    return config;
  }
}

This seems to be working with all the cases I mentioned. So probably the offending line is the one that @timneutkens pointed out in a previous comment https://github.com/zeit/next.js/blob/canary/packages/next/server/hot-reloader.js#L313-L317

My 2 cents!

BTW, Thanks everyone for such an awesome work on next!

timneutkens commented 5 years ago

@elmasse could you send a PR to fix it? Am I missing something or are you adding the exact same ignore patterns 🤔

elmasse commented 5 years ago

Hi @timneutkens I can send a PR in a few. I added a backslash on the /\.git\// ignore pattern. This will only ignore .git/ folder. Not sure if you have any other .git* pattern in mind to ignore (cannot think of any other than .gitignore at the moment but that's not something that might affect HMR IMO).

Please let me know, I'd be more than glad to send a PR.

Thanks! Max

timneutkens commented 5 years ago

Oh, I see, yeah let's just ignore .git, great catch!

Let's also make sure this works correctly on windows by doing /\.git[\\/] same should probably be done for the other patterns like /node_modules/ => [\\/]node_modules[\\/]

elmasse commented 5 years ago

Cool, I'm gonna add this:

    // We don’t watch .git/ .next/ and node_modules for changes
    const ignored = [
      /\.git[\\/]/,
      /\.next[\\/]/,
      /node_modules/
    ]

The /node_modules/ doesn't. need the match for slash/backslash since it only matches the folder name.

mlnor27 commented 5 years ago

Hi everyone;

HMR is not working with the next.config.js file below

require('dotenv').config()
const path = require('path')
const withPlugins = require('next-compose-plugins')
const withCSS = require('@zeit/next-css')
const withImages = require('next-images')
const cssLoaderConfig = require('@zeit/next-css/css-loader-config')
const webpack = require('webpack')

const scssRegExp = /\.(scss|sass)$/
const scssModuleRegExp = /\.module\.(scss|sass)$/

const { PUBLIC_URL } = process.env

module.exports = withPlugins([
  [
    withCSS,
    {
      distDir: 'build',
      assetPrefix: PUBLIC_URL,
      webpack: (config, { dev, isServer }) => {
        // Handling the additional aliases for scss
        config.resolve.alias.styles = path.resolve(__dirname, './src/styles')
        config.resolve.alias.assets = path.resolve(__dirname, './src/assets')

        // SCSS files configuration
        const scssOptions = cssLoaderConfig(config, {
          cssModules: false,
          cssLoaderOptions: {
            importLoaders: 2,
          },
          postcssLoaderOptions: {},
          dev,
          isServer,
          loaders: [{ loader: 'sass-loader' }],
        })

        // SCSS Module files configuration
        const scssModuleOptions = cssLoaderConfig(config, {
          cssModules: true,
          cssLoaderOptions: {
            importLoaders: 2,
            localIdentName: '[local]___[hash:base64:5]',
          },
          postcssLoaderOptions: {},
          dev,
          isServer,
          loaders: [{ loader: 'sass-loader' }],
        })

        config.module.rules.push(
          {
            test: scssRegExp,
            exclude: scssModuleRegExp,
            use: scssOptions,
          },
          {
            test: scssModuleRegExp,
            use: scssModuleOptions,
          },
        )

        // fonts loader
        config.module.rules.push({
          test: /\.(woff|woff2|eot|ttf|otf)$/,
          use: [
            {
              loader: 'url-loader',
              options: {
                limit: 8192,
                fallback: 'file-loader',
                publicPath: `${PUBLIC_URL}/_next/static/fonts/`,
                outputPath: 'static/fonts/',
                name: '[name]-[hash].[ext]',
              },
            },
          ],
        })

        // Linting in dev mode
        if (dev) {
          config.module.rules.push({
            test: /\.js$/,
            enforce: 'pre',
            exclude: /node_modules/,
            loader: 'eslint-loader',
            options: {
              // Emit errors as warnings for dev to not break webpack build.
              // Eslint errors are shown in console for dev, yay :-)
              emitWarning: true,
            },
          })
        }

        // Defines environement variables from the .env file
        const env = Object.keys(process.env).reduce((acc, curr) => {
          acc[`process.env.${curr}`] = JSON.stringify(process.env[curr])
          return acc
        }, {})
        config.plugins.push(new webpack.DefinePlugin(env))

        // Sets assets public path with the PUBLIC_URL prefix
        config.output.publicPath = `${PUBLIC_URL}${config.output.publicPath}`

        return config
      },
      webpackDevMiddleware(config) {
        config.watchOptions = {
          ignored: [
            /[\\/]\.git[\\/]/,
            /[\\/]\.next[\\/]/,
            /[\\/]node_modules[\\/]/
          ]
        }
        return config;
      }
    },
  ],
  [withImages],
])

I'm using next@7.0.2 It only works when i disable warnings emitted by eslint which is not what i want to do.

The new regexp for the webpackDevMiddleware didn't do the trick for me.

Any suggestions or workarounds would be greatly appreciated

jedwards1211 commented 5 years ago

@timneutkens I upgraded from next@8.0.0 to next@8.0.0-canary.21 and now HMR isn't working for me. Is anyone else seeing this problem with canary? Actually it's not working on 8.0.0 anymore for me either, so some other as-yet undetermined change broke HMR :cry:

Yzrsah commented 5 years ago

One common reason HMR of next.config.js stops working:

All of the examples which use server.js are broken.

cjayyy commented 5 years ago

@Yzrsah Have you figured out any workaround?

genox commented 5 years ago

I'm using nextjs 8@latest with express and server.js and get Uncaught ReferenceError: webpackHotUpdate is not defined at main.js on each page load in local dev mode.

When I change code, I notice the message [HMR] bundle rebuilding in the console but the app never applies the changes until I make a full page reload.

@timneutkens I'm not sure if this is connected to the original issue. Happy to provide more information to you if required.

timneutkens commented 5 years ago

@genox I doubt it's related, can you create a new issue with a clear reproduction? Then I can have a look!

dimensi commented 5 years ago

lol, really, i rename my project from sitename.domain.next to sitename-domain-next and my hmr start work again. So stupid.

timneutkens commented 5 years ago

lol, really So stupid.

This is not the best way of communicating. Especially when you're asking for the issue you're experiencing to be fixed.

I've already offered to have a look in a new issue with a clear reproduction.

As per above:

Can you create a new issue with a clear reproduction? Then I can have a look!

genox commented 5 years ago

@timneutkens I tried to provoke the behaviour by upgrading one of the nextjs examples to 8 that comes as close as possible to what I'm currently using (express+typescript+mobx+custom _app, _document, next.config.js ...). Wasn't able to reproduce the issue with custom-server-typescript upgraded to 8 with some of my config applied. All works fine when I downgrade my project to next@7 though. I'll just run on 7 for now and give 8 a try from time to time. Maybe it just Goes Away(tm) with a release down the line.. could be some web pack thing .. not critical for me to be on 8. I'll open a ticket with a repo if I run out of luck. ;) thanks.

mattdell commented 5 years ago

For anyone else struggling with this, HMR was disabled for me because I disabled chunking in my next.config.js

I've changed this

webpack(config) {
    config.optimization.splitChunks = {
        cacheGroups: {
            default: false
        }
    };

    config.optimization.runtimeChunk = false;

    return config;
}

to

if (!dev) {
    config.optimization.splitChunks = {
        cacheGroups: {
            default: false
        }
    };

    config.optimization.runtimeChunk = false;
}

To not happen when running in develop mode.

timneutkens commented 5 years ago

You don't want to add config.optimization.runtimeChunk = false; it's breaking a lot of things actually.

mattdell commented 5 years ago

Thanks for that. I'm playing around at the moment, but for my current use case I really can't use chunking!

I'm still in PoC mode, so I'll investigate the runtimeChunk setting. Do you have any further reading on that?

timneutkens commented 5 years ago

My main question would be why? Next.js ensures everything works correctly, once you start tweaking these options / disabling them you're at risk of breaking everything in any future upgrade as we have nothing ensuring it will keep working with those changed settings.

tlecreate commented 5 years ago

One thing, I found the problem also, with next@8.0.X with custom server, hot-reload not work

express.get('/:country_code?', (req, res) => {
  app.render(req, res, '/index', req.query, parse(req.url, true))
})

express.get('*', (req, res) => {
  return handle(req, res, parse(req.url, true))
})

But if I don't specific path for app.render, just use handle

// express.get('/:country_code?', (req, res) => {
//   app.render(req, res, '/index', req.query, parse(req.url, true))
// })

express.get('*', (req, res) => {
  return handle(req, res, parse(req.url, true))
})

it work sure.

Another thing if files structure of the project like this

- /pages
- /pages/index/index.tsx
- /pages/index/connector.tsx

When open the browser with url https://mydomain (index page)

Will prerender SSR but after serve to the browser reactDOM will not render again, so any event trigger will not work such as [onClick, ...]

I am not sure this is a bug or rules of Nextjs for the way to design structure of files inside folders /pages.

But in 8.0.4-canary-xx Can work with same above case.