mirror of
https://github.com/zhigang1992/create-react-app.git
synced 2026-06-16 10:24:16 +08:00
Document configuration and build process (#362)
This commit is contained in:
@@ -8,22 +8,31 @@
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
// Don't try to find .babelrc because we want to force this configuration.
|
||||
babelrc: false,
|
||||
// This is a feature of `babel-loader` for webpack (not Babel itself).
|
||||
// It enables caching results in OS temporary directory for faster rebuilds.
|
||||
cacheDirectory: true,
|
||||
presets: [
|
||||
'babel-preset-es2015',
|
||||
'babel-preset-es2016',
|
||||
'babel-preset-react'
|
||||
].map(require.resolve),
|
||||
// let, const, destructuring, classes, modules
|
||||
require.resolve('babel-preset-es2015'),
|
||||
// exponentiation
|
||||
require.resolve('babel-preset-es2016'),
|
||||
// JSX, Flow
|
||||
require.resolve('babel-preset-react')
|
||||
],
|
||||
plugins: [
|
||||
'babel-plugin-syntax-trailing-function-commas',
|
||||
'babel-plugin-transform-class-properties',
|
||||
'babel-plugin-transform-object-rest-spread'
|
||||
].map(require.resolve).concat([
|
||||
// function x(a, b, c,) { }
|
||||
require.resolve('babel-plugin-syntax-trailing-function-commas'),
|
||||
// class { handleClick = () => { } }
|
||||
require.resolve('babel-plugin-transform-class-properties'),
|
||||
// { ...todo, completed: true }
|
||||
require.resolve('babel-plugin-transform-object-rest-spread'),
|
||||
// Polyfills the runtime needed for generators
|
||||
[require.resolve('babel-plugin-transform-runtime'), {
|
||||
helpers: false,
|
||||
polyfill: false,
|
||||
regenerator: true
|
||||
}]
|
||||
])
|
||||
]
|
||||
};
|
||||
|
||||
@@ -8,22 +8,30 @@
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
// Don't try to find .babelrc because we want to force this configuration.
|
||||
babelrc: false,
|
||||
presets: [
|
||||
'babel-preset-es2015',
|
||||
'babel-preset-es2016',
|
||||
'babel-preset-react'
|
||||
].map(require.resolve),
|
||||
// let, const, destructuring, classes, modules
|
||||
require.resolve('babel-preset-es2015'),
|
||||
// exponentiation
|
||||
require.resolve('babel-preset-es2016'),
|
||||
// JSX, Flow
|
||||
require.resolve('babel-preset-react')
|
||||
],
|
||||
plugins: [
|
||||
'babel-plugin-syntax-trailing-function-commas',
|
||||
'babel-plugin-transform-class-properties',
|
||||
'babel-plugin-transform-object-rest-spread',
|
||||
'babel-plugin-transform-react-constant-elements',
|
||||
].map(require.resolve).concat([
|
||||
// function x(a, b, c,) { }
|
||||
require.resolve('babel-plugin-syntax-trailing-function-commas'),
|
||||
// class { handleClick = () => { } }
|
||||
require.resolve('babel-plugin-transform-class-properties'),
|
||||
// { ...todo, completed: true }
|
||||
require.resolve('babel-plugin-transform-object-rest-spread'),
|
||||
// Polyfills the runtime needed for generators
|
||||
[require.resolve('babel-plugin-transform-runtime'), {
|
||||
helpers: false,
|
||||
polyfill: false,
|
||||
regenerator: true
|
||||
}]
|
||||
])
|
||||
}],
|
||||
// Optimization: hoist JSX that never changes out of render()
|
||||
require.resolve('babel-plugin-transform-react-constant-elements')
|
||||
],
|
||||
};
|
||||
|
||||
@@ -6,4 +6,5 @@ if (typeof Promise === 'undefined') {
|
||||
window.Promise = require('promise/lib/es6-extensions.js');
|
||||
}
|
||||
|
||||
// fetch() polyfill for making API calls.
|
||||
require('whatwg-fetch');
|
||||
|
||||
@@ -15,22 +15,56 @@ var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
|
||||
var WatchMissingNodeModulesPlugin = require('../scripts/utils/WatchMissingNodeModulesPlugin');
|
||||
var paths = require('./paths');
|
||||
|
||||
// This is the development configuration.
|
||||
// It is focused on developer experience and fast rebuilds.
|
||||
// The production configuration is different and lives in a separate file.
|
||||
module.exports = {
|
||||
// This makes the bundle appear split into separate modules in the devtools.
|
||||
// We don't use source maps here because they can be confusing:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/343#issuecomment-237241875
|
||||
// You may want 'cheap-module-source-map' instead if you prefer source maps.
|
||||
devtool: 'eval',
|
||||
// These are the "entry points" to our application.
|
||||
// This means they will be the "root" imports that are included in JS bundle.
|
||||
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
|
||||
entry: [
|
||||
// Include WebpackDevServer client. It connects to WebpackDevServer via
|
||||
// sockets and waits for recompile notifications. When WebpackDevServer
|
||||
// recompiles, it sends a message to the client by socket. If only CSS
|
||||
// was changed, the app reload just the CSS. Otherwise, it will refresh.
|
||||
// The "?/" bit at the end tells the client to look for the socket at
|
||||
// the root path, i.e. /sockjs-node/. Otherwise visiting a client-side
|
||||
// route like /todos/42 would make it wrongly request /todos/42/sockjs-node.
|
||||
// The socket server is a part of WebpackDevServer which we are using.
|
||||
// The /sockjs-node/ path I'm referring to is hardcoded in WebpackDevServer.
|
||||
require.resolve('webpack-dev-server/client') + '?/',
|
||||
// Include Webpack hot module replacement runtime. Webpack is pretty
|
||||
// low-level so we need to put all the pieces together. The runtime listens
|
||||
// to the events received by the client above, and applies updates (such as
|
||||
// new CSS) to the running application.
|
||||
require.resolve('webpack/hot/dev-server'),
|
||||
// We ship a few polyfills by default.
|
||||
require.resolve('./polyfills'),
|
||||
// Finally, this is your app's code:
|
||||
path.join(paths.appSrc, 'index')
|
||||
// We include the app code last so that if there is a runtime error during
|
||||
// initialization, it doesn't blow up the WebpackDevServer client, and
|
||||
// changing JS code would still trigger a refresh.
|
||||
],
|
||||
output: {
|
||||
// Next line is not used in dev but WebpackDevServer crashes without it:
|
||||
path: paths.appBuild,
|
||||
// Add /* filename */ comments to generated require()s in the output.
|
||||
pathinfo: true,
|
||||
// This does not produce a real file. It's just the virtual path that is
|
||||
// served by WebpackDevServer in development. This is the JS bundle
|
||||
// containing code from all our entry points, and the Webpack runtime.
|
||||
filename: 'static/js/bundle.js',
|
||||
// In development, we always serve from the root. This makes config easier.
|
||||
publicPath: '/'
|
||||
},
|
||||
resolve: {
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
extensions: ['.js', '.json', ''],
|
||||
alias: {
|
||||
// This `alias` section can be safely removed after ejection.
|
||||
@@ -44,11 +78,16 @@ module.exports = {
|
||||
'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator')
|
||||
}
|
||||
},
|
||||
// Resolve loaders (webpack plugins for CSS, images, transpilation) from the
|
||||
// directory of `react-scripts` itself rather than the project directory.
|
||||
// You can remove this after ejecting.
|
||||
resolveLoader: {
|
||||
root: paths.ownNodeModules,
|
||||
moduleTemplates: ['*-loader']
|
||||
},
|
||||
module: {
|
||||
// First, run the linter.
|
||||
// It's important to do this before Babel processes the JS.
|
||||
preLoaders: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
@@ -57,22 +96,33 @@ module.exports = {
|
||||
}
|
||||
],
|
||||
loaders: [
|
||||
// Process JS with Babel.
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: paths.appSrc,
|
||||
loader: 'babel',
|
||||
query: require('./babel.dev')
|
||||
},
|
||||
// "postcss" loader applies autoprefixer to our CSS.
|
||||
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
||||
// "style" loader turns CSS into JS modules that inject <style> tags.
|
||||
// In production, we use a plugin to extract that CSS to a file, but
|
||||
// in development "style" loader enables hot editing of CSS.
|
||||
{
|
||||
test: /\.css$/,
|
||||
include: [paths.appSrc, paths.appNodeModules],
|
||||
loader: 'style!css!postcss'
|
||||
},
|
||||
// JSON is not enabled by default in Webpack but both Node and Browserify
|
||||
// allow it implicitly so we also enable it.
|
||||
{
|
||||
test: /\.json$/,
|
||||
include: [paths.appSrc, paths.appNodeModules],
|
||||
loader: 'json'
|
||||
},
|
||||
// "file" loader makes sure those assets get served by WebpackDevServer.
|
||||
// When you `import` an asset, you get its (virtual) filename.
|
||||
// In production, they would get copied to the `build` folder.
|
||||
{
|
||||
test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
|
||||
include: [paths.appSrc, paths.appNodeModules],
|
||||
@@ -81,6 +131,8 @@ module.exports = {
|
||||
name: 'static/media/[name].[ext]'
|
||||
}
|
||||
},
|
||||
// "url" loader works just like "file" loader but it also embeds
|
||||
// assets smaller than specified size as data URLs to avoid requests.
|
||||
{
|
||||
test: /\.(mp4|webm)(\?.*)?$/,
|
||||
include: [paths.appSrc, paths.appNodeModules],
|
||||
@@ -92,10 +144,12 @@ module.exports = {
|
||||
}
|
||||
]
|
||||
},
|
||||
// Point ESLint to our predefined config.
|
||||
eslint: {
|
||||
configFile: path.join(__dirname, 'eslint.js'),
|
||||
useEslintrc: false
|
||||
},
|
||||
// We use PostCSS for autoprefixing only.
|
||||
postcss: function() {
|
||||
return [
|
||||
autoprefixer({
|
||||
@@ -103,21 +157,32 @@ module.exports = {
|
||||
'>1%',
|
||||
'last 4 versions',
|
||||
'Firefox ESR',
|
||||
'not ie < 9',
|
||||
'not ie < 9', // React doesn't support IE8 anyway
|
||||
]
|
||||
}),
|
||||
];
|
||||
},
|
||||
plugins: [
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: paths.appHtml,
|
||||
favicon: paths.appFavicon,
|
||||
}),
|
||||
// Makes the environment available to the JS code, for example:
|
||||
// if (process.env.NODE_ENV === 'development') { ... }. See `env.js`.
|
||||
new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"development"' }),
|
||||
// Note: only CSS is currently hot reloaded
|
||||
// This is necessary to emit hot updates (currently CSS only):
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
// Watcher doesn't work well if you mistype casing in a path so we use
|
||||
// a plugin that prints an error when you attempt to do this.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/240
|
||||
new CaseSensitivePathsPlugin(),
|
||||
// If you require a missing module and then `npm install` it, you still have
|
||||
// to restart the development server for Webpack to discover it. This plugin
|
||||
// makes the discovery automatic so you don't have to restart.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/186
|
||||
new WatchMissingNodeModulesPlugin(paths.appNodeModules)
|
||||
]
|
||||
};
|
||||
|
||||
@@ -15,27 +15,45 @@ var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
var url = require('url');
|
||||
var paths = require('./paths');
|
||||
|
||||
// We use "homepage" field to infer "public path" at which the app is served.
|
||||
// Webpack needs to know it to put the right <script> hrefs into HTML even in
|
||||
// single-page apps that may serve index.html for nested URLs like /todos/42.
|
||||
// We can't use a relative path in HTML because we don't want to load something
|
||||
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
|
||||
var homepagePath = require(paths.appPackageJson).homepage;
|
||||
var publicPath = homepagePath ? url.parse(homepagePath).pathname : '/';
|
||||
if (!publicPath.endsWith('/')) {
|
||||
// Prevents incorrect paths in file-loader
|
||||
// If we don't do this, file assets will get incorrect paths.
|
||||
publicPath += '/';
|
||||
}
|
||||
|
||||
// This is the production configuration.
|
||||
// It compiles slowly and is focused on producing a fast and minimal bundle.
|
||||
// The development configuration is different and lives in a separate file.
|
||||
module.exports = {
|
||||
// Don't attempt to continue if there are any errors.
|
||||
bail: true,
|
||||
// We generate sourcemaps in production. This is slow but gives good results.
|
||||
// You can exclude the *.map files from the build during deployment.
|
||||
devtool: 'source-map',
|
||||
// In production, we only want to load the polyfills and the app code.
|
||||
entry: [
|
||||
require.resolve('./polyfills'),
|
||||
path.join(paths.appSrc, 'index')
|
||||
],
|
||||
output: {
|
||||
// The build folder.
|
||||
path: paths.appBuild,
|
||||
// Generated JS file names (with nested folders).
|
||||
// There will be one main bundle, and one file per asynchronous chunk.
|
||||
// We don't currently advertise code splitting but Webpack supports it.
|
||||
filename: 'static/js/[name].[chunkhash:8].js',
|
||||
chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js',
|
||||
// We inferred the "public path" (such as / or /my-project) from homepage.
|
||||
publicPath: publicPath
|
||||
},
|
||||
resolve: {
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
extensions: ['.js', '.json', ''],
|
||||
alias: {
|
||||
// This `alias` section can be safely removed after ejection.
|
||||
@@ -49,11 +67,16 @@ module.exports = {
|
||||
'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator')
|
||||
}
|
||||
},
|
||||
// Resolve loaders (webpack plugins for CSS, images, transpilation) from the
|
||||
// directory of `react-scripts` itself rather than the project directory.
|
||||
// You can remove this after ejecting.
|
||||
resolveLoader: {
|
||||
root: paths.ownNodeModules,
|
||||
moduleTemplates: ['*-loader']
|
||||
},
|
||||
module: {
|
||||
// First, run the linter.
|
||||
// It's important to do this before Babel processes the JS.
|
||||
preLoaders: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
@@ -62,26 +85,44 @@ module.exports = {
|
||||
}
|
||||
],
|
||||
loaders: [
|
||||
// Process JS with Babel.
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: paths.appSrc,
|
||||
loader: 'babel',
|
||||
query: require('./babel.prod')
|
||||
},
|
||||
// The notation here is somewhat confusing.
|
||||
// "postcss" loader applies autoprefixer to our CSS.
|
||||
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
||||
// "style" loader normally turns CSS into JS modules injecting <style>,
|
||||
// but unlike in development configuration, we do something different.
|
||||
// `ExtractTextPlugin` first applies the "postcss" and "css" loaders
|
||||
// (second argument), then grabs the result CSS and puts it into a
|
||||
// separate file in our build process. This way we actually ship
|
||||
// a single CSS file in production instead of JS code injecting <style>
|
||||
// tags. If you use code splitting, however, any async bundles will still
|
||||
// use the "style" loader inside the async code so CSS from them won't be
|
||||
// in the main CSS file.
|
||||
{
|
||||
test: /\.css$/,
|
||||
include: [paths.appSrc, paths.appNodeModules],
|
||||
// Disable autoprefixer in css-loader itself:
|
||||
// "?-autoprefixer" disables autoprefixer in css-loader itself:
|
||||
// https://github.com/webpack/css-loader/issues/281
|
||||
// We already have it thanks to postcss.
|
||||
loader: ExtractTextPlugin.extract('style', 'css?-autoprefixer!postcss')
|
||||
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
|
||||
},
|
||||
{
|
||||
// JSON is not enabled by default in Webpack but both Node and Browserify
|
||||
// allow it implicitly so we also enable it.
|
||||
test: /\.json$/,
|
||||
include: [paths.appSrc, paths.appNodeModules],
|
||||
loader: 'json'
|
||||
},
|
||||
{
|
||||
// "file" loader makes sure those assets end up in the `build` folder.
|
||||
// When you `import` an asset, you get its filename.
|
||||
test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
|
||||
include: [paths.appSrc, paths.appNodeModules],
|
||||
loader: 'file',
|
||||
@@ -89,6 +130,8 @@ module.exports = {
|
||||
name: 'static/media/[name].[hash:8].[ext]'
|
||||
}
|
||||
},
|
||||
// "url" loader works just like "file" loader but it also embeds
|
||||
// assets smaller than specified size as data URLs to avoid requests.
|
||||
{
|
||||
test: /\.(mp4|webm)(\?.*)?$/,
|
||||
include: [paths.appSrc, paths.appNodeModules],
|
||||
@@ -100,12 +143,14 @@ module.exports = {
|
||||
}
|
||||
]
|
||||
},
|
||||
// Point ESLint to our predefined config.
|
||||
eslint: {
|
||||
// TODO: consider separate config for production,
|
||||
// e.g. to enable no-console and no-debugger only in prod.
|
||||
// e.g. to enable no-console and no-debugger only in production.
|
||||
configFile: path.join(__dirname, 'eslint.js'),
|
||||
useEslintrc: false
|
||||
},
|
||||
// We use PostCSS for autoprefixing only.
|
||||
postcss: function() {
|
||||
return [
|
||||
autoprefixer({
|
||||
@@ -113,12 +158,13 @@ module.exports = {
|
||||
'>1%',
|
||||
'last 4 versions',
|
||||
'Firefox ESR',
|
||||
'not ie < 9',
|
||||
'not ie < 9', // React doesn't support IE8 anyway
|
||||
]
|
||||
}),
|
||||
];
|
||||
},
|
||||
plugins: [
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: paths.appHtml,
|
||||
@@ -136,12 +182,19 @@ module.exports = {
|
||||
minifyURLs: true
|
||||
}
|
||||
}),
|
||||
// Makes the environment available to the JS code, for example:
|
||||
// if (process.env.NODE_ENV === 'production') { ... }. See `env.js`.
|
||||
// It is absolutely essential that NODE_ENV was set to production here.
|
||||
// Otherwise React will be compiled in the very slow development mode.
|
||||
new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }),
|
||||
// This helps ensure the builds are consistent if source hasn't changed:
|
||||
new webpack.optimize.OccurrenceOrderPlugin(),
|
||||
// Try to dedupe duplicated modules, if any:
|
||||
new webpack.optimize.DedupePlugin(),
|
||||
// Minify the code.
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
screw_ie8: true,
|
||||
screw_ie8: true, // React doesn't support IE8
|
||||
warnings: false
|
||||
},
|
||||
mangle: {
|
||||
@@ -152,6 +205,7 @@ module.exports = {
|
||||
screw_ie8: true
|
||||
}
|
||||
}),
|
||||
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
|
||||
new ExtractTextPlugin('static/css/[name].[contenthash:8].css')
|
||||
]
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
var chalk = require('chalk');
|
||||
@@ -21,12 +22,16 @@ var paths = require('../config/paths');
|
||||
var recursive = require('recursive-readdir');
|
||||
var stripAnsi = require('strip-ansi');
|
||||
|
||||
// Input: /User/dan/app/build/static/js/main.82be8.js
|
||||
// Output: /static/js/main.js
|
||||
function removeFileNameHash(fileName) {
|
||||
return fileName
|
||||
.replace(paths.appBuild, '')
|
||||
.replace(/\/?(.*)(\.\w+)(\.js|\.css)/, (match, p1, p2, p3) => p1 + p3);
|
||||
}
|
||||
|
||||
// Input: 1024, 2048
|
||||
// Output: "(+1 KB)"
|
||||
function getDifferenceLabel(currentSize, previousSize) {
|
||||
var FIFTY_KILOBYTES = 1024 * 50;
|
||||
var difference = currentSize - previousSize;
|
||||
@@ -62,6 +67,7 @@ recursive(paths.appBuild, (err, fileNames) => {
|
||||
build(previousSizeMap);
|
||||
});
|
||||
|
||||
// Print a detailed summary of build files.
|
||||
function printFileSizes(stats, previousSizeMap) {
|
||||
var assets = stats.toJson().assets
|
||||
.filter(asset => /\.(js|css)$/.test(asset.name))
|
||||
@@ -78,7 +84,6 @@ function printFileSizes(stats, previousSizeMap) {
|
||||
};
|
||||
});
|
||||
assets.sort((a, b) => b.size - a.size);
|
||||
|
||||
var longestSizeLabelLength = Math.max.apply(null,
|
||||
assets.map(a => stripAnsi(a.sizeLabel).length)
|
||||
);
|
||||
@@ -96,6 +101,7 @@ function printFileSizes(stats, previousSizeMap) {
|
||||
});
|
||||
}
|
||||
|
||||
// Create the production build and print the deployment instructions.
|
||||
function build(previousSizeMap) {
|
||||
console.log('Creating an optimized production build...');
|
||||
webpack(config).run((err, stats) => {
|
||||
|
||||
@@ -19,7 +19,7 @@ var detect = require('detect-port');
|
||||
var prompt = require('./utils/prompt');
|
||||
var config = require('../config/webpack.config.dev');
|
||||
|
||||
// Tools like Cloud9 rely on this
|
||||
// Tools like Cloud9 rely on this.
|
||||
var DEFAULT_PORT = process.env.PORT || 3000;
|
||||
var compiler;
|
||||
|
||||
@@ -37,15 +37,13 @@ if (isSmokeTest) {
|
||||
};
|
||||
}
|
||||
|
||||
// Some custom utilities to prettify Webpack output.
|
||||
// This is a little hacky.
|
||||
// It would be easier if webpack provided a rich error object.
|
||||
var friendlySyntaxErrorLabel = 'Syntax error:';
|
||||
|
||||
function isLikelyASyntaxError(message) {
|
||||
return message.indexOf(friendlySyntaxErrorLabel) !== -1;
|
||||
}
|
||||
|
||||
// This is a little hacky.
|
||||
// It would be easier if webpack provided a rich error object.
|
||||
|
||||
function formatMessage(message) {
|
||||
return message
|
||||
// Make some common errors shorter:
|
||||
@@ -66,17 +64,27 @@ function formatMessage(message) {
|
||||
}
|
||||
|
||||
function clearConsole() {
|
||||
// This seems to work best on Windows and other systems.
|
||||
// The intention is to clear the output so you can focus on most recent build.
|
||||
process.stdout.write('\x1bc');
|
||||
}
|
||||
|
||||
function setupCompiler(port) {
|
||||
// "Compiler" is a low-level interface to Webpack.
|
||||
// It lets us listen to some events and provide our own custom messages.
|
||||
compiler = webpack(config, handleCompile);
|
||||
|
||||
// "invalid" event fires when you have changed a file, and Webpack is
|
||||
// recompiling a bundle. WebpackDevServer takes care to pause serving the
|
||||
// bundle, so if you refresh, it'll wait instead of serving the old one.
|
||||
// "invalid" is short for "bundle invalidated", it doesn't imply any errors.
|
||||
compiler.plugin('invalid', function() {
|
||||
clearConsole();
|
||||
console.log('Compiling...');
|
||||
});
|
||||
|
||||
// "done" event fires when Webpack has finished recompiling the bundle.
|
||||
// Whether or not you have warnings or errors, you will get this event.
|
||||
compiler.plugin('done', function(stats) {
|
||||
clearConsole();
|
||||
var hasErrors = stats.hasErrors();
|
||||
@@ -91,10 +99,12 @@ function setupCompiler(port) {
|
||||
console.log('Note that the development build is not optimized.');
|
||||
console.log('To create a production build, use ' + chalk.cyan('npm run build') + '.');
|
||||
console.log();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We have switched off the default Webpack output in WebpackDevServer
|
||||
// options so we are going to "massage" the warnings and errors and present
|
||||
// them in a readable focused way.
|
||||
var json = stats.toJson();
|
||||
var formattedErrors = json.errors.map(message =>
|
||||
'Error in ' + formatMessage(message)
|
||||
@@ -102,7 +112,6 @@ function setupCompiler(port) {
|
||||
var formattedWarnings = json.warnings.map(message =>
|
||||
'Warning in ' + formatMessage(message)
|
||||
);
|
||||
|
||||
if (hasErrors) {
|
||||
console.log(chalk.red('Failed to compile.'));
|
||||
console.log();
|
||||
@@ -119,7 +128,6 @@ function setupCompiler(port) {
|
||||
// If errors exist, ignore warnings.
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasWarnings) {
|
||||
console.log(chalk.yellow('Compiled with warnings.'));
|
||||
console.log();
|
||||
@@ -127,7 +135,7 @@ function setupCompiler(port) {
|
||||
console.log(message);
|
||||
console.log();
|
||||
});
|
||||
|
||||
// Teach some ESLint tricks.
|
||||
console.log('You may use special comments to disable some warnings.');
|
||||
console.log('Use ' + chalk.yellow('// eslint-disable-next-line') + ' to ignore the next line.');
|
||||
console.log('Use ' + chalk.yellow('/* eslint-disable */') + ' to ignore all warnings in a file.');
|
||||
@@ -156,11 +164,25 @@ function openBrowser(port) {
|
||||
}
|
||||
|
||||
function runDevServer(port) {
|
||||
// Launch WebpackDevServer.
|
||||
new WebpackDevServer(compiler, {
|
||||
// When an unrecognized URL is requested (e.g. localhost:3000/todos),
|
||||
// assume that this is a single-page app, and serve index.html.
|
||||
historyApiFallback: true,
|
||||
hot: true, // Note: only CSS is currently hot reloaded
|
||||
// Enable hot reloading server. It will provide /sockjs-node/ endpoint
|
||||
// for the WebpackDevServer client so it can learn when the files were
|
||||
// updated. The WebpackDevServer client is included as an entry point
|
||||
// in the Webpack development configuration. Note that only changes
|
||||
// to CSS are currently hot reloaded. JS changes will refresh the browser.
|
||||
hot: true,
|
||||
// It is important to tell WebpackDevServer to use the same "root" path
|
||||
// as we specified in the config. In development, we always serve from /.
|
||||
publicPath: config.output.publicPath,
|
||||
// WebpackDevServer is noisy by default so we emit custom message instead
|
||||
// by listening to the compiler events with `compiler.plugin` calls above.
|
||||
quiet: true,
|
||||
// Reportedly, this avoids CPU overload on some systems.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/293
|
||||
watchOptions: {
|
||||
ignored: /node_modules/
|
||||
}
|
||||
@@ -181,6 +203,8 @@ function run(port) {
|
||||
runDevServer(port);
|
||||
}
|
||||
|
||||
// We attempt to use the default port but if it is busy, we offer the user to
|
||||
// run on a different port. `detect()` Promise resolves to the next free port.
|
||||
detect(DEFAULT_PORT).then(port => {
|
||||
if (port === DEFAULT_PORT) {
|
||||
run(port);
|
||||
|
||||
Reference in New Issue
Block a user