Skip to content

Commit 629e0c8

Browse files
committed
add watch script for react-scripts
1 parent 2a8535b commit 629e0c8

File tree

6 files changed

+547
-2
lines changed

6 files changed

+547
-2
lines changed

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"postinstall": "lerna bootstrap",
99
"publish": "tasks/release.sh",
1010
"start": "node packages/react-scripts/scripts/start.js",
11+
"watch": "node packages/react-scripts/scripts/watch.js",
1112
"test": "node packages/react-scripts/scripts/test.js --env=jsdom"
1213
},
1314
"devDependencies": {
@@ -21,4 +22,4 @@
2122
"lerna": "^2.0.0-beta.37",
2223
"lerna-changelog": "^0.2.3"
2324
}
24-
}
25+
}

Diff for: packages/react-dev-utils/isProduction.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = function isProduction(){
2+
return process.env.NODE_ENV === 'production'
3+
}
+302
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
// @remove-on-eject-begin
2+
/**
3+
* Copyright (c) 2015-present, Facebook, Inc.
4+
* All rights reserved.
5+
*
6+
* This source code is licensed under the BSD-style license found in the
7+
* LICENSE file in the root directory of this source tree. An additional grant
8+
* of patent rights can be found in the PATENTS file in the same directory.
9+
*/
10+
// @remove-on-eject-end
11+
12+
var autoprefixer = require("autoprefixer");
13+
var webpack = require("webpack");
14+
var HtmlWebpackPlugin = require("html-webpack-plugin");
15+
var ExtractTextPlugin = require("extract-text-webpack-plugin");
16+
var ManifestPlugin = require("webpack-manifest-plugin");
17+
var InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin");
18+
var url = require("url");
19+
var paths = require("./paths");
20+
var getClientEnvironment = require("./env");
21+
var isProduction = require("react-dev-utils/isProduction");
22+
23+
// @remove-on-eject-begin
24+
// `path` is not used after eject - see https://github.com/facebookincubator/create-react-app/issues/1174
25+
var path = require("path");
26+
// @remove-on-eject-end
27+
28+
// Webpack uses `publicPath` to determine where the app is being served from.
29+
// It requires a trailing slash, or the file assets will get an incorrect path.
30+
var publicPath = paths.servedPath;
31+
// Some apps do not use client-side routing with pushState.
32+
// For these, "homepage" can be set to "." to enable relative asset paths.
33+
var shouldUseRelativeAssetPaths = publicPath === "./";
34+
// `publicUrl` is just like `publicPath`, but we will provide it to our app
35+
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
36+
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
37+
var publicUrl = publicPath.slice(0, -1);
38+
// Get environment variables to inject into our app.
39+
var env = getClientEnvironment(publicUrl);
40+
41+
// Assert this just to be safe.
42+
// Development builds of React are slow and not intended for production.
43+
if (env.stringified["process.env"].NODE_ENV !== '"production"') {
44+
process.env.NODE_ENV = "development";
45+
}
46+
47+
// Note: defined here because it will be used more than once.
48+
const cssFilename = "static/css/" +
49+
process.env.NODE_ENV +
50+
".[name].[contenthash:8].css";
51+
52+
// ExtractTextPlugin expects the build output to be flat.
53+
// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
54+
// However, our output is structured with css, js and media folders.
55+
// To have this structure working with relative paths, we have to use custom options.
56+
const extractTextPluginOptions = shouldUseRelativeAssetPaths
57+
? // Making sure that the publicPath goes back to to build folder.
58+
{ publicPath: Array(cssFilename.split("/").length).join("../") }
59+
: {};
60+
61+
// This is the production configuration.
62+
// It compiles slowly and is focused on producing a fast and minimal bundle.
63+
// The development configuration is different and lives in a separate file.
64+
module.exports = {
65+
watch: true,
66+
context: paths.appSrc,
67+
// We generate sourcemaps in production. This is slow but gives good results.
68+
// You can exclude the *.map files from the build during deployment.
69+
devtool: isProduction() ? "source-map" : "cheap-module-source-map",
70+
// In production, we only want to load the polyfills and the app code.
71+
entry: [require.resolve("./polyfills"), paths.appIndexJs],
72+
output: {
73+
// The build folder.
74+
path: paths.appBuild,
75+
// Generated JS file names (with nested folders).
76+
// There will be one main bundle, and one file per asynchronous chunk.
77+
// We don't currently advertise code splitting but Webpack supports it.
78+
filename: "static/js/" + process.env.NODE_ENV + ".[name].[chunkhash:8].js",
79+
chunkFilename: (
80+
"static/js/" + process.env.NODE_ENV + ".[name].[chunkhash:8].chunk.js"
81+
),
82+
// We inferred the "public path" (such as / or /my-project) from homepage.
83+
publicPath: publicPath
84+
},
85+
resolve: {
86+
// This allows you to set a fallback for where Webpack should look for modules.
87+
// We read `NODE_PATH` environment variable in `paths.js` and pass paths here.
88+
// We placed these paths second because we want `node_modules` to "win"
89+
// if there are any conflicts. This matches Node resolution mechanism.
90+
// https://github.com/facebookincubator/create-react-app/issues/253
91+
modules: ["node_modules"].concat(paths.nodePaths),
92+
// These are the reasonable defaults supported by the Node ecosystem.
93+
// We also include JSX as a common component filename extension to support
94+
// some tools, although we do not recommend using it, see:
95+
// https://github.com/facebookincubator/create-react-app/issues/290
96+
extensions: [".js", ".json", ".jsx"],
97+
alias: {
98+
// Support React Native Web
99+
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
100+
"react-native": "react-native-web"
101+
}
102+
},
103+
// @remove-on-eject-begin
104+
// Resolve loaders (webpack plugins for CSS, images, transpilation) from the
105+
// directory of `react-scripts` itself rather than the project directory.
106+
resolveLoader: {
107+
modules: [
108+
paths.ownNodeModules,
109+
// Lerna hoists everything, so we need to look in our app directory
110+
paths.appNodeModules
111+
]
112+
},
113+
// @remove-on-eject-end
114+
module: {
115+
rules: [
116+
// Disable require.ensure as it's not a standard language feature.
117+
{ parser: { requireEnsure: false } },
118+
// First, run the linter.
119+
// It's important to do this before Babel processes the JS.
120+
{
121+
test: /\.(js|jsx)$/,
122+
enforce: "pre",
123+
use: [
124+
{
125+
// @remove-on-eject-begin
126+
// Point ESLint to our predefined config.
127+
options: {
128+
// TODO: consider separate config for production,
129+
// e.g. to enable no-console and no-debugger only in production.
130+
configFile: path.join(__dirname, "../.eslintrc"),
131+
useEslintrc: false
132+
},
133+
// @remove-on-eject-end
134+
loader: "eslint-loader"
135+
}
136+
],
137+
include: paths.appSrc
138+
},
139+
// ** ADDING/UPDATING LOADERS **
140+
// The "url" loader handles all assets unless explicitly excluded.
141+
// The `exclude` list *must* be updated with every change to loader extensions.
142+
// When adding a new loader, you must add its `test`
143+
// as a new entry in the `exclude` list in the "url" loader.
144+
145+
// "url" loader embeds assets smaller than specified size as data URLs to avoid requests.
146+
// Otherwise, it acts like the "file" loader.
147+
{
148+
exclude: [/\.html$/, /\.(js|jsx)$/, /\.css$/, /\.json$/, /\.svg$/],
149+
loader: "url-loader",
150+
options: {
151+
limit: 10000,
152+
name: (
153+
"static/media/" + process.env.NODE_ENV + ".[name].[hash:8].[ext]"
154+
)
155+
}
156+
},
157+
// Process JS with Babel.
158+
{
159+
test: /\.(js|jsx)$/,
160+
include: paths.appSrc,
161+
loader: "babel-loader",
162+
// @remove-on-eject-begin
163+
options: {
164+
babelrc: false,
165+
presets: [require.resolve("babel-preset-react-app")]
166+
}
167+
// @remove-on-eject-end
168+
},
169+
// The notation here is somewhat confusing.
170+
// "postcss" loader applies autoprefixer to our CSS.
171+
// "css" loader resolves paths in CSS and adds assets as dependencies.
172+
// "style" loader normally turns CSS into JS modules injecting <style>,
173+
// but unlike in development configuration, we do something different.
174+
// `ExtractTextPlugin` first applies the "postcss" and "css" loaders
175+
// (second argument), then grabs the result CSS and puts it into a
176+
// separate file in our build process. This way we actually ship
177+
// a single CSS file in production instead of JS code injecting <style>
178+
// tags. If you use code splitting, however, any async bundles will still
179+
// use the "style" loader inside the async code so CSS from them won't be
180+
// in the main CSS file.
181+
{
182+
test: /\.css$/,
183+
loader: ExtractTextPlugin.extract(
184+
Object.assign(
185+
{
186+
fallback: "style-loader",
187+
use: [
188+
{
189+
loader: "css-loader",
190+
options: {
191+
importLoaders: 1
192+
}
193+
},
194+
{
195+
loader: "postcss-loader",
196+
options: {
197+
ident: "postcss", // https://webpack.js.org/guides/migrating/#complex-options
198+
plugins: function() {
199+
return [
200+
autoprefixer({
201+
browsers: [
202+
">1%",
203+
"last 4 versions",
204+
"Firefox ESR",
205+
"not ie < 9" // React doesn't support IE8 anyway
206+
]
207+
})
208+
];
209+
}
210+
}
211+
}
212+
]
213+
},
214+
extractTextPluginOptions
215+
)
216+
)
217+
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
218+
},
219+
// "file" loader for svg
220+
{
221+
test: /\.svg$/,
222+
loader: "file-loader",
223+
options: {
224+
name: (
225+
"static/media/" + process.env.NODE_ENV + ".[name].[hash:8].[ext]"
226+
)
227+
}
228+
}
229+
230+
// ** STOP ** Are you adding a new loader?
231+
// Remember to add the new extension(s) to the "url" loader exclusion list.
232+
]
233+
},
234+
plugins: [
235+
// Makes some environment variables available in index.html.
236+
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
237+
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
238+
// In production, it will be an empty string unless you specify "homepage"
239+
// in `package.json`, in which case it will be the pathname of that URL.
240+
new InterpolateHtmlPlugin(env.raw),
241+
// Generates an `index.html` file with the <script> injected.
242+
new HtmlWebpackPlugin({
243+
inject: true,
244+
template: paths.appHtml,
245+
minify: (
246+
isProduction()
247+
? {
248+
removeComments: true,
249+
collapseWhitespace: true,
250+
removeRedundantAttributes: true,
251+
useShortDoctype: true,
252+
removeEmptyAttributes: true,
253+
removeStyleLinkTypeAttributes: true,
254+
keepClosingSlash: true,
255+
minifyJS: true,
256+
minifyCSS: true,
257+
minifyURLs: true
258+
}
259+
: false
260+
)
261+
}),
262+
// Makes some environment variables available to the JS code, for example:
263+
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
264+
// It is absolutely essential that NODE_ENV was set to production here.
265+
// Otherwise React will be compiled in the very slow development mode.
266+
new webpack.DefinePlugin(env.stringified),
267+
// Minify the code.
268+
isProduction()
269+
? new webpack.optimize.UglifyJsPlugin({
270+
compress: {
271+
screw_ie8: true, // React doesn't support IE8
272+
warnings: false
273+
},
274+
mangle: {
275+
screw_ie8: true
276+
},
277+
output: {
278+
comments: false,
279+
screw_ie8: true
280+
},
281+
sourceMap: true
282+
})
283+
: false,
284+
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
285+
new ExtractTextPlugin({
286+
filename: cssFilename
287+
}),
288+
// Generate a manifest file which contains a mapping of all asset filenames
289+
// to their corresponding output file so that tools can pick it up without
290+
// having to parse `index.html`.
291+
new ManifestPlugin({
292+
fileName: "asset-manifest.json"
293+
})
294+
].filter(Boolean),
295+
// Some libraries import Node modules but don't use them in the browser.
296+
// Tell Webpack to provide empty mocks for them so importing them works.
297+
node: {
298+
fs: "empty",
299+
net: "empty",
300+
tls: "empty"
301+
}
302+
};

Diff for: packages/react-scripts/scripts/eject.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ prompt(
5959
path.join('config', 'jest', 'fileTransform.js'),
6060
path.join('scripts', 'build.js'),
6161
path.join('scripts', 'start.js'),
62-
path.join('scripts', 'test.js')
62+
path.join('scripts', 'test.js'),
63+
path.join('scripts', 'watch.js')
6364
];
6465

6566
// Ensure that the app folder is clean and we won't override any files

Diff for: packages/react-scripts/scripts/init.js

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ module.exports = function(appPath, appName, verbose, originalDirectory, template
2626
appPackage.scripts = {
2727
'start': 'react-scripts start',
2828
'build': 'react-scripts build',
29+
'watch': 'react-scripts watch',
2930
'test': 'react-scripts test --env=jsdom',
3031
'eject': 'react-scripts eject'
3132
};

0 commit comments

Comments
 (0)