苦海学说

Personal Blog
Exchange Learning

搭建react项目(二):配置webpack相关

1、编辑webpack.config.js,安装相关依赖:(ps.复用react-scripts/config/webpack.config.js)

npm i -D html-webpack-plugin case-sensitive-paths-webpack-plugin react-dev-utils mini-css-extract-plugin optimize-css-assets-webpack-plugin @babel/core @babel/plugin-proposal-class-properties @babel/preset-env @babel/preset-react babel-loader babel-plugin-named-asset-import case-sensitive-paths-webpack-plugin css-loader dotenv dotenv-expand eslint eslint-loader eslint-plugin-react file-loader less less-loader postcss-flexbugs-fixes postcss-loader postcss-normalize postcss-preset-env postcss-safe-parser react-dev-utils resolve-url-loader style-loader terser-webpack-plugin@2.3.8 url-loader eslint-webpack-plugin

1.1、编辑webpack.config.js:

const PnpWebpackPlugin = require('pnp-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const paths = require('./paths');
const plugins = require('./plugins');
const devServer = require('./devServer');

const postcssNormalize = require('postcss-normalize');

const appPackageJson = require(paths.appPackageJson);

//源映射是资源密集型的,可能会导致大型源文件的内存不足问题。
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';

const reactRefreshOverlayEntry = require.resolve('react-dev-utils/refreshOverlayInterop');

const isEnvDevelopment = process.env.NODE_ENV === 'development';
const isEnvProduction = process.env.NODE_ENV === 'production';
//用于在生产中启用分析的变量
//传入alias对象。如果传递到生成命令中,则使用标志
const isEnvProductionProfile = isEnvProduction && process.argv.includes('--profile');

//样式文件正则表达式
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;

//获取样式加载器的通用函数
const getStyleLoaders = (cssOptions, preProcessor) => {
  const loaders = [
    isEnvDevelopment && require.resolve('style-loader'),
    isEnvProduction && {
      loader: MiniCssExtractPlugin.loader,
      //css位于“static/css”中,使用“../../”定位索引.html文件夹
      //生产中`路径.publicUrlOrPath`可以是相对路径
      options: paths.publicUrlOrPath.startsWith('.') ? { publicPath: '../../' } : {}
    },
    {
      loader: require.resolve('css-loader'),
      options: cssOptions
    },
    {
      //邮政编码选项,因为我们引用这些选项两次
      //根据中指定的浏览器支持添加供应商前缀
      // 包.json
      loader: require.resolve('postcss-loader'),
      options: {
        //外部CSS导入工作所必需的
        // https://github.com/facebook/create-react-app/issues/2677
        ident: 'postcss',
        plugins: () => [
          require('postcss-flexbugs-fixes'),
          require('postcss-preset-env')({
            autoprefixer: {
              flexbox: 'no-2009'
            },
            stage: 3
          }),
          //添加postcs Normalize作为带有默认选项的重置css,
          //所以它尊重浏览器列表配置包.json
          //反过来,用户可以根据自己的需要定制目标行为。
          postcssNormalize()
        ],
        sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment
      }
    }
  ].filter(Boolean);
  if (preProcessor) {
    loaders.push(
      {
        loader: require.resolve('resolve-url-loader'),
        options: {
          sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
          root: paths.appSrc
        }
      },
      {
        loader: require.resolve(preProcessor),
        options: {
          sourceMap: true
        }
      }
    );
  }
  return loaders;
};

//这是生产和开发配置。
//它关注于开发人员的体验、快速重建和最小的捆绑包
module.exports = {
  mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
  //在生产初期停止编译
  bail: isEnvProduction,
  devtool: isEnvProduction
    ? shouldUseSourceMap
      ? 'source-map'
      : false
    : isEnvDevelopment && 'cheap-module-source-map',
  //这些是我们应用程序的“入口点”。
  //这意味着它们将是JS包中包含的“根”导入。
  entry: paths.appIndexJs,
  output: {
    //生成文件夹。
    path: isEnvProduction ? paths.appBuild : undefined,
    //将/*filename*/comments添加到输出中生成的require()s中。
    pathinfo: isEnvDevelopment,
    //将有一个主包,每个异步块有一个文件。
    //在开发过程中,它不会生成真正的文件。
    filename: isEnvProduction
      ? 'static/js/[name].[contenthash:8].js'
      : isEnvDevelopment && 'static/js/bundle.js',
    //如果使用代码拆分,还有其他JS块文件。
    chunkFilename: isEnvProduction
      ? 'static/js/[name].[contenthash:8].chunk.js'
      : isEnvDevelopment && 'static/js/[name].chunk.js',
    //webpack使用“publicPath”确定应用程序从何处获得服务。
    //它需要一个尾部斜杠,否则文件资源将获得不正确的路径。
    //我们从主页推断出“公共路径”(例如/或/我的项目)。
    publicPath: paths.publicUrlOrPath,
    //防止多个Web包运行时发生冲突(来自不同的应用程序)
    //在同一页上使用。
    jsonpFunction: `webpackJsonp${appPackageJson.name}`,
    //默认为“窗口”,但如果将其设置为“此”,则
    //构建的模块块也可以在webworkers中工作。
    globalObject: 'this'
  },
  optimization: {
    minimize: isEnvProduction,
    minimizer: [
      //仅在生产模式下使用
      new TerserPlugin({
        terserOptions: {
          parse: {
            //我们希望terser解析ecma8代码。但是,我们不想要
            //应用任何缩小步骤来转换有效的ecma5代码
            //变成无效的ecma 5代码。这就是为什么“压缩”和“输出”
            //节仅应用ecma 5安全的转换
            // https://github.com/facebook/create-react-app/pull/4234
            ecma: 8
          },
          compress: {
            ecma: 5,
            warnings: false,
            //由于一个丑陋的破坏看似有效的代码的问题而被禁用:
            // https://github.com/facebook/create-react-app/issues/2376
            //待进一步调查:
            // https://github.com/mishoo/UglifyJS2/issues/2011
            comparisons: false,
            //由于Terser中断有效代码的问题而禁用:
            // https://github.com/facebook/create-react-app/issues/5250
            //待进一步调查:
            // https://github.com/terser-js/terser/issues/120
            inline: 2
          },
          mangle: {
            safari10: true
          },
          //添加用于在devtools中进行分析
          keep_classnames: isEnvProductionProfile,
          keep_fnames: isEnvProductionProfile,
          output: {
            ecma: 5,
            comments: false,
            //启用此选项是因为emoji和regex未使用默认值正确缩小
            // https://github.com/facebook/create-react-app/issues/2488
            ascii_only: true
          }
        },
        sourceMap: shouldUseSourceMap
      }),
      //仅在生产模式下使用
      new OptimizeCSSAssetsPlugin({
        cssProcessorOptions: {
          parser: safePostCssParser,
          map: shouldUseSourceMap
            ? {
                //`inline:false`强制将源映射输出到
                //单独文件
                inline: false,
                //`annotation:true`将sourceMappingURL追加到
                //css文件,帮助浏览器查找源映射
                annotation: true
              }
            : false
        },
        cssProcessorPluginOptions: {
          preset: ['default', { minifyFontValues: { removeQuotes: false } }]
        }
      })
    ],
    //自动拆分供应商和共享项
    // 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: false
    },
    //保持运行时块的分隔以启用长期缓存
    // https://twitter.com/wSokra/status/969679223278505985
    // https://github.com/facebook/create-react-app/issues/5358
    runtimeChunk: {
      name: (entrypoint) => `runtime-${entrypoint.name}`
    }
  },
  resolve: {
    //这允许您为webpack应该查找模块的位置设置后备。
    //我们将这些路径放在第二位,因为我们希望“node\u modules”能够“获胜”
    //如果有任何冲突。这与节点解析机制相匹配。
    // https://github.com/facebook/create-react-app/issues/253
    modules: ['node_modules', paths.appNodeModules],
    //这些是节点生态系统支持的合理默认值。
    //我们还将JSX作为一个通用的组件文件扩展名来支持
    //有些工具,尽管我们不建议使用,请参见:
    // https://github.com/facebook/create-react-app/issues/290
    //添加了“web”扩展前缀以获得更好的支持
    //对于React Native Web。
    extensions: paths.moduleFileExtensions,
    alias: {
      ...(isEnvProductionProfile && {
        'react-dom$': 'react-dom/profiling',
        'scheduler/tracing': 'scheduler/tracing-profiling'
      }),
      '@': paths.appSrc
    },
    plugins: [
      //添加了对“即插即用”安装的支持,从而加快了安装和添加
      //防止被遗忘的依赖等。
      PnpWebpackPlugin,
      //防止用户从src/(或node_modules/)外部导入文件。
      //这通常会导致混淆,因为我们只处理src/with-babel中的文件。
      //为了解决这个问题,我们阻止您从src/--如果您愿意,
      //请将这些文件链接到您的节点_modules/中,并让模块解析生效。
      //确保源文件已编译,因为它们不会以任何方式进行处理。
      new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson, reactRefreshOverlayEntry])
    ]
  },
  resolveLoader: {
    plugins: [
      //也与即插即用有关,但这次它告诉webpack加载加载程序
      //从当前包中。
      PnpWebpackPlugin.moduleLoader(module)
    ]
  },
  module: {
    strictExportPresence: true,
    rules: [
      //禁用要求。确保因为它不是一个标准的语言功能。
      { parser: { requireEnsure: false } },
      {
        //“其中一个”将遍历所有后续装载机,直到其中一个
        //符合要求。当没有装载机匹配时,它会掉下来
        //回到加载程序列表末尾的“文件”加载程序。
        oneOf: [
          //TODO:在mime数据库中“image/avif”后合并此配置
          // https://github.com/jshttp/mime-db
          {
            test: [/\.avif$/],
            loader: require.resolve('url-loader'),
            options: {
              limit: 10000,
              mimetype: 'image/avif',
              name: 'static/media/[name].[hash:8].[ext]'
            }
          },
          //“url”加载器的工作原理与“file”加载器类似,只是它嵌入了资产
          //小于数据URL的指定限制(以字节为单位),以避免请求。
          //缺少“test”相当于匹配。
          {
            test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
            loader: require.resolve('url-loader'),
            options: {
              limit: 10000,
              name: 'static/media/[name].[hash:8].[ext]'
            }
          },
          //使用Babel处理应用程序JS。
          //预置包括JSX、Flow、TypeScript和一些ESnext特性。
          {
            test: /\.(js|mjs|jsx|ts|tsx)$/,
            include: paths.appSrc,
            loader: require.resolve('babel-loader'),
            options: {
              plugins: [
                [
                  require.resolve('babel-plugin-named-asset-import'),
                  {
                    loaderMap: {
                      svg: {
                        ReactComponent: '@svgr/webpack?-svgo,+titleProp,+ref![path]'
                      }
                    }
                  }
                ]
              ].filter(Boolean),
              //这是webpack的“babel loader”的一个特性(而不是babel本身)。
              //它允许在./node\umodules/.cache/babel loader中缓存结果/
              //快速重建目录。
              cacheDirectory: true,
              //有关为什么禁用cacheCompression的上下文,请参见#6846
              cacheCompression: false,
              compact: isEnvProduction
            }
          },
          //用Babel处理应用程序之外的任何JS。
          //与应用程序JS不同,我们只编译标准的ES特性。
          {
            test: /\.(js|mjs)$/,
            exclude: /@babel(?:\/|\\{1,2})runtime/,
            loader: require.resolve('babel-loader'),
            options: {
              babelrc: false,
              configFile: false,
              compact: false,
              presets: ['@babel/preset-env'],
              cacheDirectory: true,
              //有关为什么禁用cacheCompression的上下文,请参见#6846
              cacheCompression: false,

              //在node\u模块中调试需要Babel源映射
              //代码。如果没有下面的选项,调试器就会喜欢VSCode
              //显示错误代码并在错误的行上设置断点。
              sourceMaps: shouldUseSourceMap,
              inputSourceMap: shouldUseSourceMap
            }
          },
          //“postcs”加载器将autoprefixer应用于我们的CSS。
          //“css”加载程序解析css中的路径并将资产作为依赖项添加。
          //“style”loader将CSS转换成JS模块,注入<style>标记。
          //在生产中,我们使用MiniCSSExtractPlugin来提取CSS
          //到一个文件,但在开发中“样式”加载程序启用热编辑
          //CSS的。
          //默认情况下,我们支持带有扩展名的CSS模块。模块.css
          {
            test: cssRegex,
            exclude: cssModuleRegex,
            use: getStyleLoaders({
              importLoaders: 1,
              sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment
            }),
            //不要认为CSS导入死代码,即使
            //包含包装声称没有副作用。
            //当Web包为此添加警告或错误时删除此项。
            //看到了吗https://github.com/webpack/webpack/issues/6571
            sideEffects: true
          },
          //添加对CSS模块的支持(https://github.com/css-modules/css-modules)
          //使用扩展名。模块.css
          {
            test: cssModuleRegex,
            use: getStyleLoaders({
              importLoaders: 1,
              sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
              modules: {
                getLocalIdent: getCSSModuleLocalIdent
              }
            })
          },
          //选择支持SASS(使用.scss或.SASS扩展名)。
          //默认情况下,我们支持带有
          //扩展。模块.scss或者。模块.sass
          {
            test: lessRegex,
            exclude: lessModuleRegex,
            use: getStyleLoaders(
              {
                importLoaders: 3,
                sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment
              },
              'less-loader'
            ),
            //不要认为CSS导入死代码,即使
            //包含包装声称没有副作用。
            //当Web包为此添加警告或错误时删除此项。
            //看到了吗https://github.com/webpack/webpack/issues/6571
            sideEffects: true
          },
          //添加对CSS模块的支持,但使用SASS
          //使用扩展名。模块.scss或者。模块.sass
          {
            test: lessModuleRegex,
            use: getStyleLoaders(
              {
                importLoaders: 3,
                sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
                modules: {
                  getLocalIdent: getCSSModuleLocalIdent
                }
              },
              'less-loader'
            )
          },
          //“文件”加载程序确保这些资产由WebpackDevServer提供服务。
          //当你“导入”一个资产时,你会得到它的(虚拟)文件名。
          //在生产中,它们会被复制到“build”文件夹中。
          //此加载程序不使用“test”,因此它将捕获所有模块
          //从其他装载机上掉下来。
          {
            loader: require.resolve('file-loader'),
            //排除`js`文件以保持“css”加载程序在注入时正常工作
            //它的运行时,否则将通过“文件”加载器处理。
            //还要排除“html”和“json”扩展,以便对它们进行处理
            //内部加载程序。
            exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
            options: {
              name: 'static/media/[name].[hash:8].[ext]'
            }
          }
          //**停止**您正在添加新的加载程序吗?
          //确保在“文件”加载程序之前添加新的加载程序。
        ]
      }
    ]
  },
  plugins: plugins(isEnvDevelopment, isEnvProduction),
  //有些库导入节点模块,但不在浏览器中使用它们。
  //告诉webpack为它们提供空的模拟,以便导入它们。
  node: {
    module: 'empty',
    dgram: 'empty',
    dns: 'mock',
    fs: 'empty',
    http2: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  },
  //关闭性能处理,因为我们利用
  //我们通过FileSizeReporter提供的提示
  performance: false,
  devServer
};

2、编辑paths.js:

const paths = require('./paths');
const getClientEnvironment = require('./env');
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');

const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');

//有些应用程序不需要保存Web请求的好处,因此无需内联代码块
//使构建过程更加顺畅。
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';

const hasJsxRuntime = (() => {
  if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') {
    return false;
  }

  try {
    require.resolve('react/jsx-runtime');
    return true;
  } catch (e) {
    return false;
  }
})();

module.exports = function (isEnvDevelopment, isEnvProduction) {
  const plugins = [
    //生成`索引.html`注入<script>的文件。
    new HtmlWebpackPlugin(
      Object.assign(
        {},
        {
          inject: true,
          template: paths.appHtml
        },
        isEnvProduction
          ? {
              minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeRedundantAttributes: true,
                useShortDoctype: true,
                removeEmptyAttributes: true,
                removeStyleLinkTypeAttributes: true,
                keepClosingSlash: true,
                minifyJS: true,
                minifyCSS: true,
                minifyURLs: true
              }
            }
          : undefined
      )
    ),
    //公开网址在index.html中以%PUBLIC_URL%的形式提供,例如:
    // <link rel =“ icon” href =“%PUBLIC_URL%/ favicon.ico”>
    //除非您指定“主页”,否则它将是一个空字符串
    //在“ package.json”中,在这种情况下,它将是该URL的路径名。
    new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
    //这为未找到模块的错误提供了一些必要的上下文,例如
    //请求资源。
    new ModuleNotFoundPlugin(paths.appPath),
    //使一些环境变量可用于JS代码,例如:
    //如果(进程.env.NODE_env==='生产'){。。。}. 见`/环境js`.
    //将NODE_ENV设置为生产环境是绝对必要的
    //在生产构建期间。
    //否则React将以非常慢的开发模式编译。
    new webpack.DefinePlugin(env.stringified),
    // 力矩.js是一个非常流行的库,它绑定了大型区域设置文件
    //默认情况下,由于webpack如何解释其代码。这是一个实用程序
    //需要用户选择导入特定区域设置的解决方案。
    // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
    //如果不使用,可以将其删除力矩.js:
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new ESLintPlugin({
      // Plugin options
      extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'],
      formatter: require.resolve('react-dev-utils/eslintFormatter'),
      eslintPath: require.resolve('eslint'),
      context: paths.appSrc,
      // ESLint class options
      cwd: paths.appPath,
      resolvePluginsRelativeTo: __dirname,
      baseConfig: {
        extends: [paths.appEslintConfig],
        rules: {
          ...(!hasJsxRuntime && {
            'react/react-in-jsx-scope': 'error'
          })
        }
      }
    })
  ];

  if (isEnvDevelopment) {
    plugins.push(
      //这对于发出热更新(CSS和快速刷新)是必需的:
      new webpack.HotModuleReplacementPlugin(),
      //如果你在路径中输入了错误的case,Watcher就不能很好地工作
      //一个插件,当您尝试执行此操作时会打印错误。
      //看到了吗https://github.com/facebook/create-react-app/issues/240
      new CaseSensitivePathsPlugin(),
      //如果您需要一个丢失的模块,然后使用“npm install”命令,那么仍然需要
      //重新启动Web包的开发服务器以发现它。这个插件
      //使发现自动进行,因此您不必重新启动。
      //看到了吗https://github.com/facebook/create-react-app/issues/186
      new WatchMissingNodeModulesPlugin(paths.appNodeModules)
    );
  }

  if (isEnvProduction) {
    plugins.push(
      new MiniCssExtractPlugin({
        //选项类似于webpackOptions.output中的相同选项
        //两个选项都是可选的
        filename: 'static/css/[name].[contenthash:8].css',
        chunkFilename: 'static/css/[name].[contenthash:8].chunk.css'
      })
    );

    if (shouldInlineRuntimeChunk) {
      plugins.push(new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]));
    }
  }

  return plugins;
};

4、编辑plugins.js:

    const paths = require('./paths');
    const getClientEnvironment = require('./env');
    const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));

    const webpack = require('webpack');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');

    const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
    const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
    const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
    const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');

    //有些应用程序不需要保存Web请求的好处,因此无需内联代码块
    //使构建过程更加顺畅。
    const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';

    module.exports = function (isEnvDevelopment, isEnvProduction) {
        const plugins = [
            new HtmlWebpackPlugin(
                Object.assign(
                    {},
                    {
                        inject: true,
                        template: paths.appHtml
                    },
                    isEnvProduction
                        ? {
                                minify: {
                                    removeComments: true,
                                    collapseWhitespace: true,
                                    removeRedundantAttributes: true,
                                    useShortDoctype: true,
                                    removeEmptyAttributes: true,
                                    removeStyleLinkTypeAttributes: true,
                                    keepClosingSlash: true,
                                    minifyJS: true,
                                    minifyCSS: true,
                                    minifyURLs: true
                                }
                          }
                        : undefined
                )
            ),
            //在index.html中提供一些环境变量。
            //公开网址在index.html中以%PUBLIC_URL%的形式提供,例如:
            // <link rel =“ icon” href =“%PUBLIC_URL%/ favicon.ico”>
            //除非您指定“主页”,否则它将是一个空字符串
            //在“ package.json”中,在这种情况下,它将是该URL的路径名。
            new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
            //这为未找到模块的错误提供了一些必要的上下文,例如
            //请求资源。
            new ModuleNotFoundPlugin(paths.appPath),

            new webpack.DefinePlugin(env.stringified),
            new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
        ];

        if (isEnvDevelopment) {
            plugins.push(
                new webpack.HotModuleReplacementPlugin(),
                new CaseSensitivePathsPlugin(),
                new WatchMissingNodeModulesPlugin(paths.appNodeModules)
            );
        }

        if (isEnvProduction) {
            plugins.push(
                new MiniCssExtractPlugin({
                    //选项类似于webpackOptions.output中的相同选项
                    //两个选项都是可选的
                    filename: 'static/css/[name].[contenthash:8].css',
                    chunkFilename: 'static/css/[name].[contenthash:8].chunk.css'
                })
            );

            if (shouldInlineRuntimeChunk) {
                plugins.push(new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]));
            }
        }
        return plugins;
    };

5、编辑devServer.js:

const paths = require('./paths');
const ignoredFiles = require('react-dev-utils/ignoredFiles');

module.exports = {
    disableHostCheck: process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
    hot: true, // 热替换
    contentBase: paths.appBuild, // server文件的根目录
    contentBasePublicPath: paths.publicUrlOrPath,
    watchContentBase: true,
    compress: true, // 开启gzip
    port: 8080, // 端口
    host: '127.0.0.1',
    //使WebpackDevServer自己的日志静音,因为它们通常没有用。
    //此设置仍会显示编译警告和错误。
    clientLogLevel: 'none',
    publicPath: paths.publicUrlOrPath.slice(0, -1),
    //默认情况下,WebpackDevServer嘈杂,因此我们发出自定义消息
    //通过上面的`compiler.hooks [...]。tap`调用监听编译器事件。
    quiet: true,
    //据报道,这避免了某些系统上的CPU过载。
    watchOptions: {
        ignored: ignoredFiles(paths.appSrc)
    },
    proxy: {}
};

6、以上配置文件编辑完成后npm run dev就可以直接运行了

本原创文章未经允许不得转载 | 当前页面:苦海学说 » 搭建react项目(二):配置webpack相关

评论