| | |

Parcel 04 ๐Ÿ“ฆ Dev Server โ€” Built-in server with Fast Refresh

โฑ๏ธ Estimated read: 11 min | |

Parcel’s development server is started by the default parcel command, which is a shortcut for parcel serve. It listens on http://localhost:1234 by default, and if port 1234 is occupied, it falls back to another port automatically . The server rebuilds the changed files as you edit and pushes the updates to the browser, so the page reflects the change without a manual refresh . The previous chapter covered the project setup and the HTML entry; this chapter covers the server that serves that entry during development.

The hot-reloading behavior is the part that developers notice most. Parcel’s default is a full page reload when a file changes, but it upgrades to Hot Module Replacement (HMR) in specific cases. CSS changes are applied via HMR with no reload. React components are updated via Fast Refresh, which preserves the component state in most cases. Other frameworks with built-in HMR support receive the same treatment . For vanilla JavaScript without a framework, HMR is opt-in through the module.hot API .

Key point: The dev server is for development only. It serves the assets from memory, injects the HMR runtime, and rebuilds on change. The parcel build command is the production path, and it does not include the HMR runtime or the dev server. The watch command is the middle ground: it rebuilds on change and supports HMR, but it does not start the HTTP server, which is the correct choice when the application already has its own server .


Why the dev server requires the HMR understanding

The reload-versus-update problem.

A full page reload discards the application state. If you are testing a form with filled inputs or a modal with an open state, the reload resets everything. HMR replaces only the changed module in the running page, so the state survives the update. Parcel’s default is the reload, because the reload is the safest behavior for arbitrary code. The HMR is the upgrade that Parcel applies when it knows how to apply the update safely .

The Fast Refresh problem.

React Fast Refresh is Parcel’s HMR implementation for React. It works with function components and Hooks, and it preserves the component state across the edits in most cases. The state is lost when the file exports something other than the React components, when the component is an unnamed default export, or when the entry component is in the same file as the createRoot call . The Fast Refresh is the reason the React development with Parcel feels immediate: the edit appears in the browser, and the state is still there.

The server-option problem.

The dev server accepts the options that control the port, the host, the HTTPS, and the HMR port. The --port sets the HTTP and the HMR port (the default is process.env.PORT or 1234). The --host sets the binding address. The --https runs the server over HTTPS. The --hmr-port and the --hmr-host set the HMR server separately when the dev server and the HMR must listen on different addresses . The options are the mechanism that adapts the server to the containerized, the remote, and the multi-project environments.


a. Starting the dev server

The dev server is started by the parcel command with the entry file. The command is a shortcut for parcel serve.

# Start the dev server for the HTML entry
npx parcel src/index.html

# The server listens on http://localhost:1234

The default port is 1234, and the fallback port is chosen when 1234 is busy . The server rebuilds the changed files and pushes the updates to the browser . The --open flag opens the entry in the default browser automatically .

The port and the host can be overridden.

# Start on a custom port
npx parcel src/index.html --port 3000

# Bind to all interfaces for the container access
npx parcel src/index.html --host 0.0.0.0 --port 3000

The --port sets the HTTP and the HMR port. The --host 0.0.0.0 binds to all interfaces, which is necessary when the dev server runs inside a Docker container and the browser runs on the host . The --https flag enables the HTTPS for the dev server and the HMR .


b. The HMR and the Fast Refresh

The HMR is the mechanism that updates the modules in the browser at runtime. Parcel supports the CSS HMR automatically, and it supports the React Fast Refresh for the React components.

// The opt-in HMR for the vanilla JavaScript
if (module.hot) {
  module.hot.accept()
}

The module.hot.accept() tells Parcel that the module can be updated in place. Without it, the default is the full page reload . The module.hot.dispose and the module.hot.accept callbacks allow the custom state preservation and cleanup .

The React Fast Refresh is enabled by the framework support. The best practices for the state preservation are the function components, the named exports, and the entry component in a separate file from the createRoot call .

// The entry component in its own file preserves the state
// src/App.tsx
export function App() {
  return <h1>Hello</h1>
}

// src/index.tsx
import { createRoot } from 'react-dom/client'
import { App } from './App'
createRoot(document.getElementById('root')!).render(<App />)

The App is exported from its own file, and the createRoot is in the entry file. The separation is the Fast Refresh requirement that prevents the remount on every change .


c. The watch command and the HMR-only server

The watch command is similar to serve, but it does not start the HTTP server. It only starts the HMR server and rebuilds on change.

# Watch without the HTTP server
npx parcel watch src/index.js

The watch command is the correct choice for the libraries and the backends that have their own HTTP server. The HMR server is still available for the frontend assets, but the Parcel does not serve the HTML or the static files . The serve command is the one that starts the full HTTP server.


Complete Example Session

# ============================================
# PART 1: THE PROJECT
# ============================================
# The package.json with the source field
cat package.json
# { "source": "src/index.html", "scripts": { "dev": "parcel" } }

# ============================================
# PART 2: START THE DEV SERVER
# ============================================
npm run dev
# The server starts on http://localhost:1234

# ============================================
# PART 3: THE CSS HMR
# ============================================
# Edit src/styles.css
# The browser updates the styles without the reload

# ============================================
# PART 4: THE REACT FAST REFRESH
# ============================================
# Edit a function component
# The component updates and the state is preserved

# ============================================
# PART 5: THE CUSTOM PORT
# ============================================
npx parcel src/index.html --port 3000
# The server starts on http://localhost:3000

# ============================================
# PART 6: THE WATCH MODE
# ============================================
npx parcel watch src/index.js
# The rebuild on change, no HTTP server

# ============================================
# PART 7: THE VERIFICATION
# ============================================
curl http://localhost:1234
# The HTML entry is served

The seven parts demonstrate the dev server lifecycle: the project, the server start, the CSS HMR, the React Fast Refresh, the custom port, the watch mode, and the verification.


Quick Reference

The Dev Server Commands

CommandPurpose
parcel <entry>The dev server (default serve)
parcel serve <entry>The dev server explicitly
parcel watch <entry>The HMR only, no HTTP server

The Server Options

OptionPurposeDefault
--portThe HTTP and HMR portprocess.env.PORT or 1234
--hostThe binding addressAll interfaces
--httpsThe HTTPS for the serverOff
--hmr-portThe separate HMR portThe dev server port
--hmr-hostThe separate HMR hostThe dev server host
--openOpen the browserOff

The HMR Support

Asset TypeHMR Behavior
CSSAutomatic, no reload
React (function components)Fast Refresh, state preserved
VueThe framework HMR
Vanilla JSOpt-in via module.hot

Best Practices

โœ… Do This:

# Use the default port for the local development
npx parcel src/index.html                                     # โœ…

# Use the custom port for the port conflict
npx parcel src/index.html --port 3000                        # โœ…

# Use the watch mode for the libraries
npx parcel watch src/index.js                                # โœ…

# Keep the entry component in its own file for the React Fast Refresh
# src/App.tsx and src/index.tsx separated                       # โœ…

# Use the function components for the Fast Refresh
export function App() { ... }                                 # โœ…

โŒ Don’t Do This:

# Use the dev server in the production
# The build command is the production path                       # โŒ

# Export the mixed values from the React component file
# The Fast Refresh state is reset                              # โŒ

# Use the unnamed default export for the React component
export default () => <div />    # State reset on the edit       # โŒ

# Put the createRoot in the same file as the entry component
# The component remounts on every change                        # โŒ

# Assume the watch command serves the HTTP
npx parcel watch    # No HTTP server                            # โŒ

Common Pitfalls

PitfallWhy It HappensFix
The state is lost on the editThe component is not Fast Refresh compatibleUse the function components and the named exports
The CSS change reloads the pageThe CSS is not imported correctlyImport the CSS from the JS or reference it from the HTML
The dev server is not reachable from the containerThe server binds to localhostUse --host 0.0.0.0
The port conflictAnother process uses 1234Use --port
The watch mode has no HTTPThe watch command is HMR onlyUse serve for the HTTP

Real-World Examples

1. Start the dev server

npx parcel src/index.html

2. The custom port

npx parcel src/index.html --port 3000

3. The container host binding

npx parcel src/index.html --host 0.0.0.0

4. The HTTPS server

npx parcel src/index.html --https

5. The watch mode

npx parcel watch src/index.js

6. The opt-in HMR

if (module.hot) { module.hot.accept() }

7. The React Fast Refresh entry separation

// src/index.tsx
createRoot(document.getElementById('root')!).render(<App />)

8. The React component file

// src/App.tsx
export function App() { return <h1>Hello</h1> }

9. The open flag

npx parcel src/index.html --open

10. The package script

{ "scripts": { "dev": "parcel", "start": "parcel" } }

Visual

The Dev Server Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE DEV SERVER REBUILDS AND PUSHES THE UPDATES              โ”‚
โ”‚                                                              โ”‚
โ”‚  File changes on disk                                        โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Parcel rebuilds the changed files                           โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  The update is sent to the browser                           โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ”œโ”€โ”€ the CSS โ†’ the HMR, no reload                       โ”‚
โ”‚       โ”œโ”€โ”€ the React โ†’ the Fast Refresh, the state preserved  โ”‚
โ”‚       โ””โ”€โ”€ the vanilla JS โ†’ the full reload (by default)      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Serve vs Watch

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  SERVE HAS THE HTTP SERVER; WATCH HAS ONLY THE HMR           โ”‚
โ”‚                                                              โ”‚
โ”‚  serve:                                                      โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ The HTTP server (the default port 1234)                โ”‚  โ”‚
โ”‚  โ”‚ The HMR server                                         โ”‚  โ”‚
โ”‚  โ”‚ The rebuild on change                                  โ”‚  โ”‚
โ”‚  โ”‚ For the web apps                                       โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                                              โ”‚
โ”‚  watch:                                                      โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ The HMR server only                                    โ”‚  โ”‚
โ”‚  โ”‚ The rebuild on change                                  โ”‚  โ”‚
โ”‚  โ”‚ No HTTP server                                         โ”‚  โ”‚
โ”‚  โ”‚ For the libraries and the backends                     โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The React Fast Refresh Tips

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE FAST REFRESH WORKS WITH THE FUNCTION COMPONENTS         โ”‚
โ”‚                                                              โ”‚
โ”‚  โœ… Do:                                                      โ”‚
โ”‚  โ”œโ”€โ”€ the function components                                 โ”‚
โ”‚  โ”œโ”€โ”€ the named exports                                       โ”‚
โ”‚  โ””โ”€โ”€ the entry component in its own file                     โ”‚
โ”‚                                                              โ”‚
โ”‚  โŒ Avoid:                                                   โ”‚
โ”‚  โ”œโ”€โ”€ the class components                                    โ”‚
โ”‚  โ”œโ”€โ”€ the mixed exports                                       โ”‚
โ”‚  โ””โ”€โ”€ the unnamed default exports                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Default commandparcel = parcel serve
Default port1234 (or process.env.PORT)
Fallback portAutomatic when 1234 is busy
HMR supportCSS automatic, React Fast Refresh, vanilla opt-in
Watch commandHMR only, no HTTP server
Host binding--host (default all interfaces)
HTTPS--https
Fast Refresh requirementFunction components, named exports, separate entry

Key takeaways:

  • The dev server starts with the parcel command and listens on port 1234. The fallback port is chosen when 1234 is occupied. The --port and the --host override the defaults .
  • The CSS changes are applied via the HMR without the reload. The React components are updated via the Fast Refresh, and the state is preserved in most cases. The vanilla JavaScript requires the explicit module.hot opt-in .
  • The Fast Refresh works with the function components and the named exports. The class components, the mixed exports, and the unnamed default exports cause the state reset. The entry component must be in a separate file from the createRoot call .
  • The watch command is the HMR-only mode. It rebuilds on change and supports the HMR, but it does not start the HTTP server. It is the correct choice for the libraries and the backends with their own server .
  • The --host 0.0.0.0 is necessary for the container access. The default binding is all interfaces, but the explicit flag confirms the intent when the dev server runs inside the Docker .
  • The dev server is not the production artifact. The parcel build command is the production path. The dev server serves the assets from memory and injects the HMR runtime, which is not part of the production bundle.

Remember: The Parcel dev server is the built-in server that rebuilds the changed files and pushes the updates to the browser. The CSS updates via the HMR, the React updates via the Fast Refresh, and the vanilla JavaScript updates via the full reload unless the HMR is opted in. The watch command is the HMR-only mode for the libraries and the backends. The serve command is the full HTTP server for the web apps. The result is the development experience where the edits appear in the browser without the manual refresh, which is the default that Parcel provides from the first command.


Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!