NOTE: workspace.json
is deprecated, you can update to project.json
here.
One cool aspect of Next.js is its fast refresh support. Whenever you change some Next.js component it automatically refreshes the page without hard reloading everything. However, you might notice that whenever we change something within our MDX markdown files, fast refresh is not capturing that, hence we need to manually refresh the browser window.
In this lesson, we learn how to leverage a feature of Nx to create a "custom Next.js development server". We are going to use chokidar to watch our articles folder and then invoke a private API on the Next.js server instance to trigger a reload command.
Prefer to read along as well? Here's the accompanying article.
Instructor: [0:01] In order to improve the developer experience, Next.js comes with live reloading. For instance, if I remove this title and save the component, you can see immediately, the changes are reflected on the right-hand side in the browser.
[0:13] However, if we go to our Dynamic Routing page here, and I add some new content here and I save, there's no effect. No live reloading happens on the browser side. We already need to go there, hit the Refresh of the browser, and then we will see our text being rendered.
[0:30] Now, since we are in an Nx workspace, we launch our application with nx serve site. This does nothing else than invoking the serve target on the project site. As we have seen before, this is configured in the workspace.json. If we go in here, we can see the various projects. There are libraries in here, as well as our site project, which is our Next.js project. This is of type, application.
[0:56] This has different targets. In this case, it has a build, it has an export target, a test target, and so on. In our case, we invoke the serve target. Each of those targets has a so-called executor attached. This is the program that is situated within the @nrwl/next Node package. There's a so-called server entry point, which is a program that gets invoked, and all the options are being passed to that, such that that one can handle the actual serving, in this case, of the Next.js app.
[1:24] If we go to the Nx docs, we can actually find that executor. That executor has an interesting property, which is the so-called custom server path. This allows us to pass in a path to some custom script, where we can define how we want to instantiate our Next.js server. This is exactly what we are going to use, in order to implement hot reloading or live refresh, also for our MDX files.
[1:48] As a first step, I'm going to place my logic here in the Tools folder. The Tools folder is usually used for custom scripts and utilities, which you might need in your workspace, in order to work with other libraries.
[2:00] You could also create a library dedicated for this specific piece. That would be particularly useful if we would need to pre-build it. In this case, we can just define a TypeScript or JavaScript file, and that will be picked up automatically by Nx.
[2:14] Let's create here a folder, let's call it "Next Watch Server." Then, let's create a file in here that is called next-watch-server. Let me just paste in the actual code, and let me walk you through what is happening here.
[2:28] First of all, you can see those libraries. We use Chokidar for detecting whether changes happen on our file system. Let's, first of all, install that. The function exposed by Nx is the following. We get a Next server instance, which Nx boots for us, and passes ahead to that custom server if that is specified.
[2:47] We have some custom options here, some settings, that are being passed in here via the configuration in the workspace.json, as well as a proxy config, if that is required. We copy in, more or less, the exact same functionality that the actual Next Nx server includes, which you can find in that package here, @nrwl/next, and then the server file.
[3:09] The only thing we change here is really re-read our article path. We instantiate Chokidar on top of that article path. What that gives us, it gives us a callback. Whenever something in that path changes, this callback is being invoked.
[3:25] The app here is our custom Next server. Notice, that I put a comment on top of here, that we are using a private API. This hot reloader is not exposes a public API, unfortunately, by Next.js. We're directly calling into that and sending it a Building, and then Reload Page command.
[3:46] Finally, we just instantiate an Express server as Next.js does behind the scenes, or better, the Nx-specific implementation of such a Next.js server. Finally, once we have defined these, let's copy here the relative path. We need to go to the workspace.json and configure our Next.js serve target here, and pass the custom server implementation.
[4:08] Here, in the options, I'm adding the custom server path. Let's add in here the Tools folder. This is relative to wherever the application's running. We need to navigate out to the actual root of our workspace, and then into the Tools folder, Next.js and next-watch-server.ts.
[4:29] If we restart our server and then go to our actual Markdown file...and let's remove here the line which we added. If we save, you can see automatically on the right side, the browser refreshes just as it did before.
global workspace.json is now deprecated: https://nx.dev/deprecated/workspace-json
Hey Juri. It seems the customServerPath is deprecated. Any plans on updating this particular lesson?