diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index 5a5a2ff6122..93589a99006 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -12,6 +12,7 @@ var autoprefixer = require('autoprefixer'); var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); +var WatchMissingNodeModulesPlugin = require('../scripts/utils/WatchMissingNodeModulesPlugin'); var paths = require('./paths'); module.exports = { @@ -107,6 +108,7 @@ module.exports = { new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"development"' }), // Note: only CSS is currently hot reloaded new webpack.HotModuleReplacementPlugin(), - new CaseSensitivePathsPlugin() + new CaseSensitivePathsPlugin(), + new WatchMissingNodeModulesPlugin(paths.appNodeModules) ] }; diff --git a/scripts/eject.js b/scripts/eject.js index c3570e86e39..35021387093 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -44,7 +44,8 @@ prompt( path.join('scripts', 'build.js'), path.join('scripts', 'start.js'), path.join('scripts', 'utils', 'chrome.applescript'), - path.join('scripts', 'utils', 'prompt.js') + path.join('scripts', 'utils', 'prompt.js'), + path.join('scripts', 'utils', 'WatchMissingNodeModulesPlugin.js') ]; // Ensure that the app folder is clean and we won't override any files diff --git a/scripts/utils/WatchMissingNodeModulesPlugin.js b/scripts/utils/WatchMissingNodeModulesPlugin.js new file mode 100644 index 00000000000..ee99c218806 --- /dev/null +++ b/scripts/utils/WatchMissingNodeModulesPlugin.js @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +// This Webpack plugin ensures `npm install ` forces a project rebuild. +// We’re not sure why this isn't Webpack's default behavior. +// See https://github.com/facebookincubator/create-react-app/issues/186. + +function WatchMissingNodeModulesPlugin(nodeModulesPath) { + this.nodeModulesPath = nodeModulesPath; +} + +WatchMissingNodeModulesPlugin.prototype.apply = function (compiler) { + compiler.plugin('emit', (compilation, callback) => { + var missingDeps = compilation.missingDependencies; + var nodeModulesPath = this.nodeModulesPath; + + // If any missing files are expected to appear in node_modules... + if (missingDeps.some(file => file.indexOf(nodeModulesPath) !== -1)) { + // ...tell webpack to watch node_modules recursively until they appear. + compilation.contextDependencies.push(nodeModulesPath); + } + + callback(); + }); +} + +module.exports = WatchMissingNodeModulesPlugin;