diff --git a/packages/react-dev-utils/__tests__/.eslintrc b/packages/react-dev-utils/__tests__/.eslintrc
new file mode 100644
index 00000000000..55f121d152d
--- /dev/null
+++ b/packages/react-dev-utils/__tests__/.eslintrc
@@ -0,0 +1,5 @@
+{
+  "env": {
+    "jest": true
+  }
+}
diff --git a/packages/react-dev-utils/__tests__/ignoredFiles.test.js b/packages/react-dev-utils/__tests__/ignoredFiles.test.js
new file mode 100644
index 00000000000..6feed979797
--- /dev/null
+++ b/packages/react-dev-utils/__tests__/ignoredFiles.test.js
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+const ignoredFiles = require('../ignoredFiles');
+
+describe('ignore watch files regex', () => {
+  it('normal file', () => {
+    const appSrc = '/root/src/';
+    const isIgnored = ignoredFiles(appSrc).test('/foo');
+    const isIgnoredInSrc = ignoredFiles(appSrc).test('/root/src/foo');
+
+    expect(isIgnored).toBe(false);
+    expect(isIgnoredInSrc).toBe(false);
+  });
+
+  it('node modules', () => {
+    const appSrc = '/root/src/';
+    const isIgnored = ignoredFiles(appSrc).test('/root/node_modules/foo');
+
+    expect(isIgnored).toBe(true);
+  });
+
+  it('node modules inside source directory', () => {
+    const appSrc = '/root/src/';
+    const isIgnored = ignoredFiles(appSrc).test('/root/src/node_modules/foo');
+    const isIgnoredMoreThanOneLevel = ignoredFiles(appSrc).test(
+      '/root/src/bar/node_modules/foo'
+    );
+
+    expect(isIgnored).toBe(false);
+    expect(isIgnoredMoreThanOneLevel).toBe(false);
+  });
+
+  it('path contains source directory', () => {
+    const appSrc = '/root/src/';
+    const isIgnored = ignoredFiles(appSrc).test(
+      '/bar/root/src/node_modules/foo'
+    );
+
+    expect(isIgnored).toBe(true);
+  });
+
+  it('path starts with source directory', () => {
+    const appSrc = '/root/src/';
+    const isIgnored = ignoredFiles(appSrc).test('/root/src2/node_modules/foo');
+
+    expect(isIgnored).toBe(true);
+  });
+});
diff --git a/packages/react-dev-utils/ignoredFiles.js b/packages/react-dev-utils/ignoredFiles.js
new file mode 100644
index 00000000000..50348ea6bdd
--- /dev/null
+++ b/packages/react-dev-utils/ignoredFiles.js
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+const path = require('path');
+
+module.exports = function ignoredFiles(appSrc) {
+  return new RegExp(
+    `^(?!${path
+      .normalize(appSrc + '/')
+      .replace(/[\\]+/g, '/')}).+/node_modules/`,
+    'g'
+  );
+};
diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json
index db7114a261a..54606f33fe8 100644
--- a/packages/react-dev-utils/package.json
+++ b/packages/react-dev-utils/package.json
@@ -21,6 +21,7 @@
     "printBuildError.js",
     "formatWebpackMessages.js",
     "getProcessForPort.js",
+    "ignoredFiles.js",
     "inquirer.js",
     "InterpolateHtmlPlugin.js",
     "launchEditor.js",
@@ -53,5 +54,11 @@
     "sockjs-client": "1.1.4",
     "strip-ansi": "3.0.1",
     "text-table": "0.2.0"
+  },
+  "devDependencies": {
+    "jest": "20.0.4"
+  },
+  "scripts": {
+    "test": "jest"
   }
 }
diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js
index c32eb0f08a7..457a9672892 100644
--- a/packages/react-scripts/config/webpack.config.prod.js
+++ b/packages/react-scripts/config/webpack.config.prod.js
@@ -301,7 +301,7 @@ module.exports = {
       },
       mangle: {
         safari10: true,
-      },        
+      },
       output: {
         comments: false,
         // Turned on because emoji and regex is not minified properly using default
diff --git a/packages/react-scripts/config/webpackDevServer.config.js b/packages/react-scripts/config/webpackDevServer.config.js
index f401f2cce0d..80684538f9a 100644
--- a/packages/react-scripts/config/webpackDevServer.config.js
+++ b/packages/react-scripts/config/webpackDevServer.config.js
@@ -10,7 +10,7 @@
 
 const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
 const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
-const path = require('path');
+const ignoredFiles = require('react-dev-utils/ignoredFiles');
 const config = require('./webpack.config.dev');
 const paths = require('./paths');
 
@@ -76,12 +76,7 @@ module.exports = function(proxy, allowedHost) {
     // src/node_modules is not ignored to support absolute imports
     // https://github.com/facebookincubator/create-react-app/issues/1065
     watchOptions: {
-      ignored: new RegExp(
-        `^(?!${path
-          .normalize(paths.appSrc + '/')
-          .replace(/[\\]+/g, '\\\\')}).+[\\\\/]node_modules[\\\\/]`,
-        'g'
-      ),
+      ignored: ignoredFiles(paths.appSrc),
     },
     // Enable HTTPS if the HTTPS environment variable is set to 'true'
     https: protocol === 'https',
diff --git a/tasks/e2e-simple.sh b/tasks/e2e-simple.sh
index 867b6dc9503..9e51b00805d 100755
--- a/tasks/e2e-simple.sh
+++ b/tasks/e2e-simple.sh
@@ -159,6 +159,9 @@ cd packages/react-error-overlay/
 npm test
 npm run build:prod
 cd ../..
+cd packages/react-dev-utils/
+npm test
+cd ../..
 
 # ******************************************************************************
 # First, test the create-react-app development environment.