create-react-app 默认不支持less,且 webpack配置默认不可见,yarn eject 后,可以手动配置
    css支持

    1. less
    2. scss
    3. css ```jsx yarn add less less-loader —save // less 4x, less-load 11x

    // getStyleLoaders方法,增加第三个参数 preProcessorOptions const getStyleLoaders = (cssOptions, preProcessor, preProcessorOptions) { //… if (preProcessor) { loaders.push( //… { loader: require.resolve(preProcessor), options: preProcessorOptions } ); } }

    1. ```javascript
    2. 'use strict';
    3. const fs = require('fs');
    4. const path = require('path');
    5. const webpack = require('webpack');
    6. const resolve = require('resolve');
    7. const HtmlWebpackPlugin = require('html-webpack-plugin');
    8. const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
    9. const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
    10. const TerserPlugin = require('terser-webpack-plugin');
    11. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    12. const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
    13. const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
    14. const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
    15. const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
    16. const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
    17. const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
    18. const ESLintPlugin = require('eslint-webpack-plugin');
    19. const paths = require('./paths');
    20. const modules = require('./modules');
    21. const getClientEnvironment = require('./env');
    22. const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
    23. const ForkTsCheckerWebpackPlugin =
    24. process.env.TSC_COMPILE_ON_ERROR === 'true'
    25. ? require('react-dev-utils/ForkTsCheckerWarningWebpackPlugin')
    26. : require('react-dev-utils/ForkTsCheckerWebpackPlugin');
    27. const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
    28. const createEnvironmentHash = require('./webpack/persistentCache/createEnvironmentHash');
    29. // Source maps are resource heavy and can cause out of memory issue for large source files.
    30. const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
    31. const reactRefreshRuntimeEntry = require.resolve('react-refresh/runtime');
    32. const reactRefreshWebpackPluginRuntimeEntry = require.resolve(
    33. '@pmmmwh/react-refresh-webpack-plugin'
    34. );
    35. const babelRuntimeEntry = require.resolve('babel-preset-react-app');
    36. const babelRuntimeEntryHelpers = require.resolve(
    37. '@babel/runtime/helpers/esm/assertThisInitialized',
    38. { paths: [babelRuntimeEntry] }
    39. );
    40. const babelRuntimeRegenerator = require.resolve('@babel/runtime/regenerator', {
    41. paths: [babelRuntimeEntry],
    42. });
    43. const externals = require('./externals')
    44. // Some apps do not need the benefits of saving a web request, so not inlining the chunk
    45. // makes for a smoother build process.
    46. const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
    47. const emitErrorsAsWarnings = process.env.ESLINT_NO_DEV_ERRORS === 'true';
    48. const disableESLintPlugin = process.env.DISABLE_ESLINT_PLUGIN === 'true';
    49. const imageInlineSizeLimit = parseInt(
    50. process.env.IMAGE_INLINE_SIZE_LIMIT || '10000'
    51. );
    52. // Check if TypeScript is setup
    53. const useTypeScript = fs.existsSync(paths.appTsConfig);
    54. // Check if Tailwind config exists
    55. const useTailwind = fs.existsSync(
    56. path.join(paths.appPath, 'tailwind.config.js')
    57. );
    58. // Get the path to the uncompiled service worker (if it exists).
    59. const swSrc = paths.swSrc;
    60. // style files regexes
    61. const cssRegex = /\.css$/;
    62. const cssModuleRegex = /\.module\.css$/;
    63. const sassRegex = /\.(scss|sass)$/;
    64. const sassModuleRegex = /\.module\.(scss|sass)$/;
    65. const lessRegex = /\.less$/;
    66. const lessModuleRegex = /\.module\.less$/;
    67. const hasJsxRuntime = (() => {
    68. if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') {
    69. return false;
    70. }
    71. try {
    72. require.resolve('react/jsx-runtime');
    73. return true;
    74. } catch (e) {
    75. return false;
    76. }
    77. })();
    78. // This is the production and development configuration.
    79. // It is focused on developer experience, fast rebuilds, and a minimal bundle.
    80. module.exports = function (webpackEnv) {
    81. const isEnvDevelopment = webpackEnv === 'development';
    82. const isEnvProduction = webpackEnv === 'production';
    83. // Variable used for enabling profiling in Production
    84. // passed into alias object. Uses a flag if passed into the build command
    85. const isEnvProductionProfile =
    86. isEnvProduction && process.argv.includes('--profile');
    87. // We will provide `paths.publicUrlOrPath` to our app
    88. // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
    89. // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
    90. // Get environment variables to inject into our app.
    91. const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
    92. const shouldUseReactRefresh = env.raw.FAST_REFRESH;
    93. // common function to get style loaders
    94. const getStyleLoaders = (cssOptions, preProcessor, preProcessorOptions) => {
    95. const loaders = [
    96. isEnvDevelopment && require.resolve('style-loader'),
    97. isEnvProduction && {
    98. loader: MiniCssExtractPlugin.loader,
    99. // css is located in `static/css`, use '../../' to locate index.html folder
    100. // in production `paths.publicUrlOrPath` can be a relative path
    101. options: paths.publicUrlOrPath.startsWith('.')
    102. ? { publicPath: '../../' }
    103. : {},
    104. },
    105. {
    106. loader: require.resolve('css-loader'),
    107. options: cssOptions,
    108. },
    109. {
    110. // Options for PostCSS as we reference these options twice
    111. // Adds vendor prefixing based on your specified browser support in
    112. // package.json
    113. loader: require.resolve('postcss-loader'),
    114. options: {
    115. postcssOptions: {
    116. // Necessary for external CSS imports to work
    117. // https://github.com/facebook/create-react-app/issues/2677
    118. ident: 'postcss',
    119. config: false,
    120. plugins: !useTailwind
    121. ? [
    122. 'postcss-flexbugs-fixes',
    123. [
    124. 'postcss-preset-env',
    125. {
    126. autoprefixer: {
    127. flexbox: 'no-2009',
    128. },
    129. stage: 3,
    130. },
    131. ],
    132. // Adds PostCSS Normalize as the reset css with default options,
    133. // so that it honors browserslist config in package.json
    134. // which in turn let's users customize the target behavior as per their needs.
    135. 'postcss-normalize',
    136. ]
    137. : [
    138. 'tailwindcss',
    139. 'postcss-flexbugs-fixes',
    140. [
    141. 'postcss-preset-env',
    142. {
    143. autoprefixer: {
    144. flexbox: 'no-2009',
    145. },
    146. stage: 3,
    147. },
    148. ],
    149. ],
    150. },
    151. sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
    152. },
    153. },
    154. ].filter(Boolean);
    155. if (preProcessor) {
    156. loaders.push(
    157. {
    158. loader: require.resolve('resolve-url-loader'),
    159. options: {
    160. sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
    161. root: paths.appSrc,
    162. },
    163. },
    164. {
    165. loader: require.resolve(preProcessor),
    166. options: preProcessorOptions ?? { sourceMap: true },
    167. }
    168. );
    169. }
    170. return loaders;
    171. };
    172. return {
    173. target: ['browserslist'],
    174. // Webpack noise constrained to errors and warnings
    175. stats: 'errors-warnings',
    176. mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
    177. // Stop compilation early in production 打包遇到错误就停止执行
    178. bail: isEnvProduction,
    179. devtool: false,
    180. // devtool: isEnvProduction
    181. // ? shouldUseSourceMap
    182. // ? 'source-map'
    183. // : false
    184. // : isEnvDevelopment && 'cheap-module-source-map',
    185. // These are the "entry points" to our application.
    186. // This means they will be the "root" imports that are included in JS bundle.
    187. entry: paths.appIndexJs,
    188. output: {
    189. // The build folder.
    190. path: paths.appBuild,
    191. // Add /* filename */ comments to generated require()s in the output.
    192. pathinfo: isEnvDevelopment,
    193. // There will be one main bundle, and one file per asynchronous chunk.
    194. // In development, it does not produce real files.
    195. filename: 'js/[name].js',
    196. // There are also additional JS chunk files if you use code splitting.
    197. chunkFilename: 'js/[name].chunk.js',
    198. assetModuleFilename: 'media/[name].[hash][ext]',
    199. // webpack uses `publicPath` to determine where the app is being served from.
    200. // It requires a trailing slash, or the file assets will get an incorrect path.
    201. // We inferred the "public path" (such as / or /my-project) from homepage.
    202. publicPath: paths.publicUrlOrPath,
    203. // Point sourcemap entries to original disk location (format as URL on Windows)
    204. devtoolModuleFilenameTemplate: isEnvProduction
    205. ? info =>
    206. path
    207. .relative(paths.appSrc, info.absoluteResourcePath)
    208. .replace(/\\/g, '/')
    209. : isEnvDevelopment &&
    210. (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
    211. },
    212. cache: {
    213. type: 'filesystem',
    214. version: createEnvironmentHash(env.raw),
    215. cacheDirectory: paths.appWebpackCache,
    216. store: 'pack',
    217. buildDependencies: {
    218. defaultWebpack: ['webpack/lib/'],
    219. config: [__filename],
    220. tsconfig: [paths.appTsConfig, paths.appJsConfig].filter(f =>
    221. fs.existsSync(f)
    222. ),
    223. },
    224. },
    225. infrastructureLogging: {
    226. level: 'none',
    227. },
    228. optimization: {
    229. minimize: isEnvProduction,
    230. minimizer: [
    231. // This is only used in production mode
    232. new TerserPlugin({
    233. terserOptions: {
    234. parse: {
    235. // We want terser to parse ecma 8 code. However, we don't want it
    236. // to apply any minification steps that turns valid ecma 5 code
    237. // into invalid ecma 5 code. This is why the 'compress' and 'output'
    238. // sections only apply transformations that are ecma 5 safe
    239. // https://github.com/facebook/create-react-app/pull/4234
    240. ecma: 8,
    241. },
    242. compress: {
    243. ecma: 5,
    244. warnings: false,
    245. // Disabled because of an issue with Uglify breaking seemingly valid code:
    246. // https://github.com/facebook/create-react-app/issues/2376
    247. // Pending further investigation:
    248. // https://github.com/mishoo/UglifyJS2/issues/2011
    249. comparisons: false,
    250. // Disabled because of an issue with Terser breaking valid code:
    251. // https://github.com/facebook/create-react-app/issues/5250
    252. // Pending further investigation:
    253. // https://github.com/terser-js/terser/issues/120
    254. inline: 2,
    255. },
    256. mangle: {
    257. safari10: true,
    258. },
    259. // Added for profiling in devtools
    260. keep_classnames: isEnvProductionProfile,
    261. keep_fnames: isEnvProductionProfile,
    262. output: {
    263. ecma: 5,
    264. comments: false,
    265. // Turned on because emoji and regex is not minified properly using default
    266. // https://github.com/facebook/create-react-app/issues/2488
    267. ascii_only: true,
    268. },
    269. },
    270. }),
    271. // This is only used in production mode
    272. new CssMinimizerPlugin(),
    273. ],
    274. },
    275. resolve: {
    276. // This allows you to set a fallback for where webpack should look for modules.
    277. // We placed these paths second because we want `node_modules` to "win"
    278. // if there are any conflicts. This matches Node resolution mechanism.
    279. // https://github.com/facebook/create-react-app/issues/253
    280. modules: ['node_modules', paths.appNodeModules].concat(
    281. modules.additionalModulePaths || []
    282. ),
    283. // These are the reasonable defaults supported by the Node ecosystem.
    284. // We also include JSX as a common component filename extension to support
    285. // some tools, although we do not recommend using it, see:
    286. // https://github.com/facebook/create-react-app/issues/290
    287. // `web` extension prefixes have been added for better support
    288. // for React Native Web.
    289. extensions: paths.moduleFileExtensions
    290. .map(ext => `.${ext}`)
    291. .filter(ext => useTypeScript || !ext.includes('ts')),
    292. alias: {
    293. '@': path.resolve(__dirname, '../src'),
    294. // Support React Native Web
    295. // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
    296. 'react-native': 'react-native-web',
    297. // Allows for better profiling with ReactDevTools
    298. ...(isEnvProductionProfile && {
    299. 'react-dom$': 'react-dom/profiling',
    300. 'scheduler/tracing': 'scheduler/tracing-profiling',
    301. }),
    302. ...(modules.webpackAliases || {}),
    303. },
    304. plugins: [
    305. // Prevents users from importing files from outside of src/ (or node_modules/).
    306. // This often causes confusion because we only process files within src/ with babel.
    307. // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
    308. // please link the files into your node_modules/ and let module-resolution kick in.
    309. // Make sure your source files are compiled, as they will not be processed in any way.
    310. new ModuleScopePlugin(paths.appSrc, [
    311. paths.appPackageJson,
    312. reactRefreshRuntimeEntry,
    313. reactRefreshWebpackPluginRuntimeEntry,
    314. babelRuntimeEntry,
    315. babelRuntimeEntryHelpers,
    316. babelRuntimeRegenerator,
    317. ]),
    318. ],
    319. },
    320. module: {
    321. strictExportPresence: true,
    322. rules: [
    323. // Handle node_modules packages that contain sourcemaps
    324. shouldUseSourceMap && {
    325. enforce: 'pre',
    326. exclude: /@babel(?:\/|\\{1,2})runtime/,
    327. test: /\.(js|mjs|jsx|ts|tsx|css)$/,
    328. loader: require.resolve('source-map-loader'),
    329. },
    330. {
    331. // "oneOf" will traverse all following loaders until one will
    332. // match the requirements. When no loader matches it will fall
    333. // back to the "file" loader at the end of the loader list.
    334. oneOf: [
    335. // TODO: Merge this config once `image/avif` is in the mime-db
    336. // https://github.com/jshttp/mime-db
    337. {
    338. test: [/\.avif$/],
    339. type: 'asset',
    340. mimetype: 'image/avif',
    341. parser: {
    342. dataUrlCondition: {
    343. maxSize: imageInlineSizeLimit,
    344. },
    345. },
    346. },
    347. // "url" loader works like "file" loader except that it embeds assets
    348. // smaller than specified limit in bytes as data URLs to avoid requests.
    349. // A missing `test` is equivalent to a match.
    350. {
    351. test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
    352. type: 'asset',
    353. parser: {
    354. dataUrlCondition: {
    355. maxSize: imageInlineSizeLimit,
    356. },
    357. },
    358. },
    359. {
    360. test: /\.svg$/,
    361. use: [
    362. {
    363. loader: require.resolve('@svgr/webpack'),
    364. options: {
    365. prettier: false,
    366. svgo: false,
    367. svgoConfig: {
    368. plugins: [{ removeViewBox: false }],
    369. },
    370. titleProp: true,
    371. ref: true,
    372. },
    373. },
    374. {
    375. loader: require.resolve('file-loader'),
    376. options: {
    377. name: 'media/[name].[hash].[ext]',
    378. },
    379. },
    380. ],
    381. issuer: {
    382. and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
    383. },
    384. },
    385. // Process application JS with Babel.
    386. // The preset includes JSX, Flow, TypeScript, and some ESnext features.
    387. {
    388. test: /\.(js|mjs|jsx|ts|tsx)$/,
    389. include: paths.appSrc,
    390. loader: require.resolve('babel-loader'),
    391. options: {
    392. customize: require.resolve(
    393. 'babel-preset-react-app/webpack-overrides'
    394. ),
    395. presets: [
    396. [
    397. require.resolve('babel-preset-react-app'),
    398. {
    399. runtime: hasJsxRuntime ? 'automatic' : 'classic',
    400. },
    401. ],
    402. ],
    403. plugins: [
    404. isEnvDevelopment &&
    405. shouldUseReactRefresh &&
    406. require.resolve('react-refresh/babel'),
    407. ].filter(Boolean),
    408. // This is a feature of `babel-loader` for webpack (not Babel itself).
    409. // It enables caching results in ./node_modules/.cache/babel-loader/
    410. // directory for faster rebuilds.
    411. cacheDirectory: true,
    412. // See #6846 for context on why cacheCompression is disabled
    413. cacheCompression: false,
    414. compact: isEnvProduction,
    415. },
    416. },
    417. // Process any JS outside of the app with Babel.
    418. // Unlike the application JS, we only compile the standard ES features.
    419. {
    420. test: /\.(js|mjs)$/,
    421. exclude: /@babel(?:\/|\\{1,2})runtime/,
    422. loader: require.resolve('babel-loader'),
    423. options: {
    424. babelrc: false,
    425. configFile: false,
    426. compact: false,
    427. presets: [
    428. [
    429. require.resolve('babel-preset-react-app/dependencies'),
    430. { helpers: true },
    431. ],
    432. ],
    433. cacheDirectory: true,
    434. // See #6846 for context on why cacheCompression is disabled
    435. cacheCompression: false,
    436. // Babel sourcemaps are needed for debugging into node_modules
    437. // code. Without the options below, debuggers like VSCode
    438. // show incorrect code and set breakpoints on the wrong lines.
    439. sourceMaps: shouldUseSourceMap,
    440. inputSourceMap: shouldUseSourceMap,
    441. },
    442. },
    443. // "postcss" loader applies autoprefixer to our CSS.
    444. // "css" loader resolves paths in CSS and adds assets as dependencies.
    445. // "style" loader turns CSS into JS modules that inject <style> tags.
    446. // In production, we use MiniCSSExtractPlugin to extract that CSS
    447. // to a file, but in development "style" loader enables hot editing
    448. // of CSS.
    449. // By default we support CSS Modules with the extension .module.css
    450. {
    451. test: cssRegex,
    452. exclude: cssModuleRegex,
    453. use: getStyleLoaders({
    454. importLoaders: 1,
    455. sourceMap: isEnvProduction
    456. ? shouldUseSourceMap
    457. : isEnvDevelopment,
    458. modules: {
    459. mode: 'icss',
    460. },
    461. }),
    462. // Don't consider CSS imports dead code even if the
    463. // containing package claims to have no side effects.
    464. // Remove this when webpack adds a warning or an error for this.
    465. // See https://github.com/webpack/webpack/issues/6571
    466. sideEffects: true,
    467. },
    468. // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
    469. // using the extension .module.css
    470. {
    471. test: cssModuleRegex,
    472. use: getStyleLoaders({
    473. importLoaders: 1,
    474. sourceMap: isEnvProduction
    475. ? shouldUseSourceMap
    476. : isEnvDevelopment,
    477. modules: {
    478. mode: 'local',
    479. getLocalIdent: getCSSModuleLocalIdent,
    480. },
    481. }),
    482. },
    483. // Opt-in support for SASS (using .scss or .sass extensions).
    484. // By default we support SASS Modules with the
    485. // extensions .module.scss or .module.sass
    486. {
    487. test: sassRegex,
    488. exclude: sassModuleRegex,
    489. use: getStyleLoaders(
    490. {
    491. importLoaders: 3,
    492. sourceMap: isEnvProduction
    493. ? shouldUseSourceMap
    494. : isEnvDevelopment,
    495. modules: {
    496. mode: 'icss',
    497. },
    498. },
    499. 'sass-loader'
    500. ),
    501. // Don't consider CSS imports dead code even if the
    502. // containing package claims to have no side effects.
    503. // Remove this when webpack adds a warning or an error for this.
    504. // See https://github.com/webpack/webpack/issues/6571
    505. sideEffects: true,
    506. },
    507. // Adds support for CSS Modules, but using SASS
    508. // using the extension .module.scss or .module.sass
    509. {
    510. test: sassModuleRegex,
    511. use: getStyleLoaders(
    512. {
    513. importLoaders: 3,
    514. sourceMap: isEnvProduction
    515. ? shouldUseSourceMap
    516. : isEnvDevelopment,
    517. modules: {
    518. mode: 'local',
    519. getLocalIdent: getCSSModuleLocalIdent,
    520. },
    521. },
    522. 'sass-loader'
    523. ),
    524. },
    525. // extensions .module.less or .module.less
    526. {
    527. test: lessRegex,
    528. exclude: sassModuleRegex,
    529. use: getStyleLoaders(
    530. {
    531. importLoaders: 3,
    532. sourceMap: isEnvProduction
    533. ? shouldUseSourceMap
    534. : isEnvDevelopment,
    535. },
    536. 'less-loader',
    537. {
    538. sourceMap: true,
    539. lessOptions: {
    540. javascriptEnabled: true // less javascriptEnabled参数
    541. }
    542. }
    543. ),
    544. // Don't consider CSS imports dead code even if the
    545. // containing package claims to have no side effects.
    546. // Remove this when webpack adds a warning or an error for this.
    547. // See https://github.com/webpack/webpack/issues/6571
    548. sideEffects: true,
    549. },
    550. // Adds support for CSS Modules, but using SASS
    551. // using the extension .module.scss or .module.sass
    552. {
    553. test: lessModuleRegex,
    554. use: getStyleLoaders(
    555. {
    556. importLoaders: 3,
    557. sourceMap: isEnvProduction
    558. ? shouldUseSourceMap
    559. : isEnvDevelopment,
    560. modules: {
    561. mode: 'local',
    562. getLocalIdent: getCSSModuleLocalIdent,
    563. },
    564. },
    565. 'less-loader',
    566. {
    567. sourceMap: true,
    568. lessOptions: {
    569. javascriptEnabled: true // less javascriptEnabled参数
    570. }
    571. }
    572. ),
    573. },
    574. // "file" loader makes sure those assets get served by WebpackDevServer.
    575. // When you `import` an asset, you get its (virtual) filename.
    576. // In production, they would get copied to the `build` folder.
    577. // This loader doesn't use a "test" so it will catch all modules
    578. // that fall through the other loaders.
    579. {
    580. // Exclude `js` files to keep "css" loader working as it injects
    581. // its runtime that would otherwise be processed through "file" loader.
    582. // Also exclude `html` and `json` extensions so they get processed
    583. // by webpacks internal loaders.
    584. exclude: [/^$/, /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
    585. type: 'asset/resource',
    586. },
    587. // ** STOP ** Are you adding a new loader?
    588. // Make sure to add the new loader(s) before the "file" loader.
    589. ],
    590. },
    591. ].filter(Boolean),
    592. },
    593. plugins: [
    594. // Generates an `index.html` file with the <script> injected.
    595. new HtmlWebpackPlugin(
    596. Object.assign(
    597. {},
    598. {
    599. inject: true,
    600. template: paths.appHtml, // 模板名
    601. filename: 'index.html', // 文件名
    602. },
    603. isEnvProduction
    604. ? {
    605. minify: {
    606. removeComments: true,
    607. collapseWhitespace: true,
    608. removeRedundantAttributes: true,
    609. useShortDoctype: true,
    610. removeEmptyAttributes: true,
    611. removeStyleLinkTypeAttributes: true,
    612. keepClosingSlash: true,
    613. minifyJS: true,
    614. minifyCSS: true,
    615. minifyURLs: true,
    616. },
    617. }
    618. : undefined
    619. )
    620. ),
    621. // Inlines the webpack runtime script. This script is too small to warrant
    622. // a network request.
    623. // https://github.com/facebook/create-react-app/issues/5358
    624. isEnvProduction &&
    625. shouldInlineRuntimeChunk &&
    626. new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
    627. // Makes some environment variables available in index.html.
    628. // The public URL is available as %PUBLIC_URL% in index.html, e.g.:
    629. // <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
    630. // It will be an empty string unless you specify "homepage"
    631. // in `package.json`, in which case it will be the pathname of that URL.
    632. new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
    633. // This gives some necessary context to module not found errors, such as
    634. // the requesting resource.
    635. new ModuleNotFoundPlugin(paths.appPath),
    636. // Makes some environment variables available to the JS code, for example:
    637. // if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
    638. // It is absolutely essential that NODE_ENV is set to production
    639. // during a production build.
    640. // Otherwise React will be compiled in the very slow development mode.
    641. new webpack.DefinePlugin(env.stringified),
    642. // Experimental hot reloading for React .
    643. // https://github.com/facebook/react/tree/main/packages/react-refresh
    644. isEnvDevelopment &&
    645. shouldUseReactRefresh &&
    646. new ReactRefreshWebpackPlugin({
    647. overlay: false,
    648. }),
    649. // Watcher doesn't work well if you mistype casing in a path so we use
    650. // a plugin that prints an error when you attempt to do this.
    651. // See https://github.com/facebook/create-react-app/issues/240
    652. isEnvDevelopment && new CaseSensitivePathsPlugin(),
    653. isEnvProduction &&
    654. new MiniCssExtractPlugin({
    655. // Options similar to the same options in webpackOptions.output
    656. // both options are optional
    657. // filename: 'static/css/[name].[contenthash:8].css',
    658. filename: 'css/index.css',
    659. chunkFilename: 'css/[name].chunk.css',
    660. }),
    661. // Generate an asset manifest file with the following content:
    662. // - "files" key: Mapping of all asset filenames to their corresponding
    663. // output file so that tools can pick it up without having to parse
    664. // `index.html`
    665. // - "entrypoints" key: Array of files which are included in `index.html`,
    666. // can be used to reconstruct the HTML if necessary
    667. new WebpackManifestPlugin({
    668. fileName: 'asset-manifest.json',
    669. publicPath: paths.publicUrlOrPath,
    670. generate: (seed, files, entrypoints) => {
    671. const manifestFiles = files.reduce((manifest, file) => {
    672. manifest[file.name] = file.path;
    673. return manifest;
    674. }, seed);
    675. const entrypointFiles = entrypoints.main.filter(
    676. fileName => !fileName.endsWith('.map')
    677. );
    678. return {
    679. files: manifestFiles,
    680. entrypoints: entrypointFiles,
    681. };
    682. },
    683. }),
    684. // Moment.js is an extremely popular library that bundles large locale files
    685. // by default due to how webpack interprets its code. This is a practical
    686. // solution that requires the user to opt into importing specific locales.
    687. // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
    688. // You can remove this if you don't use Moment.js:
    689. new webpack.IgnorePlugin({
    690. resourceRegExp: /^\.\/locale$/,
    691. contextRegExp: /moment$/,
    692. }),
    693. // Generate a service worker script that will precache, and keep up to date,
    694. // the HTML & assets that are part of the webpack build.
    695. isEnvProduction &&
    696. fs.existsSync(swSrc) &&
    697. new WorkboxWebpackPlugin.InjectManifest({
    698. swSrc,
    699. dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
    700. exclude: [/\.map$/, /asset-manifest\.json$/, /LICENSE/],
    701. // Bump up the default maximum size (2mb) that's precached,
    702. // to make lazy-loading failure scenarios less likely.
    703. // See https://github.com/cra-template/pwa/issues/13#issuecomment-722667270
    704. maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
    705. }),
    706. // TypeScript type checking
    707. useTypeScript &&
    708. new ForkTsCheckerWebpackPlugin({
    709. async: isEnvDevelopment,
    710. typescript: {
    711. typescriptPath: resolve.sync('typescript', {
    712. basedir: paths.appNodeModules,
    713. }),
    714. configOverwrite: {
    715. compilerOptions: {
    716. sourceMap: isEnvProduction
    717. ? shouldUseSourceMap
    718. : isEnvDevelopment,
    719. skipLibCheck: true,
    720. inlineSourceMap: false,
    721. declarationMap: false,
    722. noEmit: true,
    723. incremental: true,
    724. tsBuildInfoFile: paths.appTsBuildInfoFile,
    725. },
    726. },
    727. context: paths.appPath,
    728. diagnosticOptions: {
    729. syntactic: true,
    730. },
    731. mode: 'write-references',
    732. // profile: true,
    733. },
    734. issue: {
    735. // This one is specifically to match during CI tests,
    736. // as micromatch doesn't match
    737. // '../cra-template-typescript/template/src/App.tsx'
    738. // otherwise.
    739. include: [
    740. { file: '../**/src/**/*.{ts,tsx}' },
    741. { file: '**/src/**/*.{ts,tsx}' },
    742. ],
    743. exclude: [
    744. { file: '**/src/**/__tests__/**' },
    745. { file: '**/src/**/?(*.){spec|test}.*' },
    746. { file: '**/src/setupProxy.*' },
    747. { file: '**/src/setupTests.*' },
    748. ],
    749. },
    750. logger: {
    751. infrastructure: 'silent',
    752. },
    753. }),
    754. !disableESLintPlugin &&
    755. new ESLintPlugin({
    756. // Plugin options
    757. extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'],
    758. formatter: require.resolve('react-dev-utils/eslintFormatter'),
    759. eslintPath: require.resolve('eslint'),
    760. failOnError: !(isEnvDevelopment && emitErrorsAsWarnings),
    761. context: paths.appSrc,
    762. cache: true,
    763. cacheLocation: path.resolve(
    764. paths.appNodeModules,
    765. '.cache/.eslintcache'
    766. ),
    767. // ESLint class options
    768. cwd: paths.appPath,
    769. resolvePluginsRelativeTo: __dirname,
    770. baseConfig: {
    771. extends: [require.resolve('eslint-config-react-app/base')],
    772. rules: {
    773. ...(!hasJsxRuntime && {
    774. 'react/react-in-jsx-scope': 'error',
    775. }),
    776. },
    777. },
    778. }),
    779. ].filter(Boolean),
    780. // Turn off performance processing because we utilize
    781. // our own hints via the FileSizeReporter
    782. performance: false,
    783. externals,
    784. };
    785. };

    webpack.config.js配置参考
    https://www.cnblogs.com/Im-Victor/p/16347144.html