webpack.config.prod.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. 'use strict';
  2. var autoprefixer = require('autoprefixer');
  3. var webpack = require('webpack');
  4. var HtmlWebpackPlugin = require('html-webpack-plugin');
  5. var ExtractTextPlugin = require('extract-text-webpack-plugin');
  6. var ManifestPlugin = require('webpack-manifest-plugin');
  7. var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
  8. var paths = require('./paths');
  9. var getClientEnvironment = require('./env');
  10. // Webpack uses `publicPath` to determine where the app is being served from.
  11. // It requires a trailing slash, or the file assets will get an incorrect path.
  12. var publicPath = paths.servedPath;
  13. // Some apps do not use client-side routing with pushState.
  14. // For these, "homepage" can be set to "." to enable relative asset paths.
  15. var shouldUseRelativeAssetPaths = publicPath === './';
  16. // `publicUrl` is just like `publicPath`, but we will provide it to our app
  17. // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
  18. // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
  19. var publicUrl = publicPath.slice(0, -1);
  20. // Get environment variables to inject into our app.
  21. var env = getClientEnvironment(publicUrl);
  22. // Assert this just to be safe.
  23. // Development builds of React are slow and not intended for production.
  24. if (env.stringified['process.env'].NODE_ENV !== '"production"') {
  25. throw new Error('Production builds must have NODE_ENV=production.');
  26. }
  27. // Note: defined here because it will be used more than once.
  28. const cssFilename = 'static/css/[name].[contenthash:8].css';
  29. // ExtractTextPlugin expects the build output to be flat.
  30. // (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
  31. // However, our output is structured with css, js and media folders.
  32. // To have this structure working with relative paths, we have to use custom options.
  33. const extractTextPluginOptions = shouldUseRelativeAssetPaths
  34. // Making sure that the publicPath goes back to to build folder.
  35. ? { publicPath: Array(cssFilename.split('/').length).join('../') }
  36. : undefined;
  37. // This is the production configuration.
  38. // It compiles slowly and is focused on producing a fast and minimal bundle.
  39. // The development configuration is different and lives in a separate file.
  40. module.exports = {
  41. // Don't attempt to continue if there are any errors.
  42. bail: true,
  43. // We generate sourcemaps in production. This is slow but gives good results.
  44. // You can exclude the *.map files from the build during deployment.
  45. devtool: 'source-map',
  46. // In production, we only want to load the polyfills and the app code.
  47. entry: [
  48. require.resolve('./polyfills'),
  49. paths.appIndexJs
  50. ],
  51. output: {
  52. // The build folder.
  53. path: paths.appBuild,
  54. // Generated JS file names (with nested folders).
  55. // There will be one main bundle, and one file per asynchronous chunk.
  56. // We don't currently advertise code splitting but Webpack supports it.
  57. filename: 'static/js/[name].[chunkhash:8].js',
  58. chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js',
  59. // We inferred the "public path" (such as / or /my-project) from homepage.
  60. publicPath: publicPath
  61. },
  62. resolve: {
  63. // This allows you to set a fallback for where Webpack should look for modules.
  64. // We read `NODE_PATH` environment variable in `paths.js` and pass paths here.
  65. // We use `fallback` instead of `root` because we want `node_modules` to "win"
  66. // if there any conflicts. This matches Node resolution mechanism.
  67. // https://github.com/facebookincubator/create-react-app/issues/253
  68. fallback: paths.nodePaths,
  69. // These are the reasonable defaults supported by the Node ecosystem.
  70. // We also include JSX as a common component filename extension to support
  71. // some tools, although we do not recommend using it, see:
  72. // https://github.com/facebookincubator/create-react-app/issues/290
  73. extensions: ['.js', '.json', '.jsx', ''],
  74. alias: {
  75. // Support React Native Web
  76. // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
  77. 'react-native': 'react-native-web',
  78. components: `../src/components`,
  79. }
  80. },
  81. module: {
  82. // First, run the linter.
  83. // It's important to do this before Babel processes the JS.
  84. preLoaders: [
  85. {
  86. test: /\.(js|jsx)$/,
  87. loader: 'eslint',
  88. include: paths.appSrc
  89. }
  90. ],
  91. loaders: [
  92. // ** ADDING/UPDATING LOADERS **
  93. // The "url" loader handles all assets unless explicitly excluded.
  94. // The `exclude` list *must* be updated with every change to loader extensions.
  95. // When adding a new loader, you must add its `test`
  96. // as a new entry in the `exclude` list in the "url" loader.
  97. // "url" loader embeds assets smaller than specified size as data URLs to avoid requests.
  98. // Otherwise, it acts like the "file" loader.
  99. {
  100. exclude: [
  101. /\.html$/,
  102. /\.(js|jsx)$/,
  103. /\.css$/,
  104. /\.json$/,
  105. /\.svg$/
  106. ],
  107. loader: 'url',
  108. query: {
  109. limit: 10000,
  110. name: 'static/media/[name].[hash:8].[ext]'
  111. }
  112. },
  113. // Process JS with Babel.
  114. {
  115. test: /\.(js|jsx)$/,
  116. include: paths.appSrc,
  117. loader: 'babel',
  118. query: {
  119. plugins: [
  120. ['import', [{ libraryName: "antd", style: 'css' }]],
  121. ],
  122. }
  123. },
  124. // The notation here is somewhat confusing.
  125. // "postcss" loader applies autoprefixer to our CSS.
  126. // "css" loader resolves paths in CSS and adds assets as dependencies.
  127. // "style" loader normally turns CSS into JS modules injecting <style>,
  128. // but unlike in development configuration, we do something different.
  129. // `ExtractTextPlugin` first applies the "postcss" and "css" loaders
  130. // (second argument), then grabs the result CSS and puts it into a
  131. // separate file in our build process. This way we actually ship
  132. // a single CSS file in production instead of JS code injecting <style>
  133. // tags. If you use code splitting, however, any async bundles will still
  134. // use the "style" loader inside the async code so CSS from them won't be
  135. // in the main CSS file.
  136. {
  137. test: /\.css$/,
  138. loader: ExtractTextPlugin.extract(
  139. 'style',
  140. 'css?importLoaders=1!postcss',
  141. extractTextPluginOptions
  142. )
  143. // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
  144. },
  145. // JSON is not enabled by default in Webpack but both Node and Browserify
  146. // allow it implicitly so we also enable it.
  147. {
  148. test: /\.json$/,
  149. loader: 'json'
  150. },
  151. // "file" loader for svg
  152. {
  153. test: /\.svg$/,
  154. loader: 'file',
  155. query: {
  156. name: 'static/media/[name].[hash:8].[ext]'
  157. }
  158. }
  159. // ** STOP ** Are you adding a new loader?
  160. // Remember to add the new extension(s) to the "url" loader exclusion list.
  161. ]
  162. },
  163. // We use PostCSS for autoprefixing only.
  164. postcss: function() {
  165. return [
  166. autoprefixer({
  167. browsers: [
  168. '>1%',
  169. 'last 4 versions',
  170. 'Firefox ESR',
  171. 'not ie < 9', // React doesn't support IE8 anyway
  172. ]
  173. }),
  174. ];
  175. },
  176. plugins: [
  177. // Makes some environment variables available in index.html.
  178. // The public URL is available as %PUBLIC_URL% in index.html, e.g.:
  179. // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
  180. // In production, it will be an empty string unless you specify "homepage"
  181. // in `package.json`, in which case it will be the pathname of that URL.
  182. new InterpolateHtmlPlugin(env.raw),
  183. // Generates an `index.html` file with the <script> injected.
  184. new HtmlWebpackPlugin({
  185. inject: true,
  186. template: paths.appHtml,
  187. minify: {
  188. removeComments: true,
  189. collapseWhitespace: true,
  190. removeRedundantAttributes: true,
  191. useShortDoctype: true,
  192. removeEmptyAttributes: true,
  193. removeStyleLinkTypeAttributes: true,
  194. keepClosingSlash: true,
  195. minifyJS: true,
  196. minifyCSS: true,
  197. minifyURLs: true
  198. }
  199. }),
  200. // Makes some environment variables available to the JS code, for example:
  201. // if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
  202. // It is absolutely essential that NODE_ENV was set to production here.
  203. // Otherwise React will be compiled in the very slow development mode.
  204. new webpack.DefinePlugin(env.stringified),
  205. // This helps ensure the builds are consistent if source hasn't changed:
  206. new webpack.optimize.OccurrenceOrderPlugin(),
  207. // Try to dedupe duplicated modules, if any:
  208. new webpack.optimize.DedupePlugin(),
  209. // Minify the code.
  210. new webpack.optimize.UglifyJsPlugin({
  211. compress: {
  212. screw_ie8: true, // React doesn't support IE8
  213. warnings: false
  214. },
  215. mangle: {
  216. screw_ie8: true
  217. },
  218. output: {
  219. comments: false,
  220. screw_ie8: true
  221. }
  222. }),
  223. // Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
  224. new ExtractTextPlugin(cssFilename),
  225. // Generate a manifest file which contains a mapping of all asset filenames
  226. // to their corresponding output file so that tools can pick it up without
  227. // having to parse `index.html`.
  228. new ManifestPlugin({
  229. fileName: 'asset-manifest.json'
  230. })
  231. ],
  232. // Some libraries import Node modules but don't use them in the browser.
  233. // Tell Webpack to provide empty mocks for them so importing them works.
  234. node: {
  235. fs: 'empty',
  236. net: 'empty',
  237. tls: 'empty'
  238. }
  239. };