loaders.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. const paths = require('./paths');
  2. const tsImportPluginFactory = require('ts-import-plugin');
  3. const ExtractTextPlugin = require('extract-text-webpack-plugin');
  4. const autoprefixer = require('autoprefixer')({
  5. browsers: [
  6. '>1%',
  7. 'last 4 versions',
  8. 'Firefox ESR',
  9. 'not ie < 9', // React doesn't support IE8 anyway
  10. ],
  11. flexbox: 'no-2009',
  12. });
  13. const precss = require('precss')();
  14. const flexBugFixes = require('postcss-flexbugs-fixes')();
  15. // Webpack uses `publicPath` to determine where the app is being served from.
  16. // It requires a trailing slash, or the file assets will get an incorrect path.
  17. const publicPath = paths.servedPath;
  18. // Some apps do not use client-side routing with pushState.
  19. // For these, "homepage" can be set to "." to enable relative asset paths.
  20. const shouldUseRelativeAssetPaths = publicPath === './';
  21. // Source maps are resource heavy and can cause out of memory issue for large source files.
  22. const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP === 'true';
  23. // Note: defined here because it will be used more than once.
  24. const cssFilename = 'static/css/[name].[contenthash:8].css';
  25. // ExtractTextPlugin expects the build output to be flat.
  26. // (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
  27. // However, our output is structured with css, js and media folders.
  28. // To have this structure working with relative paths, we have to use custom options.
  29. const extractTextPluginOptions = shouldUseRelativeAssetPaths
  30. ? // Making sure that the publicPath goes back to to build folder.
  31. { publicPath: Array(cssFilename.split('/').length).join('../') }
  32. : {};
  33. // "url" loader works like "file" loader except that it embeds assets
  34. // smaller than specified limit in bytes as data URLs to avoid requests.
  35. // A missing `test` is equivalent to a match.
  36. const urlLoader = {
  37. test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
  38. loader: require.resolve('url-loader'),
  39. options: {
  40. limit: 2048,
  41. name: 'static/media/[name].[hash:8].[ext]',
  42. },
  43. };
  44. const importPluginOption = [
  45. {
  46. libraryName: 'antd',
  47. libraryDirectory: 'lib',
  48. style: 'css'
  49. },
  50. {
  51. libraryName: 'antd-mobile',
  52. libraryDirectory: 'lib',
  53. style: 'css',
  54. }
  55. ];
  56. // js loader
  57. const jsLoader = {
  58. test: /\.(js|jsx|mjs)$/,
  59. include: paths.appSrc,
  60. loader: require.resolve('babel-loader'),
  61. options: {
  62. compact: true,
  63. },
  64. };
  65. // ts loader
  66. const tsLoader = {
  67. test: /\.(ts|tsx)$/,
  68. include: paths.appSrc,
  69. use: [
  70. {
  71. loader: require.resolve('ts-loader'),
  72. options: {
  73. transpileOnly: true,
  74. getCustomTransformers: () => ({
  75. before: [tsImportPluginFactory(importPluginOption)]
  76. })
  77. }
  78. }
  79. ]
  80. };
  81. const postcssLoader = {
  82. loader: require.resolve('postcss-loader'),
  83. options: {
  84. // Necessary for external CSS imports to work
  85. // https://github.com/facebookincubator/create-react-app/issues/2677
  86. // don't need now
  87. // ident: 'postcss',
  88. plugins: () => [
  89. flexBugFixes,
  90. autoprefixer
  91. ],
  92. },
  93. };
  94. const precssLoader = {
  95. loader: require.resolve('postcss-loader'),
  96. options: {
  97. // Necessary for external CSS imports to work
  98. // https://github.com/facebookincubator/create-react-app/issues/2677
  99. // don't need now
  100. // ident: 'postcss',
  101. plugins: () => [
  102. precss,
  103. flexBugFixes,
  104. autoprefixer
  105. ],
  106. },
  107. };
  108. const rawCssLoaderDev = {
  109. loader: require.resolve('css-loader'),
  110. options: {
  111. importLoaders: 1,
  112. },
  113. };
  114. const rawCssLoaderProd = {
  115. loader: require.resolve('css-loader'),
  116. options: {
  117. importLoaders: 1,
  118. minimize: true,
  119. sourceMap: shouldUseSourceMap,
  120. },
  121. };
  122. const cssLoaderDev = {
  123. test: /\.css$/,
  124. use: [
  125. require.resolve('style-loader'),
  126. rawCssLoaderDev,
  127. postcssLoader,
  128. ],
  129. };
  130. const cssLoaderProd = {
  131. test: /\.css$/,
  132. loader: ExtractTextPlugin.extract(
  133. Object.assign(
  134. {
  135. fallback: require.resolve('style-loader'),
  136. use: [
  137. rawCssLoaderProd,
  138. postcssLoader,
  139. ],
  140. },
  141. extractTextPluginOptions
  142. )
  143. ),
  144. // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
  145. };
  146. // scss loader
  147. const scssLoaderDev = {
  148. test: /\.scss$/,
  149. use: [
  150. require.resolve('style-loader'),
  151. rawCssLoaderDev,
  152. precssLoader,
  153. ],
  154. };
  155. const scssLoaderProd = {
  156. test: /\.scss$/,
  157. loader: ExtractTextPlugin.extract(
  158. Object.assign(
  159. {
  160. fallback: require.resolve('style-loader'),
  161. use: [
  162. rawCssLoaderProd,
  163. precssLoader,
  164. ],
  165. },
  166. extractTextPluginOptions
  167. )
  168. )
  169. };
  170. // less loader
  171. const lessLoaderDev = {
  172. test: /\.less$/,
  173. use: [
  174. require.resolve('style-loader'),
  175. rawCssLoaderDev,
  176. postcssLoader,
  177. require.resolve('less-loader')
  178. ],
  179. };
  180. const lessLoaderProd = {
  181. test: /\.less$/,
  182. loader: ExtractTextPlugin.extract(
  183. Object.assign(
  184. {
  185. fallback: require.resolve('style-loader'),
  186. use: [
  187. rawCssLoaderProd,
  188. postcssLoader,
  189. require.resolve('less-loader')
  190. ],
  191. },
  192. extractTextPluginOptions
  193. )
  194. )
  195. };
  196. // Exclude `js` files to keep "css" loader working as it injects
  197. // it's runtime that would otherwise processed through "file" loader.
  198. // Also exclude `html` and `json` extensions so they get processed
  199. // by webpacks internal loaders.
  200. const fileLoader = {
  201. loader: require.resolve('file-loader'),
  202. // Exclude `js` files to keep "css" loader working as it injects
  203. // it's runtime that would otherwise processed through "file" loader.
  204. // Also exclude `html` and `json` extensions so they get processed
  205. // by webpacks internal loaders.
  206. exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
  207. options: {
  208. name: 'static/media/[name].[hash:8].[ext]',
  209. },
  210. };
  211. module.exports = {
  212. urlLoader,
  213. jsLoader,
  214. tsLoader,
  215. cssLoaderDev,
  216. cssLoaderProd,
  217. scssLoaderDev,
  218. scssLoaderProd,
  219. lessLoaderDev,
  220. lessLoaderProd,
  221. fileLoader,
  222. postcssLoader
  223. };