text: /**
   * @author City
   * @description Webpack 公共配置
   */
  
  const { resolve } = require('path')
  
  // const
  const { isDev, PROJECT_PATH } = require('../constant')
  
  // plugin
  const HtmlWebpackPlugin = require('html-webpack-plugin')
  const CopyPlugin = require('copy-webpack-plugin')
  const WebpackBar = require('webpackbar')
  const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
  const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
  const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  const TerserPlugin = require('terser-webpack-plugin')
  const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
  
  module.exports = {
    // 入口文件
    entry: {
      app: resolve(PROJECT_PATH, './src/index.tsx')
    },
    // 出口文件
    output: {
      filename: `js/[name]${isDev ? '' : '.[hash:8]'}.js`,
      path: resolve(PROJECT_PATH, './dist')
    },
    // 定义文件后缀名
    resolve: {
      extensions: ['.tsx', '.ts', '.js', '.json'],
      alias: {
        '@src': resolve(PROJECT_PATH, './src')
      }
    },
    // 插件
    plugins: [
      new HtmlWebpackPlugin({
        template: resolve(PROJECT_PATH, './public/index.html'),
        filename: 'index.html',
        cache: false, // 特别重要：防止之后使用v6版本 copy-webpack-plugin 时代码修改一刷新页面为空问题。
        minify: isDev
          ? false
          : {
              removeAttributeQuotes: true,
              collapseWhitespace: true,
              removeComments: true,
              collapseBooleanAttributes: true,
              collapseInlineTagWhitespace: true,
              removeRedundantAttributes: true,
              removeScriptTypeAttributes: true,
              removeStyleLinkTypeAttributes: true,
              minifyCSS: true,
              minifyJS: true,
              minifyURLs: true,
              useShortDoctype: true
            }
      }),
      new CopyPlugin({
        patterns: [
          {
            context: resolve(PROJECT_PATH, './public'),
            from: '*',
            to: resolve(PROJECT_PATH, './dist'),
            toType: 'dir'
          }
        ]
      }),
      new WebpackBar({
        name: isDev ? '正在启动' : '正在打包',
        color: '#fa8c16'
      }),
      new ForkTsCheckerWebpackPlugin({
        typescript: {
          configFile: resolve(PROJECT_PATH, './tsconfig.json')
        }
      }),
      new HardSourceWebpackPlugin(),
      !isDev
        ? new MiniCssExtractPlugin({
            filename: 'css/[name].[contenthash:8].css',
            chunkFilename: 'css/[name].[contenthash:8].css',
            ignoreOrder: false
          })
        : () => {}
    ],
    // 规则
    module: {
      rules: [
        {
          test: /\.(tsx?|js)$/,
          loader: 'babel-loader',
          options: { cacheDirectory: true },
          exclude: /node_modules/
        },
        {
          test: /\.css$/,
          use: [
            isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
            {
              loader: 'css-loader',
              options: {
                modules: false, // 默认就是 false, 若要开启，可在官网具体查看可配置项
                sourceMap: isDev, // 开启后与 devtool 设置一致, 开发环境开启，生产环境关闭
                importLoaders: 0 // 指定在 CSS loader 处理前使用的 loader 数量
              }
            },
            {
              loader: 'postcss-loader',
              options: {
                postcssOptions: {
                  ident: 'postcss',
                  plugins: [
                    require('postcss-flexbugs-fixes'),
                    require('postcss-preset-env')({
                      autoprefixer: {
                        grid: true,
                        flexbox: 'no-2009'
                      },
                      stage: 3
                    }),
                    require('postcss-normalize')
                  ]
                },
                sourceMap: isDev
              }
            }
          ]
        }
      ]
    },
    optimization: {
      minimize: !isDev,
      minimizer: [
        !isDev &&
          new TerserPlugin({
            extractComments: false,
            terserOptions: {
              compress: { pure_funcs: ['console.log'] }
            }
          }),
        !isDev && new OptimizeCssAssetsPlugin()
      ].filter(Boolean),
      splitChunks: {
        chunks: 'all',
        name: true
      }
    }
  }
  