const path = require("path");
const resolve = dir => path.join(__dirname, dir);
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer");
const TerserPlugin = require("terser-webpack-plugin");
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = ["js", "css"];
const px2rem = require("postcss-px2rem");
const SkeletonWebpackPlugin = require("vue-skeleton-webpack-plugin");

const _env = process.env; // 不支持解构

// == ant-design 主题覆盖 less (条件编译) == //
let antDesignVariables = {};
/* IFTRUE_ANT_DESIGN */
antDesignVariables = {
  modifyVars: {
    hack: `true; @import "~@/styles/loader/ant-design.variables";`
  },
  javascriptEnabled: true
};
/* FITRUE_ANT_DESIGN */

// es5语法, 导出一份拷贝: 修改需要重新运行
module.exports = {
  // 基础配置
  publicPath: "./",
  outputDir: _env.DIR_OUT_PUT || "dist",
  assetsDir: "",
  lintOnSave: _env.NODE_ENV === "development",
  runtimeCompiler: true,
  productionSourceMap: false,
  // 本地代理
  devServer: {
    port: _env.VUE_APP_DEV_PORT,
    proxy: {
      [_env.VUE_APP_DEV_PROXY]: {
        // target字段为空编译报错
        target: _env.VUE_APP_BASE_API,
        changeOrigin: true,
        pathRewrite: {
          ["^" + _env.VUE_APP_DEV_PROXY]: ""
        }
      }
    },
    disableHostCheck: true
  },
  // css配置: 自动加载 loaderOptions 对 stylus 和 less 都无效
  css: {
    extract: true,
    sourceMap: false,
    loaderOptions: {
      // 自动加载仅导入主题: less sass stylus 方式不相同 - 细节详见 README.md
      stylus: {
        import: "~@/styles/loader/variables"
      },
      postcss: {
        plugins: [
          //基准大小 baseSize，需要和flexRem.js中相同
          px2rem({
            remUnit: _env.VUE_APP_REM_UNIT
          })
        ]
      },
      less: antDesignVariables
    }
  },
  chainWebpack: config => {
    // 运行 Webpack Bundle Analyzer插件：npm run analyze
    if (_env.IS_ANALYZE) {
      config
        .plugin("webpack-report")
        .use(BundleAnalyzerPlugin.BundleAnalyzerPlugin, [
          {
            analyzerMode: "static"
          }
        ]);
    }
    // 添加别名
    config.resolve.alias
      .set("@", resolve("src"))
      .set("storage", resolve("src/utils/storage"))
      .set("extend", resolve("src/styles/extend"))
      .set("mixin", resolve("src/styles/mixin"))
      .set("dinkle", resolve("src/modules/dinkle")) // 町洋阿拉丁
      .set("opay", resolve("src/modules/opay")); // 欧非项目
    // 模块配置使用链式语法
    config.module
      // 配置pug/jade
      .rule("pug")
      .test(/\.pug$/)
      .use("pug-plain-loader")
      .loader("pug-plain-loader")
      .end();
  },
  configureWebpack: config => {
    // 自动识别文件后缀
    config.resolve.extensions = [
      ".js",
      ".vue",
      ".json",
      ".css",
      ".styl",
      ".sass",
      ".scss",
      ".less"
    ];
    // vue骨架屏插件配置
    if (_env.VUE_APP_SKELETON) {
      config.plugins.push(
        new SkeletonWebpackPlugin({
          webpackConfig: {
            entry: {
              app: resolve("src/config/skeleton/conf")
            }
          },
          minimize: true,
          quiet: true
        })
      );
    }
    // 配置条件编译: js-conditional-compile-loader 下 npm 和 cnpm 不能混用
    config.module.rules.push({
      test: /\.js$/,
      include: [resolve("src"), resolve("test")],
      use: [
        {
          loader: "js-conditional-compile-loader",
          options: {
            isDebug: _env.NODE_ENV == "development", // optional, this is default
            // 自定义 flag (.env 是 string 化的值, 非合法 json: string 可使用 includes 函数, 单独效验使用正则)
            ANT_DESIGN: _env.VUE_APP_PLATFORM.includes(
              _env.VUE_APP_UI_ANT_DESIGN
            ),
            QUASAR: _env.VUE_APP_PLATFORM.includes(_env.VUE_APP_UI_QUASAR),
            ELEMENT: _env.VUE_APP_PLATFORM.includes(_env.VUE_APP_UI_ELEMENT)
          }
        }
      ]
    });
    // 开发环境独立配置 devtool
    if (_env.NODE_ENV === "development") {
      config.devtool = "source-map";
    }
    // 生产环境立配置
    if (_env.NODE_ENV === "production") {
      // 开启gzip压缩
      if (_env.IS_GZIP) {
        config.plugins.push(
          new CompressionWebpackPlugin({
            filename: "[path].gz[query]",
            algorithm: "gzip",
            test: new RegExp(
              "\\.(" + productionGzipExtensions.join("|") + ")$"
            ),
            threshold: 10240,
            minRatio: 0.8
          })
        );
      }
      // webpack4语法返回一个将会被合并的对象
      return {
        output: {
          // 输出重构: 打包编译后的文件名称【模块名称.chunkhash.版本号】- 添加文件夹(./js/)
          filename: `./js/[name].[chunkhash].${_env.VUE_APP_VERSION}.js`,
          chunkFilename: `./js/[name].[chunkhash].${_env.VUE_APP_VERSION}.js`
        },
        // 到打包chunk警告配置
        performance: {
          hints: "warning",
          // 入口起点的最大体积 整数类型（以字节为单位）
          maxEntrypointSize: 50000000,
          // 生成文件的最大体积 整数类型（以字节为单位 300k）
          maxAssetSize: 30000000,
          // 只给出 js 文件的性能提示
          assetFilter: function (assetFilename) {
            return assetFilename.endsWith(".js");
          }
        },
        // 拆包: 大文件拆分提升加载速度和懒加载
        optimization: {
          runtimeChunk: "single",
          splitChunks: {
            chunks: "all",
            maxInitialRequests: Infinity,
            minSize: 20000, // 依赖包超过20000bit将被单独打包
            cacheGroups: {
              vendor: {
                test: /[\\/]node_modules[\\/]/,
                name (module) {
                  const packageName = module.context.match(
                    /[\\/]node_modules[\\/](.*?)([\\/]|$)/
                  )[1];
                  return `npm.${packageName.replace("@", "")}`;
                }
              }
            }
          },
          // 代码压缩去除打印: npm i uglifyjs-webpack-plugin@1 需要使用低版本, 新版本不识别 const 关键字 - 报 npm audit fix
          minimizer: [
            new TerserPlugin({
              cache: false,
              sourceMap: false,
              parallel: true, // 使用多进程并行运行来提高构建速度。默认并发运行数：os.cpus().length - 1。
              terserOptions: {
                compress: {
                  drop_debugger: true, // 去除 debugger
                  drop_console: true, // 生产环境自动删除 console
                  dead_code: true // 去除不可达代码: 如 if (false) { ... }
                },
                warnings: false
              }
            })
          ]
        }
      };
    }
  },
  // quasar: vue add quasar 自动添加
  pluginOptions: {
    quasar: {
      importStrategy: "manual",
      rtlSupport: false
    }
  },
  transpileDependencies: ["quasar"]
};
