Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to webpack v2 #1291

Merged
merged 15 commits into from Feb 11, 2017
6 changes: 5 additions & 1 deletion packages/babel-preset-react-app/index.js
Expand Up @@ -88,7 +88,11 @@ if (env === 'test') {
module.exports = {
presets: [
// Latest stable ECMAScript features
require.resolve('babel-preset-latest'),
[require.resolve('babel-preset-latest'), {
'es2015': {
modules: false
}
}],
// JSX, Flow
require.resolve('babel-preset-react')
],
Expand Down
109 changes: 62 additions & 47 deletions packages/react-scripts/config/webpack.config.dev.js
Expand Up @@ -78,15 +78,15 @@ module.exports = {
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
// We read `NODE_PATH` environment variable in `paths.js` and pass paths here.
// We use `fallback` instead of `root` because we want `node_modules` to "win"
// if there any conflicts. This matches Node resolution mechanism.
// We placed these paths second because we want `node_modules` to "win"
// if there are any conflicts. This matches Node resolution mechanism.
// https://github.com/facebookincubator/create-react-app/issues/253
fallback: paths.nodePaths,
modules: ['node_modules'].concat(paths.nodePaths),
// These are the reasonable defaults supported by the Node ecosystem.
// We also include JSX as a common component filename extension to support
// some tools, although we do not recommend using it, see:
// https://github.com/facebookincubator/create-react-app/issues/290
extensions: ['.js', '.json', '.jsx', ''],
extensions: ['.js', '.json', '.jsx'],
alias: {
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
Expand All @@ -97,21 +97,32 @@ module.exports = {
// Resolve loaders (webpack plugins for CSS, images, transpilation) from the
// directory of `react-scripts` itself rather than the project directory.
resolveLoader: {
root: paths.ownNodeModules,
moduleTemplates: ['*-loader']
modules: [
paths.ownNodeModules,
// Lerna hoists everything, so we need to look in our app directory
paths.appNodeModules
]
},
// @remove-on-eject-end
module: {
// First, run the linter.
// It's important to do this before Babel processes the JS.
preLoaders: [
rules: [
// First, run the linter.
// It's important to do this before Babel processes the JS.
{
test: /\.(js|jsx)$/,
loader: 'eslint',
include: paths.appSrc,
}
],
loaders: [
enforce: 'pre',
use: [{
// @remove-on-eject-begin
// Point ESLint to our predefined config.
options: {
configFile: path.join(__dirname, '../.eslintrc'),
useEslintrc: false
},
// @remove-on-eject-end
loader: 'eslint-loader'
}],
include: paths.appSrc
},
// ** ADDING/UPDATING LOADERS **
// The "url" loader handles all assets unless explicitly excluded.
// The `exclude` list *must* be updated with every change to loader extensions.
Expand All @@ -128,8 +139,8 @@ module.exports = {
/\.json$/,
/\.svg$/
],
loader: 'url',
query: {
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]'
}
Expand All @@ -138,8 +149,8 @@ module.exports = {
{
test: /\.(js|jsx)$/,
include: paths.appSrc,
loader: 'babel',
query: {
loader: 'babel-loader',
options: {
// @remove-on-eject-begin
babelrc: false,
presets: [require.resolve('babel-preset-react-app')],
Expand All @@ -157,46 +168,44 @@ module.exports = {
// in development "style" loader enables hot editing of CSS.
{
test: /\.css$/,
loader: 'style!css?importLoaders=1!postcss'
},
// JSON is not enabled by default in Webpack but both Node and Browserify
// allow it implicitly so we also enable it.
{
test: /\.json$/,
loader: 'json'
use: [
'style-loader', {
loader: 'css-loader',
options: {
importLoaders: 1
}
}, {
loader: 'postcss-loader',
options: {
ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
plugins: function () {
return [
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
]
})
]
}
}
}
]
},
// "file" loader for svg
{
test: /\.svg$/,
loader: 'file',
query: {
loader: 'file-loader',
options: {
name: 'static/media/[name].[hash:8].[ext]'
}
}
// ** STOP ** Are you adding a new loader?
// Remember to add the new extension(s) to the "url" loader exclusion list.
]
},
// @remove-on-eject-begin
// Point ESLint to our predefined config.
eslint: {
configFile: path.join(__dirname, '../.eslintrc'),
useEslintrc: false
},
// @remove-on-eject-end
// We use PostCSS for autoprefixing only.
postcss: function() {
return [
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
]
}),
];
},
plugins: [
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
Expand Down Expand Up @@ -229,5 +238,11 @@ module.exports = {
fs: 'empty',
net: 'empty',
tls: 'empty'
},
// Turn off performance hints during development because we don't do any
// splitting or minification in interest of speed. These warnings become
// cumbersome.
performance: {
hints: false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is turned off completely during development and by default set to warning in the production config, it might come as a surprise to users to then have to tweak their app for code-splitting, although extracting css should bring the file size down. @TheLarkInn gives a reason to leave it enabled in dev builds. We could tweak the maxAssetSize and maxEntrypointSize options to reasonable file sizes instead. What do you think?

Copy link
Contributor Author

@Timer Timer Dec 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's very valuable in its certain form -- I think we need to go a step further and show our own warnings more in line with what @TheLarkInn was saying.

Currently, we don't display build size warnings -- and bundle size is going to vary wildly between end-users. I don't think there is a good "default" we can set which will cover all cases (and we don't want to expose configuration unless it's a feature we want to support for the foreseeable future of cra; even if we switch bundlers).

Knowing this, I think that monitoring build size between rebuilds would be beneficial to let the user know their bundle has grown -- maybe doing some caching so we can display warnings between restarts/sessions.

Since the feature isn't there now, I think we can safely disable it completely until we implement said feature or wait for more detailed [json] performance hints from webpack.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note, performance hints are now off by default in rc4:
https://github.com/webpack/webpack/releases/tag/v2.2.0-rc.4

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be set to warning in production now?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of additional details are you looking for? At the least I'd recommend having it as "warning" in Production as well.

}
};
127 changes: 67 additions & 60 deletions packages/react-scripts/config/webpack.config.prod.js
Expand Up @@ -52,8 +52,8 @@ const cssFilename = 'static/css/[name].[contenthash:8].css';
// To have this structure working with relative paths, we have to use custom options.
const extractTextPluginOptions = shouldUseRelativeAssetPaths
// Making sure that the publicPath goes back to to build folder.
? { publicPath: Array(cssFilename.split('/').length).join('../') }
: undefined;
? {publicPath: Array(cssFilename.split('/').length).join('../')}
: {};

// This is the production configuration.
// It compiles slowly and is focused on producing a fast and minimal bundle.
Expand Down Expand Up @@ -83,15 +83,15 @@ module.exports = {
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
// We read `NODE_PATH` environment variable in `paths.js` and pass paths here.
// We use `fallback` instead of `root` because we want `node_modules` to "win"
// if there any conflicts. This matches Node resolution mechanism.
// We placed these paths second because we want `node_modules` to "win"
// if there are any conflicts. This matches Node resolution mechanism.
// https://github.com/facebookincubator/create-react-app/issues/253
fallback: paths.nodePaths,
modules: ['node_modules'].concat(paths.nodePaths),
// These are the reasonable defaults supported by the Node ecosystem.
// We also include JSX as a common component filename extension to support
// some tools, although we do not recommend using it, see:
// https://github.com/facebookincubator/create-react-app/issues/290
extensions: ['.js', '.json', '.jsx', ''],
extensions: ['.js', '.json', '.jsx'],
alias: {
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
Expand All @@ -102,21 +102,34 @@ module.exports = {
// Resolve loaders (webpack plugins for CSS, images, transpilation) from the
// directory of `react-scripts` itself rather than the project directory.
resolveLoader: {
root: paths.ownNodeModules,
moduleTemplates: ['*-loader']
modules: [
paths.ownNodeModules,
// Lerna hoists everything, so we need to look in our app directory
paths.appNodeModules
]
},
// @remove-on-eject-end
module: {
// First, run the linter.
// It's important to do this before Babel processes the JS.
preLoaders: [
rules: [
// First, run the linter.
// It's important to do this before Babel processes the JS.
{
test: /\.(js|jsx)$/,
loader: 'eslint',
enforce: 'pre',
use: [{
// @remove-on-eject-begin
// Point ESLint to our predefined config.
options: {
// TODO: consider separate config for production,
// e.g. to enable no-console and no-debugger only in production.
configFile: path.join(__dirname, '../.eslintrc'),
useEslintrc: false
},
// @remove-on-eject-end
loader: 'eslint-loader'
}],
include: paths.appSrc
}
],
loaders: [
},
// ** ADDING/UPDATING LOADERS **
// The "url" loader handles all assets unless explicitly excluded.
// The `exclude` list *must* be updated with every change to loader extensions.
Expand All @@ -133,8 +146,8 @@ module.exports = {
/\.json$/,
/\.svg$/
],
loader: 'url',
query: {
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]'
}
Expand All @@ -143,9 +156,9 @@ module.exports = {
{
test: /\.(js|jsx)$/,
include: paths.appSrc,
loader: 'babel',
loader: 'babel-loader',
// @remove-on-eject-begin
query: {
options: {
babelrc: false,
presets: [require.resolve('babel-preset-react-app')],
},
Expand All @@ -165,53 +178,48 @@ module.exports = {
// in the main CSS file.
{
test: /\.css$/,
loader: ExtractTextPlugin.extract(
'style',
'css?importLoaders=1!postcss',
extractTextPluginOptions
)
loader: ExtractTextPlugin.extract(Object.assign({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
importLoaders: 1
}
}, {
loader: 'postcss-loader',
options: {
ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
plugins: function () {
return [
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
]
})
]
}
}
}
]
}, extractTextPluginOptions))
// 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$/,
loader: 'json'
},
// "file" loader for svg
{
test: /\.svg$/,
loader: 'file',
query: {
loader: 'file-loader',
options: {
name: 'static/media/[name].[hash:8].[ext]'
}
}
// ** STOP ** Are you adding a new loader?
// Remember to add the new extension(s) to the "url" loader exclusion list.
]
},
// @remove-on-eject-begin
// Point ESLint to our predefined config.
eslint: {
// TODO: consider separate config for production,
// e.g. to enable no-console and no-debugger only in production.
configFile: path.join(__dirname, '../.eslintrc'),
useEslintrc: false
},
// @remove-on-eject-end
// We use PostCSS for autoprefixing only.
postcss: function() {
return [
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
]
}),
];
},
plugins: [
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
Expand Down Expand Up @@ -241,10 +249,6 @@ module.exports = {
// 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(env.stringified),
// 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: {
Expand All @@ -257,10 +261,13 @@ module.exports = {
output: {
comments: false,
screw_ie8: true
}
},
sourceMap: true
}),
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
new ExtractTextPlugin(cssFilename),
new ExtractTextPlugin({
filename: cssFilename
}),
// Generate a manifest file which contains a mapping of all asset filenames
// to their corresponding output file so that tools can pick it up without
// having to parse `index.html`.
Expand Down
3 changes: 2 additions & 1 deletion packages/react-scripts/fixtures/kitchensink/.babelrc
@@ -1,3 +1,4 @@
{
"presets": ["react-app"]
"presets": ["react-app"],
"plugins": ["babel-plugin-transform-es2015-modules-commonjs"]
}