Writing A Browser Reload Node Server 2019
node server --css "<css build command>" --js "<js build command>"
const http = require ( 'http' )
const server = http . createServer ( ( request , response ) => {
// ...
} )
server . listen ( 3000 , ( ) => {
console . log ( 'Running at http://localhost:3000' )
} )
const handler = require ( 'serve-handler' )
const server = http . createServer ( ( request , response ) => {
return handler ( request , response , {
public : 'public' ,
rewrites : [ { source : '**' , destination : '/index.html' } ]
} )
} )
Handling Server Sent Events
const crypto = require ( 'crypto' )
const clientMap = new Map ( )
const sendEvent = ( data , response ) => {
response . write ( 'data:' + data + '\n\n' )
}
const server = http . createServer ( ( request , response ) => {
response . setHeader ( 'Content-Type' , 'text/event-stream' )
const clientID = crypto . randomBytes ( 6 ) . toString ( 'hex' )
const heartbeat = setInterval ( ( ) => sendEvent ( '' , response ) , 90000 )
clientMap . set ( clientID , response )
sendEvent ( 'connect' , response )
request . on ( 'aborted' , ( ) => {
clearInterval ( heartbeat )
clientMap . delete ( clientID )
} )
} )
const argv = process . argv
const commands = { }
for ( let i = 2 ; i < argv . length ; i += 2 ) {
commands [ argv [ i ] ] = argv [ i + 1 ]
}
const child_process = require ( 'child_process' ) // eslint-disable-line
const execute = flag => {
const process = child_process . exec ( commands [ flag ] , { stdio : 'inherit' } )
process . on ( 'close' , ( ) => {
for ( let [ key ] of clientMap ) {
sendEvent ( 'reload' , clientMap . get ( key ) )
}
} )
}
Watching For File Changes
const fs = require ( 'fs' )
const watchHandler = ( e , filename ) => {
if ( filename . endsWith ( '.scss' ) ) {
return execute ( 'css' )
}
if ( filename . endsWith ( '.js' ) ) {
return execute ( 'js' )
}
}
fs . watch ( 'src' , { recursive : true } , watchHandler )
fs . watch ( 'src/shared' , { recursive : true } , watchHandler )
Connecting and Reloading The Browser
< script >
const reloadSource = new EventSource ( '/reload' ) // eslint-disable-line
reloadSource . onmessage = data => {
if ( data === 'connect' ) {
return console . log ( 'Automatic Reload: connected' )
}
if ( data === 'reload' ) {
window . location . reload ( )
}
console . log ( 'Automatic Reload: heartbeat' )
}
</ script >
const child_process = require ( 'child_process' ) // eslint-disable-line
const crypto = require ( 'crypto' )
const fs = require ( 'fs' )
const handler = require ( 'serve-handler' )
const http = require ( 'http' )
const argv = process . argv
const commands = { }
for ( let i = 2 ; i < argv . length ; i += 2 ) {
commands [ argv [ i ] ] = argv [ i + 1 ]
}
const clientMap = new Map ( )
const sendEvent = ( data , response ) => {
response . write ( 'data:' + data + '\n\n' )
}
const server = http . createServer ( ( request , response ) => {
if ( request . url !== '/reload' ) {
return handler ( request , response , {
public : 'public' ,
rewrites : [ { source : '**' , destination : '/index.html' } ]
} )
}
response . setHeader ( 'Content-Type' , 'text/event-stream' )
const clientID = crypto . randomBytes ( 6 ) . toString ( 'hex' )
const heartbeat = setInterval ( ( ) => sendEvent ( '' , response ) , 90000 )
clientMap . set ( clientID , response )
sendEvent ( 'connect' , response )
request . on ( 'aborted' , ( ) => {
clearInterval ( heartbeat )
clientMap . delete ( clientID )
} )
} )
const execute = flag => {
const process = child_process . exec ( commands [ flag ] , { stdio : 'inherit' } )
process . on ( 'close' , ( ) => {
for ( let [ key ] of clientMap ) {
sendEvent ( 'reload' , clientMap . get ( key ) )
}
} )
}
const watchHandler = ( e , filename ) => {
if ( filename . endsWith ( '.scss' ) ) {
return execute ( 'css' )
}
if ( filename . endsWith ( '.js' ) ) {
return execute ( 'js' )
}
}
fs . watch ( 'src' , { recursive : true } , watchHandler )
fs . watch ( 'src/shared' , { recursive : true } , watchHandler )
server . listen ( 3000 , ( ) => {
console . log ( '\nRunning at http://localhost:3000' )
} )