Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onBeforeSetupMiddleware server isn't accessible #3121

Closed
1 of 2 tasks
jimblue opened this issue Mar 27, 2021 · 24 comments · Fixed by #3136
Closed
1 of 2 tasks

onBeforeSetupMiddleware server isn't accessible #3121

jimblue opened this issue Mar 27, 2021 · 24 comments · Fixed by #3136

Comments

@jimblue
Copy link

jimblue commented Mar 27, 2021

  • Operating System: MacOS v11.2.3

  • Node Version: v15.12.0

  • NPM Version: v7.7.5

  • webpack Version: v5.28.0

  • webpack-dev-server Version: v4.0.0-beta.1

  • Browser: Chrome ARM v89.0.4389.90

  • This is a bug

  • This is a modification request

Code

When I was using webpack-dev-server v3, I was configuring the before option like below.

// webpack.config.js

 before(app, server) {
    const files = [
      path.resolve(rootFolder, 'resources/views/**/*.html.twig'),
      path.resolve(rootFolder, 'content/collections/**/*.md')
    ]

    // Reload the browser on content/template files change
    chokidar.watch(files).on('all', () => {
      server.sockWrite(server.sockets, 'content-changed')
    })
  },

Since I've upgrade to webpack-dev-server v4.0.0-beta.1 this is not working even if I've follow the release notes.
I'm getting an error : TypeError: Cannot read property 'sockWrite' of undefined
I've looked at the source code to understand how the new onBeforeSetupMiddleware but sadly, nothing I've tried worked...

Any help would really appreciated, thank you 😅 !

// webpack.config.js

 onBeforeSetupMiddleware({ server, sockets }) {
    const files = [
      path.resolve(rootFolder, 'resources/views/**/*.html.twig'),
      path.resolve(rootFolder, 'content/collections/**/*.md')
    ]

    // Reload the browser on content/template files change
    chokidar.watch(files).on('all', () => {
      server.sockWrite(sockets, 'content-changed')
    })
  },
@alexander-akait
Copy link
Member

hm, it is private API, why you need this?

@jimblue
Copy link
Author

jimblue commented Mar 29, 2021

hi @alexander-akait,
It helps speed up dev workflow a lot by preventing to manually reload the browser on a any changes.
With this setup it automatically reload the browser when I change a Twig template file or a mardown content file.

@jimblue
Copy link
Author

jimblue commented Mar 29, 2021

If you want to keep this API private, we could maybe add an option to handle this case internally ?

@alexander-akait
Copy link
Member

hm, we can implement option watchFiles: string | { paths, options }, so you can watch files without dirty hacks

@jimblue
Copy link
Author

jimblue commented Mar 29, 2021

That would be awesome and cleaner for sure 😄

@anshumanv
Copy link
Member

watchFiles(watchPath, watchOptions) {
should work for this case, right? we can just read the watch files from the option and pass it to this watcher or is this specific for static option?

@alexander-akait
Copy link
Member

Yep, easy to implement, just pass this options to watchFiles, i.e. const watchers = watchFiles.map((item) => watchFiles(item.path, item.options)), move this code to setupWatchFiles method, don't forget to close them in close method and add CLI option for this

@anshumanv
Copy link
Member

got it, thanks

@jimblue
Copy link
Author

jimblue commented Apr 3, 2021

got it, thanks

Can I help you ?

@anshumanv
Copy link
Member

Thanks but PR is ready 😄

@jimblue
Copy link
Author

jimblue commented Apr 3, 2021

Can't believe how fast this feature as been implemented, thank you guys ❤️

@alexander-akait
Copy link
Member

Anyway you can fix your code (should work):

onBeforeSetupMiddleware(devServer) {
    const files = [
      path.resolve(rootFolder, 'resources/views/**/*.html.twig'),
      path.resolve(rootFolder, 'content/collections/**/*.md')
    ]

    // Reload the browser on content/template files change
    chokidar.watch(files).on('all', () => {
      devServer.sockWrite(sockets, 'content-changed')
    })
  },

@jimblue
Copy link
Author

jimblue commented Apr 3, 2021

Hey @alexander-akait in the above code socket is not defined.
But even by fixing it by using devServer.sockets instead, it doesn't work because it returns an empty array.

onBeforeSetupMiddleware(devServer) {
    // Reload the browser on content/template files change
    chokidar.watch([WEBPACKER_SETTINGS.files.template, WEBPACKER_SETTINGS.files.content], { ignoreInitial: true }).on('all', () => {
      devServer.sockWrite(devServer.sockets, 'content-changed')
    })
  },

Anyway, I can totally wait for a new release with the merge PR to use this feature now 😄 !

@alexander-akait
Copy link
Member

devServer.sockets is empty only on initial stage, after it should contain array of socket contentions... I think I will do release tomorrow/after tomorrow

@flyyang
Copy link

flyyang commented Apr 7, 2021

The new release seems not work for me. I tried the sockWrite option,but the this.socketServer seems to be undefined.

  sockWrite(sockets, type, data) {
    sockets.forEach((socket) => {
      this.socketServer.send(socket, JSON.stringify({ type, data }));
    });
  }

@alexander-akait
Copy link
Member

@flyyang because you need wait when socket server starts

@jimblue
Copy link
Author

jimblue commented Apr 7, 2021

Perfectly working ! Thank you so much @alexander-akait / @anshumanv ❤️

@llwor94
Copy link

llwor94 commented Sep 23, 2021

FYI if anyone is here with this question on version 4.2.1, devServer.sockWrite has been renamed to devServer.sendMessage and you'll want to use devServer.webSocketServer.clients instead of devServer.sockets !!

devServer.sendMessage(devServer.webSocketServer.clients, 'content-changed');

@alexander-akait
Copy link
Member

Why you use internal API?

@llwor94
Copy link

llwor94 commented Sep 23, 2021

Live reload federated micro-app in host application:

devServer.app.get('/mfe-change', (req, res) => {
    devServer.sendMessage(devServer.webSocketServer.clients, 'content-changed');
    res.sendStatus(200);
  });

@alexander-akait
Copy link
Member

we have built-in /webpack-dev-server/invalidate route for this case

@llwor94
Copy link

llwor94 commented Sep 23, 2021

I'll check it out, thanks!

@sbussard
Copy link

Why you use internal API?

To get it to work with ibazel

@nitin-io
Copy link

nitin-io commented Oct 23, 2023

FYI if anyone is here with this question on version 4.2.1, devServer.sockWrite has been renamed to devServer.sendMessage and you'll want to use devServer.webSocketServer.clients instead of devServer.sockets !!

devServer.sendMessage(devServer.webSocketServer.clients, 'content-changed');

When I am using this code and changing anything in HTML it refreshes the page instead of HMR?

onBeforeSetupMiddleware(devServer) {
      chokidar
        .watch(resolve(__dirname, 'src', 'index.html'))
        .on('all', () =>
          devServer.sendMessage(
            devServer.webSocketServer.clients,
            'content-changed'
          )
        );
    },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants