Repository: mapbox/batfish
Pull request #319 (2019-09-13 17:00:26)

Fix: Wepback is not compiling md and js files on `start` and copying them on `build`
With the recent upgrade to Webpack 4, I’ve observed two issues related to `.md` and `.js` files: 
* On `start` Batfish is not watching `.md` and `.js` files for changes.
* Batfish is copying md and .js files to production. (This is actually present in Batfish@1.98 as evidenced by [markdown files on production site](https://docs.mapbox.com/help/tutorials/android-navigation-sdk.md), /help is still on Batfish@1.9.8)

This PR:
* Prevents `getNonPageFileGlob` from copying `.md` and `.js` files
* Allows `compiler.watch` to watch `.md` and `.js` files
* Updates browser-sync@2.26.3 to 2.26.7 (This version heals a warning on start, ref: https://github.com/BrowserSync/browser-sync/issues/1688)



## What's happening

Below is a site using Batfish@1.11.0 with the `start` command. On `start` when a markdown file is changed the file is copied, but Webpack does not compile. Despite being copied, the file does not reflect the changes made, even on refresh:

![start-md-no-watch-copy-2](https://user-images.githubusercontent.com/2180540/64880236-b4628400-d625-11e9-8e08-2b49754812ce.gif)


Other files, like `.html` and `.json` are being watched and updated properly on change.

## Expected behavior

When a md or js file is changed Webpack should compile, but it should not copy.

## Commit explanation

### Prevent `getNonPageFileGlob` from copying `.md` and `.js` files

I believe this line will prevent a file like `src/pages/index.md` from being copied over, but will copy over `src/pages/overview/index.md`:

https://github.com/mapbox/batfish/blob/fa7882c39ece32e10fadf55d0cd3d9c69967914e/src/node/non-page-files.js#L15

**Solution:** Update the md and js paths to prevent all md and js files from being copied over:

https://github.com/mapbox/batfish/blob/5f05123ae6e75628de6504f57670f609dd02a2dd/src/node/non-page-files.js#L15

### Allow `compiler.watch` to watch `.md` and .`js` files

This line says that `watchContext` is watching the pages directory:

https://github.com/mapbox/batfish/blob/fa7882c39ece32e10fadf55d0cd3d9c69967914e/src/node/watch-webpack.js#L96-L100

However, when I removed those lines to allow the compiler to watch md and js files, Webpack began watching md and js files and compiling them on change. This is the part I'm not sure about. These are my lingering questions:

* Why did Batfish stopped watching md and js files in Webpack@4?
* How is `watchContext` watching the pages directory? (Lines 96-100 must have been implemented for a reason.) I did a lot of console.logging through these functions and haven't been able to see the connections.

**Tentative solution:** Remove lines 96-100 in watch-webpack.js to allow `complier.watch` to watch md and js files.

## How I tested

* [x] Installed Batfish locally on /ios-sdk: 
    * [x] confirmed that Wepback compiles md, js, json, and html files on change
    * [x] confirmed all files are copied over correctly on `build`.
* [x] Tested every Batfish example on the `start` and `build` commands.

---

@davidtheclark or @kepta would either of you mind reviewing? 🙏 



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 59be96f..e893c5f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,8 @@
 ## Head
 
 - **Fix**: Revert increase `maxAsyncRequests` and `maxInitialRequests` in `splitChunks` to prevent JavaScript from running out of memory.
+- **Fix**: Fix issue where `.md` and `.js` files were not being compiled on `start`.
+- **Fix**: Prevent `.md` and `.js` files from being copied on `build` since they will be compiled.
 
 ## 1.11.1
 
diff --git a/package-lock.json b/package-lock.json
index 64bb444..b0733c0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -675,12 +675,27 @@
       "optional": true
     },
     "accepts": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
-      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+      "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
       "requires": {
-        "mime-types": "~2.1.18",
-        "negotiator": "0.6.1"
+        "mime-types": "~2.1.24",
+        "negotiator": "0.6.2"
+      },
+      "dependencies": {
+        "mime-db": {
+          "version": "1.40.0",
+          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+          "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+        },
+        "mime-types": {
+          "version": "2.1.24",
+          "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+          "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+          "requires": {
+            "mime-db": "1.40.0"
+          }
+        }
       }
     },
     "acorn": {
@@ -1252,12 +1267,19 @@
       "dev": true
     },
     "axios": {
-      "version": "0.17.1",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz",
-      "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=",
+      "version": "0.19.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
+      "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==",
       "requires": {
-        "follow-redirects": "^1.2.5",
-        "is-buffer": "^1.1.5"
+        "follow-redirects": "1.5.10",
+        "is-buffer": "^2.0.2"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
+          "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw=="
+        }
       }
     },
     "babel-cli": {
@@ -2975,12 +2997,12 @@
       "dev": true
     },
     "browser-sync": {
-      "version": "2.26.3",
-      "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.3.tgz",
-      "integrity": "sha512-VLzpjCA4uXqfzkwqWtMM6hvPm2PNHp2RcmzBXcbi6C9WpkUhhFb8SVAr4CFrCsFxDg+oY6HalOjn8F+egyvhag==",
+      "version": "2.26.7",
+      "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.7.tgz",
+      "integrity": "sha512-lY3emme0OyvA2ujEMpRmyRy9LY6gHLuTr2/ABxhIm3lADOiRXzP4dgekvnDrQqZ/Ec2Fz19lEjm6kglSG5766w==",
       "requires": {
-        "browser-sync-client": "^2.26.2",
-        "browser-sync-ui": "^2.26.2",
+        "browser-sync-client": "^2.26.6",
+        "browser-sync-ui": "^2.26.4",
         "bs-recipes": "1.3.4",
         "bs-snippet-injector": "^2.0.1",
         "chokidar": "^2.0.4",
@@ -2994,8 +3016,8 @@
         "fs-extra": "3.0.1",
         "http-proxy": "1.15.2",
         "immutable": "^3",
-        "localtunnel": "1.9.1",
-        "micromatch": "2.3.11",
+        "localtunnel": "1.9.2",
+        "micromatch": "^3.1.10",
         "opn": "5.3.0",
         "portscanner": "2.1.1",
         "qs": "6.2.3",
@@ -3011,73 +3033,6 @@
         "yargs": "6.4.0"
       },
       "dependencies": {
-        "arr-diff": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
-          "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
-          "requires": {
-            "arr-flatten": "^1.0.1"
-          }
-        },
-        "array-unique": {
-          "version": "0.2.1",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
-          "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="
-        },
-        "braces": {
-          "version": "1.8.5",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
-          "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
-          "requires": {
-            "expand-range": "^1.8.1",
-            "preserve": "^0.2.0",
-            "repeat-element": "^1.1.2"
-          }
-        },
-        "expand-brackets": {
-          "version": "0.1.5",
-          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
-          "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
-          "requires": {
-            "is-posix-bracket": "^0.1.0"
-          }
-        },
-        "extglob": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
-          "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        },
-        "micromatch": {
-          "version": "2.3.11",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
-          "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
-          "requires": {
-            "arr-diff": "^2.0.0",
-            "array-unique": "^0.2.1",
-            "braces": "^1.8.2",
-            "expand-brackets": "^0.1.4",
-            "extglob": "^0.3.1",
-            "filename-regex": "^2.0.0",
-            "is-extglob": "^1.0.0",
-            "is-glob": "^2.0.1",
-            "kind-of": "^3.0.2",
-            "normalize-path": "^2.0.1",
-            "object.omit": "^2.0.0",
-            "parse-glob": "^3.0.4",
-            "regex-cache": "^0.4.2"
-          }
-        },
         "ua-parser-js": {
           "version": "0.7.17",
           "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz",
@@ -3086,9 +3041,9 @@
       }
     },
     "browser-sync-client": {
-      "version": "2.26.2",
-      "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.2.tgz",
-      "integrity": "sha512-FEuVJD41fI24HJ30XOT2RyF5WcnEtdJhhTqeyDlnMk/8Ox9MZw109rvk9pdfRWye4soZLe+xcAo9tHSMxvgAdw==",
+      "version": "2.26.6",
+      "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.6.tgz",
+      "integrity": "sha512-mGrkZdNzttKdf/16I+y+2dTQxoMCIpKbVIMJ/uP8ZpnKu9f9qa/2CYVtLtbjZG8nsM14EwiCrjuFTGBEnT3Gjw==",
       "requires": {
         "etag": "1.8.1",
         "fresh": "0.5.2",
@@ -3112,9 +3067,9 @@
       }
     },
     "browser-sync-ui": {
-      "version": "2.26.2",
-      "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.2.tgz",
-      "integrity": "sha512-LF7GMWo8ELOE0eAlxuRCfnGQT1ZxKP9flCfGgZdXFc6BwmoqaJHlYe7MmVvykKkXjolRXTz8ztXAKGVqNwJ3EQ==",
+      "version": "2.26.4",
+      "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.4.tgz",
+      "integrity": "sha512-u20P3EsZoM8Pt+puoi3BU3KlbQAH1lAcV+/O4saF26qokrBqIDotmGonfWwoRbUmdxZkM9MBmA0K39ZTG1h4sA==",
       "requires": {
         "async-each-series": "0.1.1",
         "connect-history-api-fallback": "^1",
@@ -3255,9 +3210,9 @@
       "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
     },
     "bytes": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-      "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+      "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
     },
     "cache-base": {
       "version": "1.0.1",
@@ -4639,9 +4594,9 @@
       }
     },
     "engine.io-client": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.1.tgz",
-      "integrity": "sha512-q66JBFuQcy7CSlfAz9L3jH+v7DTT3i6ZEadYcVj2pOs8/0uJHLxKX3WBkGTvULJMdz0tUCyJag0aKT/dpXL9BQ==",
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz",
+      "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==",
       "requires": {
         "component-emitter": "1.2.1",
         "component-inherit": "0.0.3",
@@ -4665,9 +4620,9 @@
           }
         },
         "ws": {
-          "version": "6.1.2",
-          "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.2.tgz",
-          "integrity": "sha512-rfUqzvz0WxmSXtJpPMX2EeASXabOrSMk1ruMOV3JBTBjo4ac2lDjGGsbQSyxj8Odhw5fBib8ZKEjDNvgouNKYw==",
+          "version": "6.1.4",
+          "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
+          "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
           "requires": {
             "async-limiter": "~1.0.0"
           }
@@ -5839,9 +5794,9 @@
       "dev": true
     },
     "follow-redirects": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz",
-      "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==",
+      "version": "1.5.10",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+      "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
       "requires": {
         "debug": "=3.1.0"
       },
@@ -9684,9 +9639,9 @@
       }
     },
     "limiter": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.3.tgz",
-      "integrity": "sha512-zrycnIMsLw/3ZxTbW7HCez56rcFGecWTx5OZNplzcXUUmJLmoYArC6qdJzmAN5BWiNXGcpjhF9RQ1HSv5zebEw=="
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.4.tgz",
+      "integrity": "sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg=="
     },
     "line-column": {
       "version": "1.0.2",
@@ -10037,12 +9992,12 @@
       }
     },
     "localtunnel": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.1.tgz",
-      "integrity": "sha512-HWrhOslklDvxgOGFLxi6fQVnvpl6XdX4sPscfqMZkzi3gtt9V7LKBWYvNUcpHSVvjwCQ6xzXacVvICNbNcyPnQ==",
+      "version": "1.9.2",
+      "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.2.tgz",
+      "integrity": "sha512-NEKF7bDJE9U3xzJu3kbayF0WTvng6Pww7tzqNb/XtEARYwqw7CKEX7BvOMg98FtE9es2CRizl61gkV3hS8dqYg==",
       "requires": {
-        "axios": "0.17.1",
-        "debug": "2.6.9",
+        "axios": "0.19.0",
+        "debug": "4.1.1",
         "openurl": "1.1.1",
         "yargs": "6.6.0"
       },
@@ -10052,6 +10007,19 @@
           "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
           "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
         },
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+        },
         "os-locale": {
           "version": "1.4.0",
           "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
@@ -10084,14 +10052,6 @@
             "y18n": "^3.2.1",
             "yargs-parser": "^4.2.0"
           }
-        },
-        "yargs-parser": {
-          "version": "4.2.1",
-          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
-          "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
-          "requires": {
-            "camelcase": "^3.0.0"
-          }
         }
       }
     },
@@ -11007,9 +10967,9 @@
       }
     },
     "negotiator": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
-      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+      "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
     },
     "neo-async": {
       "version": "2.6.1",
@@ -12840,39 +12800,45 @@
       "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
     },
     "raw-body": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
-      "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz",
+      "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==",
       "requires": {
-        "bytes": "3.0.0",
-        "http-errors": "1.6.3",
-        "iconv-lite": "0.4.23",
+        "bytes": "3.1.0",
+        "http-errors": "1.7.3",
+        "iconv-lite": "0.4.24",
         "unpipe": "1.0.0"
       },
       "dependencies": {
         "http-errors": {
-          "version": "1.6.3",
-          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-          "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+          "version": "1.7.3",
+          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
+          "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
           "requires": {
             "depd": "~1.1.2",
-            "inherits": "2.0.3",
-            "setprototypeof": "1.1.0",
-            "statuses": ">= 1.4.0 < 2"
+            "inherits": "2.0.4",
+            "setprototypeof": "1.1.1",
+            "statuses": ">= 1.5.0 < 2",
+            "toidentifier": "1.0.0"
           }
         },
         "iconv-lite": {
-          "version": "0.4.23",
-          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
-          "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+          "version": "0.4.24",
+          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+          "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
           "requires": {
             "safer-buffer": ">= 2.1.2 < 3"
           }
         },
+        "inherits": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+          "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+        },
         "setprototypeof": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
-          "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+          "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
         },
         "statuses": {
           "version": "1.5.0",
@@ -15699,6 +15665,11 @@
         "x-is-function": "^1.0.4"
       }
     },
+    "toidentifier": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+      "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+    },
     "toposort": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.6.tgz",
@@ -16953,6 +16924,11 @@
         "string-width": "^1.0.1"
       }
     },
+    "window-size": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz",
+      "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU="
+    },
     "wordwrap": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
@@ -17147,19 +17123,21 @@
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
           "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8="
-        },
-        "window-size": {
-          "version": "0.2.0",
-          "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz",
-          "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU="
-        },
-        "yargs-parser": {
-          "version": "4.2.1",
-          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
-          "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
-          "requires": {
-            "camelcase": "^3.0.0"
-          }
+        }
+      }
+    },
+    "yargs-parser": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
+      "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
+      "requires": {
+        "camelcase": "^3.0.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
         }
       }
     },
diff --git a/package.json b/package.json
index eef83fb..e03f24c 100644
--- a/package.json
+++ b/package.json
@@ -108,7 +108,7 @@
     "babel-plugin-transform-react-remove-prop-types": "^0.4.13",
     "babel-preset-env": "^1.7.0",
     "babel-preset-react": "^6.24.1",
-    "browser-sync": "^2.26.3",
+    "browser-sync": "^2.26.7",
     "chalk": "^2.4.2",
     "chokidar": "^2.0.4",
     "concat-with-sourcemaps": "^1.1.0",
diff --git a/src/node/non-page-files.js b/src/node/non-page-files.js
index b933078..cb0b3cd 100644
--- a/src/node/non-page-files.js
+++ b/src/node/non-page-files.js
@@ -12,7 +12,7 @@ function getNonPageFileGlob(
 ): Array<string> {
   // Don't copy pages files, which are already incorporated into
   // the build in other ways.
-  let glob = ['**/*.*', '!*.js', '!*.md'];
+  let glob = ['**/*.*', '!**/*.js', '!**/*.md'];
   // Copy unprocessed page files directly, unless they are ignored.
   if (batfishConfig.unprocessedPageFiles !== undefined) {
     glob = glob.concat(batfishConfig.unprocessedPageFiles);
diff --git a/src/node/watch-webpack.js b/src/node/watch-webpack.js
index b12d370..69e5597 100644
--- a/src/node/watch-webpack.js
+++ b/src/node/watch-webpack.js
@@ -93,11 +93,6 @@ function watchWebpack(
         {
           ignored: [
             /node_modules/,
-            // Ignore page files because they are watched by watchContext.
-            path.join(
-              batfishConfig.pagesDirectory,
-              `./**/*.${constants.PAGE_EXT_GLOB}`
-            ),
             // Ignore temporary files because they are only re-generated by
             // watchContext, and we don't want to double-compile.
             path.join(batfishConfig.temporaryDirectory, './**/*')


Test patch:
diff --git a/test/non-page-files.test.js b/test/non-page-files.test.js
index 174b8e4..2715383 100644
--- a/test/non-page-files.test.js
+++ b/test/non-page-files.test.js
@@ -17,7 +17,7 @@ describe('nonPageFiles.copy', () => {
       .then(() => {
         expect(cpy).toHaveBeenCalledTimes(1);
         expect(cpy).toHaveBeenCalledWith(
-          ['**/*.*', '!*.js', '!*.md'],
+          ['**/*.*', '!**/*.js', '!**/*.md'],
           'mockOutputDirectory',
           {
             cwd: 'mockPagesDirectory',
@@ -37,7 +37,7 @@ describe('nonPageFiles.copy', () => {
       .then(() => {
         expect(cpy).toHaveBeenCalledTimes(1);
         expect(cpy).toHaveBeenCalledWith(
-          ['**/*.*', '!*.js', '!*.md', '**/home.js', '**/horse.md'],
+          ['**/*.*', '!**/*.js', '!**/*.md', '**/home.js', '**/horse.md'],
           'mockOutputDirectory',
           {
             cwd: 'mockPagesDirectory',
@@ -57,7 +57,7 @@ describe('nonPageFiles.copy', () => {
       .then(() => {
         expect(cpy).toHaveBeenCalledTimes(1);
         expect(cpy).toHaveBeenCalledWith(
-          ['**/*.*', '!*.js', '!*.md', '!**/*.txt', '!*.xyz'],
+          ['**/*.*', '!**/*.js', '!**/*.md', '!**/*.txt', '!*.xyz'],
           'mockOutputDirectory',
           {
             cwd: 'mockPagesDirectory',
@@ -80,8 +80,8 @@ describe('nonPageFiles.copy', () => {
         expect(cpy).toHaveBeenCalledWith(
           [
             '**/*.*',
-            '!*.js',
-            '!*.md',
+            '!**/*.js',
+            '!**/*.md',
             '**/home.js',
             '**/horse.md',
             '!**/*.js',
diff --git a/test/watch-webpack.test.js b/test/watch-webpack.test.js
index efd64fd..477b96b 100644
--- a/test/watch-webpack.test.js
+++ b/test/watch-webpack.test.js
@@ -82,11 +82,7 @@ describe('watchWebpack', () => {
     process.nextTick(() => {
       expect(webpack.compiler.watch).toHaveBeenCalledTimes(1);
       expect(webpack.compiler.watch.mock.calls[0][0]).toEqual({
-        ignored: [
-          /node_modules/,
-          '/mock/pages/directory/**/*.{js,md}',
-          '/mock/temporary/directory/**/*'
-        ]
+        ignored: [/node_modules/, '/mock/temporary/directory/**/*']
       });
       expect(webpack.compiler.watch.mock.calls[0][1]).toBeInstanceOf(Function);
       done();