diff --git a/boot.js b/boot.js index 81e537cd9..e1217ab2a 100644 --- a/boot.js +++ b/boot.js @@ -7,7 +7,7 @@ import express from 'express' import newrelic from 'artsy-newrelic' import path from 'path' import { IpFilter } from 'express-ipfilter' -import { createReloadable, isDevelopment } from 'lib/reloadable' +import { createReloadable, isDevelopment } from '@artsy/express-reloadable' const debug = require('debug')('app') const app = module.exports = express() @@ -28,7 +28,7 @@ artsyXapp.init(xappConfig, () => { app.use(newrelic) if (isDevelopment) { - const reloadAndMount = createReloadable(app) + const reloadAndMount = createReloadable(app, require) // Enable server-side code hot-swapping on change app.use('/api', reloadAndMount(path.resolve(__dirname, 'api'), { diff --git a/lib/reloadable.js b/lib/reloadable.js deleted file mode 100644 index 95bfb50e6..000000000 --- a/lib/reloadable.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Dev utility for server-side code reloading without the restart. In development, - * watch for file-system changes and clear cached modules when a change occurs, - * thus effectively reloading the entire app on request. - */ - -export const isDevelopment = process.env.NODE_ENV === 'development' - -export function createReloadable (app) { - return (folderPath, options = {}) => { - if (isDevelopment) { - const { - mountPoint = '/' - } = options - - // On browser page reload, re-require app files - const onReload = (req, res, next) => require(folderPath)(req, res, next) - - // Watch a subset of files for changes - const watcher = require('chokidar').watch(folderPath) - - watcher.on('ready', () => { - watcher.on('all', () => { - Object.keys(require.cache).forEach(id => { - if (id.startsWith(folderPath)) { - delete require.cache[id] - } - }) - }) - }) - - let currentResponse = null - let currentNext = null - - app.use((req, res, next) => { - currentResponse = res - currentNext = next - - res.on('finish', () => { - currentResponse = null - currentNext = null - }) - - next() - }) - - /** - * In case of an uncaught exception show it to the user and proceed, rather - * than exiting the process. - */ - process.on('uncaughtException', (error) => { - if (currentResponse) { - currentNext(error) - currentResponse = null - currentNext = null - } else { - process.abort() - } - }) - - app.use(mountPoint, (req, res, next) => { - onReload(req, res, next) - }) - - return onReload - - // Node env not 'development', exit - } else { - throw new Error( - '(lib/reloadable.js) NODE_ENV must be set to "development" to use ' + - 'reloadable.js' - ) - } - } -} diff --git a/package.json b/package.json index 5dc4c93f2..ce1d740f5 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "deploy": "sh scripts/deploy.sh" }, "dependencies": { + "@artsy/express-reloadable": "^1.0.2", "@artsy/reaction-force": "^0.1.49", "airtable": "^0.4.5", "artsy-backbone-mixins": "git://github.com/artsy/artsy-backbone-mixins.git", diff --git a/yarn.lock b/yarn.lock index db45f29e1..95ffc1921 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,12 @@ # yarn lockfile v1 +"@artsy/express-reloadable@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@artsy/express-reloadable/-/express-reloadable-1.0.2.tgz#c63adeb7682334cfa5bf66c92fb9aaea062bda47" + dependencies: + chokidar "^1.7.0" + "@artsy/reaction-force@^0.1.49": version "0.1.49" resolved "https://registry.yarnpkg.com/@artsy/reaction-force/-/reaction-force-0.1.49.tgz#3899011c56a37b9fdeb92e06532ddc40d3fb4a8d"