Simple Vue Dev Server with Hot Module Replacement (HMR)
Building a development server is a fundamental skill for any web developer. This challenge asks you to implement a basic development server for a Vue.js application, including hot module replacement (HMR) to provide a faster development experience. This will solidify your understanding of module bundling, file system watching, and basic server functionality.
Problem Description
You are tasked with creating a simple development server that serves a Vue.js application and supports HMR. The server should:
- Serve Static Files: Serve the files in a specified directory (e.g.,
distorpublic) as static assets. - Watch for Changes: Monitor the specified directory for file changes.
- Bundle and Rebuild: When a file changes, bundle the Vue.js application using a simple bundler (you can use a basic implementation or a lightweight library like
esbuildorrollupfor bundling – the focus is on the server logic, not the bundler itself). - Hot Module Replacement (HMR): Implement HMR so that when a file changes, only the modified modules are updated in the browser, without a full page refresh. This requires establishing a WebSocket connection between the server and the browser.
- Basic Error Handling: Provide basic error handling for file watching and bundling.
Expected Behavior:
- The server should start and listen on a specified port (e.g., 8080).
- When the server starts, it should bundle the Vue.js application.
- When a file in the watched directory changes, the server should:
- Re-bundle the application.
- Send an HMR update to the connected browser via WebSocket.
- The browser should receive the HMR update and update the relevant modules without a full page refresh.
- The server should log any errors encountered during file watching or bundling.
Examples
Example 1:
Input: Directory to serve: 'src', Port: 8080, Vue entry point: 'src/main.ts'
Output: Server started on port 8080. Files in 'src' are being watched. HMR enabled.
Explanation: The server starts, serves files from 'src', watches for changes, and enables HMR. The initial bundle is created.
Example 2:
Input: Directory to serve: 'public', Port: 9000, Vue entry point: 'public/app.ts'
Output: Server started on port 9000. Files in 'public' are being watched. HMR enabled.
Explanation: The server starts, serves files from 'public', watches for changes, and enables HMR. The initial bundle is created.
Example 3: (Edge Case - Invalid Directory)
Input: Directory to serve: 'nonexistent_dir', Port: 8080, Vue entry point: 'src/main.ts'
Output: Error: Directory 'nonexistent_dir' not found. Server exiting.
Explanation: The server detects that the specified directory does not exist and exits gracefully, logging an error.
Constraints
- Bundler: You can use a simple bundler implementation or a lightweight library like
esbuildorrollup. The focus is on the server logic, not the bundler's complexity. Assume the bundler returns a bundle object with acodeproperty (the bundled JavaScript) and amapproperty (source map, optional). - HMR: The HMR implementation should be basic. Sending a simple message to the browser indicating a module has changed is sufficient. The browser-side HMR handling is not required for this challenge.
- TypeScript: The solution must be written in TypeScript.
- Node.js: The server should be implemented using Node.js.
- Port: The server should listen on the specified port. Handle the case where the port is already in use.
- File Types: The server should watch for changes to
.ts,.vue,.js, and.jsonfiles.
Notes
- Consider using Node.js built-in modules like
fs,http, andpath. - You'll need to establish a WebSocket connection for HMR. Libraries like
wscan simplify this. - The bundling process should be asynchronous to avoid blocking the event loop.
- Focus on the core server logic and HMR functionality. Detailed error handling and advanced features are not required.
- Think about how to handle different file types and how to efficiently update modules in the browser during HMR.
- The browser-side HMR implementation is not part of this challenge. You only need to send the HMR update message to the browser.