mirror of
https://github.com/zhigang1992/create-react-app.git
synced 2026-01-12 17:12:59 +08:00
- [x] Upgrade to webpack 4.8.X (#4077)
- [x] Utilize webpack 4 development and production modes - [x] Upgrade webpack dev server - [x] Webpack 4 compatible release of thread-loader - [x] Webpack 4 compatible release of HtmlWebpackPlugin - [x] Webpack 4 compatible release of SwPrecacheWebpackPlugin - [x] Webpack 4 compatible release of WebpackManifestPlugin - [x] Update README - [x] Update WebpackDevServerUtils - [x] Update InterpolateHtmlPlugin - [x] Update ModuleScopePlugin - [x] Update WatchMissingNodeModulesPlugin - [x] Move UglifyJS options to webpack 4 optimize - [x] Move InterpolateHtmlPlugin to make it tapable on HtmlWebpackPlugin - [x] vendor splitting via splitChunks.splitChunks (https://twitter.com/wSokra/status/969633336732905474) - [x] long term caching via splitChunks.runtimeChunk (https://twitter.com/wSokra/status/969679223278505985) - [x] Make sure process.env.NODE_ENV is proxied correctly to `react-error-overlay` - [x] Implicit webpack.NamedModulesPlugin in dev config as its default in webpack 4 - [x] Disable webpack performance hints as we have our own filesize reporter - [x] Replace ExtractTextPlugin with MiniCssExtractPlugin - [x] Switch to css whole file minification via OptimizeCSSAssetsPlugin rather than per module css minification to gain performance
This commit is contained in:
committed by
Dan Abramov
parent
493a379c21
commit
d72678fb0c
14
package.json
14
package.json
@@ -19,16 +19,16 @@
|
||||
"precommit": "lint-staged"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "4.15.0",
|
||||
"execa": "^0.9.0",
|
||||
"husky": "^0.13.2",
|
||||
"lerna": "2.6.0",
|
||||
"lerna-changelog": "^0.6.0",
|
||||
"eslint": "4.19.1",
|
||||
"execa": "^0.10.0",
|
||||
"husky": "^0.14.3",
|
||||
"lerna": "2.9.1",
|
||||
"lerna-changelog": "^0.7.0",
|
||||
"lint-staged": "^7.0.5",
|
||||
"meow": "^4.0.0",
|
||||
"multimatch": "^2.1.0",
|
||||
"prettier": "1.6.1",
|
||||
"svg-term-cli": "^2.0.3",
|
||||
"prettier": "1.12.1",
|
||||
"svg-term-cli": "^2.1.1",
|
||||
"tempy": "^0.2.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
|
||||
@@ -27,6 +27,6 @@
|
||||
"@babel/preset-react": "7.0.0-beta.46",
|
||||
"babel-plugin-macros": "2.2.1",
|
||||
"babel-plugin-transform-dynamic-import": "2.0.0",
|
||||
"babel-plugin-transform-react-remove-prop-types": "0.4.12"
|
||||
"babel-plugin-transform-react-remove-prop-types": "0.4.13"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
"index.js"
|
||||
],
|
||||
"devDependencies": {
|
||||
"jest": "22.4.1"
|
||||
"jest": "22.4.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"eslint-plugin-flowtype": "^2.34.1",
|
||||
"eslint-plugin-import": "^2.6.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.0.2",
|
||||
"eslint-plugin-react": "^7.7.0"
|
||||
"eslint-plugin-react": "^7.8.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"confusing-browser-globals": "^1.0.0"
|
||||
|
||||
@@ -22,10 +22,10 @@ class InterpolateHtmlPlugin {
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.plugin('compilation', compilation => {
|
||||
compilation.plugin(
|
||||
'html-webpack-plugin-before-html-processing',
|
||||
(data, callback) => {
|
||||
compiler.hooks.compilation.tap('InterpolateHtmlPlugin', compilation => {
|
||||
compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing.tap(
|
||||
'InterpolateHtmlPlugin',
|
||||
data => {
|
||||
// Run HTML through a series of user-specified string replacements.
|
||||
Object.keys(this.replacements).forEach(key => {
|
||||
const value = this.replacements[key];
|
||||
@@ -34,7 +34,6 @@ class InterpolateHtmlPlugin {
|
||||
value
|
||||
);
|
||||
});
|
||||
callback(null, data);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
128
packages/react-dev-utils/ModuleScopePlugin.js
vendored
128
packages/react-dev-utils/ModuleScopePlugin.js
vendored
@@ -18,70 +18,72 @@ class ModuleScopePlugin {
|
||||
|
||||
apply(resolver) {
|
||||
const { appSrcs } = this;
|
||||
resolver.plugin('file', (request, callback) => {
|
||||
// Unknown issuer, probably webpack internals
|
||||
if (!request.context.issuer) {
|
||||
return callback();
|
||||
}
|
||||
if (
|
||||
// If this resolves to a node_module, we don't care what happens next
|
||||
request.descriptionFileRoot.indexOf('/node_modules/') !== -1 ||
|
||||
request.descriptionFileRoot.indexOf('\\node_modules\\') !== -1 ||
|
||||
// Make sure this request was manual
|
||||
!request.__innerRequest_request
|
||||
) {
|
||||
return callback();
|
||||
}
|
||||
// Resolve the issuer from our appSrc and make sure it's one of our files
|
||||
// Maybe an indexOf === 0 would be better?
|
||||
if (
|
||||
appSrcs.every(appSrc => {
|
||||
const relative = path.relative(appSrc, request.context.issuer);
|
||||
// If it's not in one of our app src or a subdirectory, not our request!
|
||||
return relative.startsWith('../') || relative.startsWith('..\\');
|
||||
})
|
||||
) {
|
||||
return callback();
|
||||
}
|
||||
const requestFullPath = path.resolve(
|
||||
path.dirname(request.context.issuer),
|
||||
request.__innerRequest_request
|
||||
);
|
||||
if (this.allowedFiles.has(requestFullPath)) {
|
||||
return callback();
|
||||
}
|
||||
// Find path from src to the requested file
|
||||
// Error if in a parent directory of all given appSrcs
|
||||
if (
|
||||
appSrcs.every(appSrc => {
|
||||
const requestRelative = path.relative(appSrc, requestFullPath);
|
||||
return (
|
||||
requestRelative.startsWith('../') ||
|
||||
requestRelative.startsWith('..\\')
|
||||
);
|
||||
})
|
||||
) {
|
||||
callback(
|
||||
new Error(
|
||||
`You attempted to import ${chalk.cyan(
|
||||
request.__innerRequest_request
|
||||
)} which falls outside of the project ${chalk.cyan(
|
||||
'src/'
|
||||
)} directory. ` +
|
||||
`Relative imports outside of ${chalk.cyan(
|
||||
'src/'
|
||||
)} are not supported. ` +
|
||||
`You can either move it inside ${chalk.cyan(
|
||||
'src/'
|
||||
)}, or add a symlink to it from project's ${chalk.cyan(
|
||||
'node_modules/'
|
||||
)}.`
|
||||
),
|
||||
request
|
||||
resolver.hooks.file.tapAsync(
|
||||
'ModuleScopePlugin',
|
||||
(request, contextResolver, callback) => {
|
||||
// Unknown issuer, probably webpack internals
|
||||
if (!request.context.issuer) {
|
||||
return callback();
|
||||
}
|
||||
if (
|
||||
// If this resolves to a node_module, we don't care what happens next
|
||||
request.descriptionFileRoot.indexOf('/node_modules/') !== -1 ||
|
||||
request.descriptionFileRoot.indexOf('\\node_modules\\') !== -1 ||
|
||||
// Make sure this request was manual
|
||||
!request.__innerRequest_request
|
||||
) {
|
||||
return callback();
|
||||
}
|
||||
// Resolve the issuer from our appSrc and make sure it's one of our files
|
||||
// Maybe an indexOf === 0 would be better?
|
||||
if (
|
||||
appSrcs.every(appSrc => {
|
||||
const relative = path.relative(appSrc, request.context.issuer);
|
||||
// If it's not in one of our app src or a subdirectory, not our request!
|
||||
return relative.startsWith('../') || relative.startsWith('..\\');
|
||||
})
|
||||
) {
|
||||
return callback();
|
||||
}
|
||||
const requestFullPath = path.resolve(
|
||||
path.dirname(request.context.issuer),
|
||||
request.__innerRequest_request
|
||||
);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
if (this.allowedFiles.has(requestFullPath)) {
|
||||
return callback();
|
||||
}
|
||||
// Find path from src to the requested file
|
||||
// Error if in a parent directory of all given appSrcs
|
||||
if (
|
||||
appSrcs.every(appSrc => {
|
||||
const requestRelative = path.relative(appSrc, requestFullPath);
|
||||
return (
|
||||
requestRelative.startsWith('../') ||
|
||||
requestRelative.startsWith('..\\')
|
||||
);
|
||||
})
|
||||
) {
|
||||
callback(
|
||||
new Error(
|
||||
`You attempted to import ${chalk.cyan(
|
||||
request.__innerRequest_request
|
||||
)} which falls outside of the project ${chalk.cyan(
|
||||
'src/'
|
||||
)} directory. ` +
|
||||
`Relative imports outside of ${chalk.cyan(
|
||||
'src/'
|
||||
)} are not supported. ` +
|
||||
`You can either move it inside ${chalk.cyan(
|
||||
'src/'
|
||||
)}, or add a symlink to it from project's ${chalk.cyan(
|
||||
'node_modules/'
|
||||
)}.`
|
||||
),
|
||||
request
|
||||
);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,11 @@ module.exports = {
|
||||
},
|
||||
// ...
|
||||
plugins: [
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: path.resolve('public/index.html'),
|
||||
}),
|
||||
// Makes the public URL available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
new InterpolateHtmlPlugin({
|
||||
@@ -45,11 +50,6 @@ module.exports = {
|
||||
// You can pass any key-value pairs, this was just an example.
|
||||
// WHATEVER: 42 will replace %WHATEVER% with 42 in index.html.
|
||||
}),
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: path.resolve('public/index.html'),
|
||||
}),
|
||||
// ...
|
||||
],
|
||||
// ...
|
||||
@@ -198,11 +198,11 @@ var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
|
||||
|
||||
var compiler = webpack(config);
|
||||
|
||||
compiler.plugin('invalid', function() {
|
||||
compiler.hooks.invalid.tap('invalid', function() {
|
||||
console.log('Compiling...');
|
||||
});
|
||||
|
||||
compiler.plugin('done', function(stats) {
|
||||
compiler.hooks.done.tap('done', function(stats) {
|
||||
var rawMessages = stats.toJson({}, true);
|
||||
var messages = formatWebpackMessages(rawMessages);
|
||||
if (!messages.errors.length && !messages.warnings.length) {
|
||||
|
||||
@@ -17,17 +17,15 @@ class WatchMissingNodeModulesPlugin {
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.plugin('emit', (compilation, callback) => {
|
||||
var missingDeps = compilation.missingDependencies;
|
||||
compiler.hooks.emit.tap('WatchMissingNodeModulesPlugin', compilation => {
|
||||
var missingDeps = Array.from(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)) {
|
||||
if (missingDeps.some(file => file.includes(nodeModulesPath))) {
|
||||
// ...tell webpack to watch node_modules recursively until they appear.
|
||||
compilation.contextDependencies.push(nodeModulesPath);
|
||||
compilation.contextDependencies.add(nodeModulesPath);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ function createCompiler(webpack, config, appName, urls, useYarn) {
|
||||
// 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', () => {
|
||||
compiler.hooks.invalid.tap('invalid', () => {
|
||||
if (isInteractive) {
|
||||
clearConsole();
|
||||
}
|
||||
@@ -142,7 +142,7 @@ function createCompiler(webpack, config, appName, urls, useYarn) {
|
||||
|
||||
// "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', stats => {
|
||||
compiler.hooks.done.tap('done', stats => {
|
||||
if (isInteractive) {
|
||||
clearConsole();
|
||||
}
|
||||
|
||||
@@ -40,29 +40,29 @@
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "7.0.0-beta.46",
|
||||
"address": "1.0.3",
|
||||
"browserslist": "2.11.3",
|
||||
"chalk": "2.3.0",
|
||||
"cross-spawn": "5.1.0",
|
||||
"browserslist": "3.2.6",
|
||||
"chalk": "2.4.1",
|
||||
"cross-spawn": "6.0.5",
|
||||
"detect-port-alt": "1.1.6",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"filesize": "3.5.11",
|
||||
"filesize": "3.6.1",
|
||||
"find-pkg": "1.0.0",
|
||||
"global-modules": "1.0.0",
|
||||
"globby": "7.1.1",
|
||||
"globby": "8.0.1",
|
||||
"gzip-size": "4.1.0",
|
||||
"inquirer": "5.0.0",
|
||||
"inquirer": "5.1.0",
|
||||
"is-root": "1.0.0",
|
||||
"opn": "5.2.0",
|
||||
"opn": "5.3.0",
|
||||
"pkg-up": "2.0.0",
|
||||
"react-error-overlay": "^4.0.0",
|
||||
"recursive-readdir": "2.2.1",
|
||||
"recursive-readdir": "2.2.2",
|
||||
"shell-quote": "1.6.1",
|
||||
"sockjs-client": "1.1.4",
|
||||
"strip-ansi": "4.0.0",
|
||||
"text-table": "0.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "22.4.1"
|
||||
"jest": "22.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
|
||||
@@ -36,31 +36,32 @@
|
||||
"anser": "1.4.6",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-eslint": "^8.2.2",
|
||||
"babel-jest": "^22.4.1",
|
||||
"babel-jest": "^22.4.3",
|
||||
"babel-loader": "^8.0.0-beta.0",
|
||||
"babel-preset-react-app": "^3.1.1",
|
||||
"chalk": "^2.1.0",
|
||||
"chokidar": "^2.0.0",
|
||||
"cross-env": "5.1.3",
|
||||
"eslint": "4.15.0",
|
||||
"chalk": "^2.3.2",
|
||||
"chokidar": "^2.0.2",
|
||||
"cross-env": "5.1.4",
|
||||
"eslint": "4.19.1",
|
||||
"eslint-config-react-app": "^2.1.0",
|
||||
"eslint-plugin-flowtype": "2.41.0",
|
||||
"eslint-plugin-import": "2.8.0",
|
||||
"eslint-plugin-flowtype": "2.46.1",
|
||||
"eslint-plugin-import": "2.9.0",
|
||||
"eslint-plugin-jsx-a11y": "6.0.3",
|
||||
"eslint-plugin-react": "7.7.0",
|
||||
"eslint-plugin-react": "7.8.2",
|
||||
"flow-bin": "^0.63.1",
|
||||
"html-entities": "1.2.1",
|
||||
"jest": "22.4.1",
|
||||
"jest-fetch-mock": "1.2.1",
|
||||
"jest": "22.4.3",
|
||||
"jest-fetch-mock": "1.5.0",
|
||||
"object-assign": "4.1.1",
|
||||
"promise": "8.0.1",
|
||||
"raw-loader": "^0.5.1",
|
||||
"react": "^16.0.0",
|
||||
"react-dom": "^16.0.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"react": "^16.3.2",
|
||||
"react-dom": "^16.3.2",
|
||||
"rimraf": "^2.6.2",
|
||||
"settle-promise": "1.0.0",
|
||||
"source-map": "0.5.6",
|
||||
"webpack": "^3.6.0"
|
||||
"uglifyjs-webpack-plugin": "1.2.5",
|
||||
"webpack": "^4.8.1"
|
||||
},
|
||||
"jest": {
|
||||
"setupFiles": [
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
|
||||
entry: './src/iframeScript.js',
|
||||
output: {
|
||||
path: path.join(__dirname, './lib'),
|
||||
@@ -43,6 +45,24 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
optimization: {
|
||||
minimizer: [
|
||||
// This code is embedded as a string, so it would never be optimized
|
||||
// elsewhere.
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
compress: {
|
||||
warnings: false,
|
||||
comparisons: false,
|
||||
},
|
||||
output: {
|
||||
comments: false,
|
||||
ascii_only: false,
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
// We set process.env.NODE_ENV to 'production' so that React is built
|
||||
@@ -51,17 +71,5 @@ module.exports = {
|
||||
// This prevents our bundled React from accidentally hijacking devtools.
|
||||
__REACT_DEVTOOLS_GLOBAL_HOOK__: '({})',
|
||||
}),
|
||||
// This code is embedded as a string, so it would never be optimized
|
||||
// elsewhere.
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false,
|
||||
comparisons: false,
|
||||
},
|
||||
output: {
|
||||
comments: false,
|
||||
ascii_only: false,
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
|
||||
entry: './src/index.js',
|
||||
output: {
|
||||
path: path.join(__dirname, './lib'),
|
||||
@@ -34,4 +35,14 @@ module.exports = {
|
||||
iframeScript$: path.resolve(__dirname, './lib/iframe-bundle.js'),
|
||||
},
|
||||
},
|
||||
optimization: {
|
||||
nodeEnv: false,
|
||||
},
|
||||
node: {
|
||||
fs: 'empty',
|
||||
process: false,
|
||||
},
|
||||
performance: {
|
||||
hints: false,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -31,21 +31,6 @@ const publicUrl = '';
|
||||
// Get environment variables to inject into our app.
|
||||
const env = getClientEnvironment(publicUrl);
|
||||
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
const postCSSLoaderOptions = {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
autoprefixer({
|
||||
flexbox: 'no-2009',
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
// style files regexes
|
||||
const cssRegex = /\.css$/;
|
||||
const cssModuleRegex = /\.module\.css$/;
|
||||
@@ -61,8 +46,21 @@ const getStyleLoaders = (cssOptions, preProcessor) => {
|
||||
options: cssOptions,
|
||||
},
|
||||
{
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: postCSSLoaderOptions,
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
autoprefixer({
|
||||
flexbox: 'no-2009',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
if (preProcessor) {
|
||||
@@ -75,6 +73,7 @@ const getStyleLoaders = (cssOptions, preProcessor) => {
|
||||
// It is focused on developer experience and fast rebuilds.
|
||||
// The production configuration is different and lives in a separate file.
|
||||
module.exports = {
|
||||
mode: 'development',
|
||||
// You may want 'eval' instead if you prefer to see the compiled output in DevTools.
|
||||
// See the discussion in https://github.com/facebook/create-react-app/issues/343.
|
||||
devtool: 'cheap-module-source-map',
|
||||
@@ -116,6 +115,18 @@ module.exports = {
|
||||
devtoolModuleFilenameTemplate: info =>
|
||||
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
|
||||
},
|
||||
optimization: {
|
||||
// Automatically split vendor and commons
|
||||
// https://twitter.com/wSokra/status/969633336732905474
|
||||
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
name: 'vendors',
|
||||
},
|
||||
// Keep the runtime chunk seperated to enable long term caching
|
||||
// https://twitter.com/wSokra/status/969679223278505985
|
||||
runtimeChunk: true,
|
||||
},
|
||||
resolve: {
|
||||
// This allows you to set a fallback for where Webpack should look for modules.
|
||||
// We placed these paths second because we want `node_modules` to "win"
|
||||
@@ -335,18 +346,16 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In development, this will be an empty string.
|
||||
new InterpolateHtmlPlugin(env.raw),
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: paths.appHtml,
|
||||
}),
|
||||
// Add module names to factory functions so they appear in browser profiler.
|
||||
new webpack.NamedModulesPlugin(),
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In development, this will be an empty string.
|
||||
new InterpolateHtmlPlugin(env.raw),
|
||||
// Makes some environment variables available to the JS code, for example:
|
||||
// if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
|
||||
new webpack.DefinePlugin(env.stringified),
|
||||
@@ -368,6 +377,7 @@ module.exports = {
|
||||
// You can remove this if you don't use Moment.js:
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
],
|
||||
|
||||
// Some libraries import Node modules but don't use them in the browser.
|
||||
// Tell Webpack to provide empty mocks for them so importing them works.
|
||||
node: {
|
||||
@@ -377,10 +387,7 @@ module.exports = {
|
||||
tls: 'empty',
|
||||
child_process: '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,
|
||||
},
|
||||
// Turn off performance processing because we utilize
|
||||
// our own hints via the FileSizeReporter
|
||||
performance: false,
|
||||
};
|
||||
|
||||
@@ -13,7 +13,8 @@ const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
||||
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
|
||||
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
|
||||
@@ -26,9 +27,6 @@ const getClientEnvironment = require('./env');
|
||||
// Webpack uses `publicPath` to determine where the app is being served from.
|
||||
// It requires a trailing slash, or the file assets will get an incorrect path.
|
||||
const publicPath = paths.servedPath;
|
||||
// Some apps do not use client-side routing with pushState.
|
||||
// For these, "homepage" can be set to "." to enable relative asset paths.
|
||||
const shouldUseRelativeAssetPaths = publicPath === './';
|
||||
// Source maps are resource heavy and can cause out of memory issue for large source files.
|
||||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
|
||||
// `publicUrl` is just like `publicPath`, but we will provide it to our app
|
||||
@@ -44,34 +42,6 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') {
|
||||
throw new Error('Production builds must have NODE_ENV=production.');
|
||||
}
|
||||
|
||||
// Note: defined here because it will be used more than once.
|
||||
const cssFilename = 'static/css/[name].[contenthash:8].css';
|
||||
|
||||
// ExtractTextPlugin expects the build output to be flat.
|
||||
// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
|
||||
// However, our output is structured with css, js and media folders.
|
||||
// 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('../') }
|
||||
: {};
|
||||
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
const postCSSLoaderOptions = {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
autoprefixer({
|
||||
flexbox: 'no-2009',
|
||||
}),
|
||||
],
|
||||
sourceMap: shouldUseSourceMap,
|
||||
};
|
||||
|
||||
// style files regexes
|
||||
const cssRegex = /\.css$/;
|
||||
const cssModuleRegex = /\.module\.css$/;
|
||||
@@ -81,13 +51,28 @@ const sassModuleRegex = /\.module\.(scss|sass)$/;
|
||||
// common function to get style loaders
|
||||
const getStyleLoaders = (cssOptions, preProcessor) => {
|
||||
const loaders = [
|
||||
MiniCssExtractPlugin.loader,
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: cssOptions,
|
||||
},
|
||||
{
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: postCSSLoaderOptions,
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
autoprefixer({
|
||||
flexbox: 'no-2009',
|
||||
}),
|
||||
],
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
];
|
||||
if (preProcessor) {
|
||||
@@ -98,26 +83,14 @@ const getStyleLoaders = (cssOptions, preProcessor) => {
|
||||
},
|
||||
});
|
||||
}
|
||||
return ExtractTextPlugin.extract(
|
||||
Object.assign(
|
||||
{
|
||||
fallback: {
|
||||
loader: require.resolve('style-loader'),
|
||||
options: {
|
||||
hmr: false,
|
||||
},
|
||||
},
|
||||
use: loaders,
|
||||
},
|
||||
extractTextPluginOptions
|
||||
)
|
||||
);
|
||||
return loaders;
|
||||
};
|
||||
|
||||
// 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 = {
|
||||
mode: 'production',
|
||||
// Don't attempt to continue if there are any errors.
|
||||
bail: true,
|
||||
// We generate sourcemaps in production. This is slow but gives good results.
|
||||
@@ -141,6 +114,58 @@ module.exports = {
|
||||
.relative(paths.appSrc, info.absoluteResourcePath)
|
||||
.replace(/\\/g, '/'),
|
||||
},
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
parse: {
|
||||
// we want uglify-js to parse ecma 8 code. However, we don't want it
|
||||
// to apply any minfication steps that turns valid ecma 5 code
|
||||
// into invalid ecma 5 code. This is why the 'compress' and 'output'
|
||||
// sections only apply transformations that are ecma 5 safe
|
||||
// https://github.com/facebook/create-react-app/pull/4234
|
||||
ecma: 8,
|
||||
},
|
||||
compress: {
|
||||
ecma: 5,
|
||||
warnings: false,
|
||||
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
||||
// https://github.com/facebook/create-react-app/issues/2376
|
||||
// Pending further investigation:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2011
|
||||
comparisons: false,
|
||||
},
|
||||
mangle: {
|
||||
safari10: true,
|
||||
},
|
||||
output: {
|
||||
ecma: 5,
|
||||
comments: false,
|
||||
// Turned on because emoji and regex is not minified properly using default
|
||||
// https://github.com/facebook/create-react-app/issues/2488
|
||||
ascii_only: true,
|
||||
},
|
||||
},
|
||||
// Use multi-process parallel running to improve the build speed
|
||||
// Default number of concurrent runs: os.cpus().length - 1
|
||||
parallel: true,
|
||||
// Enable file caching
|
||||
cache: true,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
}),
|
||||
new OptimizeCSSAssetsPlugin(),
|
||||
],
|
||||
// Automatically split vendor and commons
|
||||
// https://twitter.com/wSokra/status/969633336732905474
|
||||
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
name: 'vendors',
|
||||
},
|
||||
// Keep the runtime chunk seperated to enable long term caching
|
||||
// https://twitter.com/wSokra/status/969679223278505985
|
||||
runtimeChunk: true,
|
||||
},
|
||||
resolve: {
|
||||
// This allows you to set a fallback for where Webpack should look for modules.
|
||||
// We placed these paths second because we want `node_modules` to "win"
|
||||
@@ -284,28 +309,18 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
// 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.
|
||||
// `MiniCSSExtractPlugin` extracts styles into CSS
|
||||
// files. If you use code splitting, async bundles will have their own separate CSS chunk file.
|
||||
// By default we support CSS Modules with the extension .module.css
|
||||
{
|
||||
test: cssRegex,
|
||||
exclude: cssModuleRegex,
|
||||
loader: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
minimize: true,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
}),
|
||||
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
|
||||
},
|
||||
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
|
||||
// using the extension .module.css
|
||||
@@ -313,12 +328,10 @@ module.exports = {
|
||||
test: cssModuleRegex,
|
||||
loader: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
minimize: true,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
}),
|
||||
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
|
||||
},
|
||||
// Opt-in support for SASS. The logic here is somewhat similar
|
||||
// as in the CSS routine, except that "sass-loader" runs first
|
||||
@@ -331,12 +344,10 @@ module.exports = {
|
||||
loader: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 2,
|
||||
minimize: true,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
'sass-loader'
|
||||
),
|
||||
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
|
||||
},
|
||||
// Adds support for CSS Modules, but using SASS
|
||||
// using the extension .module.scss or .module.sass
|
||||
@@ -345,14 +356,12 @@ module.exports = {
|
||||
loader: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 2,
|
||||
minimize: true,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
},
|
||||
'sass-loader'
|
||||
),
|
||||
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
|
||||
},
|
||||
// The GraphQL loader preprocesses GraphQL queries in .graphql files.
|
||||
{
|
||||
@@ -381,12 +390,6 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In production, it will be an empty string unless you specify "homepage"
|
||||
// in `package.json`, in which case it will be the pathname of that URL.
|
||||
new InterpolateHtmlPlugin(env.raw),
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
@@ -404,52 +407,22 @@ module.exports = {
|
||||
minifyURLs: true,
|
||||
},
|
||||
}),
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In production, it will be an empty string unless you specify "homepage"
|
||||
// in `package.json`, in which case it will be the pathname of that URL.
|
||||
new InterpolateHtmlPlugin(env.raw),
|
||||
// Makes some environment variables 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(env.stringified),
|
||||
// Minify the code.
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
parse: {
|
||||
// we want uglify-js to parse ecma 8 code. However, we don't want it
|
||||
// to apply any minfication steps that turns valid ecma 5 code
|
||||
// into invalid ecma 5 code. This is why the 'compress' and 'output'
|
||||
// sections only apply transformations that are ecma 5 safe
|
||||
// https://github.com/facebook/create-react-app/pull/4234
|
||||
ecma: 8,
|
||||
},
|
||||
compress: {
|
||||
ecma: 5,
|
||||
warnings: false,
|
||||
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
||||
// https://github.com/facebook/create-react-app/issues/2376
|
||||
// Pending further investigation:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2011
|
||||
comparisons: false,
|
||||
},
|
||||
mangle: {
|
||||
safari10: true,
|
||||
},
|
||||
output: {
|
||||
ecma: 5,
|
||||
comments: false,
|
||||
// Turned on because emoji and regex is not minified properly using default
|
||||
// https://github.com/facebook/create-react-app/issues/2488
|
||||
ascii_only: true,
|
||||
},
|
||||
},
|
||||
// Use multi-process parallel running to improve the build speed
|
||||
// Default number of concurrent runs: os.cpus().length - 1
|
||||
parallel: true,
|
||||
// Enable file caching
|
||||
cache: true,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
}),
|
||||
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
|
||||
new ExtractTextPlugin({
|
||||
filename: cssFilename,
|
||||
new MiniCssExtractPlugin({
|
||||
// Options similar to the same options in webpackOptions.output
|
||||
// both options are optional
|
||||
filename: 'static/css/[name].[contenthash:8].css',
|
||||
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
|
||||
}),
|
||||
// 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
|
||||
@@ -503,4 +476,7 @@ module.exports = {
|
||||
tls: 'empty',
|
||||
child_process: 'empty',
|
||||
},
|
||||
// Turn off performance processing because we utilize
|
||||
// our own hints via the FileSizeReporter
|
||||
performance: false,
|
||||
};
|
||||
|
||||
@@ -69,7 +69,7 @@ module.exports = function(proxy, allowedHost) {
|
||||
// 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.
|
||||
// by listening to the compiler events with `compiler.hooks[...].tap` calls above.
|
||||
quiet: true,
|
||||
// Reportedly, this avoids CPU overload on some systems.
|
||||
// https://github.com/facebook/create-react-app/issues/293
|
||||
|
||||
@@ -23,56 +23,57 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "7.0.0-beta.46",
|
||||
"@babel/runtime": "7.0.0-beta.46",
|
||||
"autoprefixer": "7.2.5",
|
||||
"autoprefixer": "8.5.0",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "8.2.2",
|
||||
"babel-jest": "22.4.1",
|
||||
"babel-eslint": "8.2.3",
|
||||
"babel-jest": "22.4.3",
|
||||
"babel-loader": "8.0.0-beta.0",
|
||||
"babel-plugin-named-asset-import": "^0.1.0",
|
||||
"babel-preset-react-app": "^3.1.1",
|
||||
"case-sensitive-paths-webpack-plugin": "2.1.1",
|
||||
"chalk": "2.3.0",
|
||||
"css-loader": "0.28.9",
|
||||
"dotenv": "5.0.0",
|
||||
"case-sensitive-paths-webpack-plugin": "2.1.2",
|
||||
"chalk": "2.4.1",
|
||||
"css-loader": "0.28.11",
|
||||
"dotenv": "5.0.1",
|
||||
"dotenv-expand": "4.2.0",
|
||||
"eslint": "4.15.0",
|
||||
"eslint": "4.19.1",
|
||||
"eslint-config-react-app": "^2.1.0",
|
||||
"eslint-loader": "1.9.0",
|
||||
"eslint-plugin-flowtype": "2.41.0",
|
||||
"eslint-plugin-import": "2.8.0",
|
||||
"eslint-loader": "2.0.0",
|
||||
"eslint-plugin-flowtype": "2.46.3",
|
||||
"eslint-plugin-import": "2.11.0",
|
||||
"eslint-plugin-jsx-a11y": "6.0.3",
|
||||
"eslint-plugin-react": "7.7.0",
|
||||
"extract-text-webpack-plugin": "3.0.2",
|
||||
"file-loader": "1.1.6",
|
||||
"eslint-plugin-react": "7.8.2",
|
||||
"file-loader": "1.1.11",
|
||||
"fs-extra": "5.0.0",
|
||||
"graphql": "0.12.3",
|
||||
"graphql-tag": "2.6.1",
|
||||
"html-webpack-plugin": "2.30.1",
|
||||
"graphql": "0.13.2",
|
||||
"graphql-tag": "2.9.2",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"identity-obj-proxy": "3.0.0",
|
||||
"jest": "22.4.1",
|
||||
"loader-utils": "^1.1.0",
|
||||
"jest": "22.4.3",
|
||||
"mini-css-extract-plugin": "^0.4.0",
|
||||
"object-assign": "4.1.1",
|
||||
"postcss-flexbugs-fixes": "3.2.0",
|
||||
"postcss-loader": "2.0.10",
|
||||
"postcss-flexbugs-fixes": "3.3.1",
|
||||
"optimize-css-assets-webpack-plugin": "^4.0.1",
|
||||
"postcss-loader": "2.1.5",
|
||||
"promise": "8.0.1",
|
||||
"raf": "3.4.0",
|
||||
"react-dev-utils": "^5.0.0",
|
||||
"resolve": "1.6.0",
|
||||
"sass-loader": "7.0.1",
|
||||
"style-loader": "0.19.1",
|
||||
"style-loader": "0.21.0",
|
||||
"svgr": "1.9.2",
|
||||
"sw-precache-webpack-plugin": "0.11.4",
|
||||
"thread-loader": "1.1.2",
|
||||
"uglifyjs-webpack-plugin": "1.1.6",
|
||||
"url-loader": "0.6.2",
|
||||
"webpack": "3.10.0",
|
||||
"webpack-dev-server": "2.11.0",
|
||||
"webpack-manifest-plugin": "1.3.2",
|
||||
"whatwg-fetch": "2.0.3"
|
||||
"sw-precache-webpack-plugin": "0.11.5",
|
||||
"thread-loader": "1.1.5",
|
||||
"uglifyjs-webpack-plugin": "1.2.5",
|
||||
"url-loader": "1.0.1",
|
||||
"webpack": "4.8.3",
|
||||
"webpack-dev-server": "3.1.4",
|
||||
"webpack-manifest-plugin": "2.0.2",
|
||||
"whatwg-fetch": "2.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react": "^16.0.0",
|
||||
"react-dom": "^16.0.0"
|
||||
"react": "^16.3.2",
|
||||
"react-dom": "^16.3.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "1.2.0"
|
||||
|
||||
Reference in New Issue
Block a user