UNPKG

handy-service

Version:
322 lines (308 loc) 8.86 kB
const path = require("path"); const chalk = require("chalk"); const autoprefixer = require("autoprefixer"); const webpack = require("webpack"); const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const TerserPlugin = require("terser-webpack-plugin"); const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); const ManifestPlugin = require("webpack-manifest-plugin"); const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin"); const ReplaceHtmlPlugin = require("./replaceHtmlPlugin"); const paths = require("./paths"); const multiPage = require("./multiPage"); const getClientEnvironment = require("./env"); const presets = paths.appPresets; const hasAntd = presets.features.includes("antd"); const publicPath = paths.servedPath; const publicUrl = publicPath.slice(0, -1); const env = getClientEnvironment(publicUrl); const outputFileName = "[name].[chunkhash:8].js"; const outputChunkFilename = "[name].[chunkhash:8].chunk.js"; const cssFilename = "[name].[contenthash:8].css"; const cssRegex = /\.css$/; const cssModuleRegex = /\.module\.css$/; const lessRegex = /\.less$/; const lessModuleRegex = /\.module\.less$/; const sassRegex = /\.sass$/; const sassModuleRegex = /\.module\.sass$/; const stylusRegex = /.styl$/; const stylusModuleRegex = /\.module\.styl$/; const shouldUseSourceMap = process.env.SOURCEMAP !== "false"; if (env.stringified["process.env"].NODE_ENV !== "\"production\"") { throw new Error("Production builds must have NODE_ENV=production."); } const getStyleLoaders = (cssOptions, preProcessor, preProcessorOptions) => { const loaders = [ MiniCssExtractPlugin.loader, { loader: require.resolve("css-loader"), options: cssOptions }, { loader: require.resolve("postcss-loader"), options: { ident: "postcss", plugins: () => [ require("postcss-flexbugs-fixes"), autoprefixer({ flexbox: "no-2009" }) ], sourceMap: shouldUseSourceMap } } ]; if (preProcessor) { loaders.push({ loader: require.resolve(preProcessor), options: Object.assign( { sourceMap: shouldUseSourceMap }, preProcessorOptions ) }); } return loaders; }; const config = { mode: "production", devtool: shouldUseSourceMap ? "source-map" : false, entry: multiPage.appEntries, output: { path: paths.appBuild, filename: outputFileName, chunkFilename: outputChunkFilename, publicPath }, resolve: { extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"], alias: { components: path.resolve(paths.appPath, "src", "components"), modules: path.resolve(paths.appPath, "src", "modules"), utils: path.resolve(paths.appPath, "src", "utils"), common: path.resolve(paths.appPath, "src", "common"), stores: path.resolve(paths.appPath, "src", "stores"), context: path.resolve(paths.appPath, "src", "contexts") }, plugins: [new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson])] }, optimization: { minimizer: [ new TerserPlugin({ terserOptions: { parse: { ecma: 8 }, compress: { ecma: 5, warnings: false, comparisons: false }, mangle: { safari10: true }, output: { ecma: 5, comments: false, ascii_only: true } }, parallel: true, cache: true, sourceMap: shouldUseSourceMap }), new OptimizeCSSAssetsPlugin({ cssProcessorOptions: { safe: true } }) ], splitChunks: { chunks: "all", name: true } }, module: { strictExportPresence: true, rules: [ { oneOf: [ { test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], loader: require.resolve("url-loader"), options: { limit: 10000, name: "static/media/[name].[hash:8].[ext]" } }, { test: /\.(js|jsx|mjs)$/, include: paths.appSrc, loader: require.resolve("babel-loader"), options: { presets: [ [ require("@babel/preset-env"), { useBuiltIns: "entry", modules: false } ], [ require("@babel/preset-react"), { development: false } ] ], compact: true, plugins: [ [require("@babel/plugin-proposal-decorators"), { legacy: true }], [require("@babel/plugin-proposal-class-properties"), { loose: true }] ] } }, { test: cssRegex, exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, sourceMap: shouldUseSourceMap }) }, { test: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, modules: true, sourceMap: shouldUseSourceMap }) }, { test: sassRegex, exclude: sassModuleRegex, use: getStyleLoaders( { importLoaders: 2, sourceMap: shouldUseSourceMap }, "sass-loader" ) }, { test: sassModuleRegex, use: getStyleLoaders( { importLoaders: 2, modules: true, sourceMap: shouldUseSourceMap }, "sass-loader" ) }, { test: lessRegex, exclude: lessModuleRegex, use: getStyleLoaders( { importLoaders: 2, sourceMap: shouldUseSourceMap }, "less-loader", { modifyVars: hasAntd ? require(paths.modifyVarsJson) : {}, javascriptEnabled: true } ) }, { test: lessModuleRegex, use: getStyleLoaders( { importLoaders: 2, modules: true, sourceMap: shouldUseSourceMap }, "less-loader" ) }, { test: stylusRegex, exclude: stylusModuleRegex, use: getStyleLoaders( { importLoaders: 2, sourceMap: shouldUseSourceMap }, "stylus-loader" ) }, { test: stylusModuleRegex, use: getStyleLoaders( { importLoaders: 2, modules: true, sourceMap: shouldUseSourceMap }, "stylus-loader" ) }, { exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/], loader: require.resolve("file-loader"), options: { name: "static/media/[name].[hash:8].[ext]" } } ] } ] }, plugins: [ new ReplaceHtmlPlugin(env.raw), new webpack.DefinePlugin(env.stringified), new webpack.ProvidePlugin({ React: "react", ReactDOM: "react-dom", PropTypes: "prop-types" }), new MiniCssExtractPlugin({ filename: cssFilename, chunkFilename: "[name].[hash].css" }), new ManifestPlugin({ fileName: "asset-manifest.json", publicPath }), new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), new BundleAnalyzerPlugin() ], node: { dgram: "empty", fs: "empty", net: "empty", tls: "empty", child_process: "empty" } }; config.plugins = [...multiPage.htmlWebpackPlugins, ...config.plugins]; if (!presets) { console.log(chalk.red("package.json not includes presets field")); process.exit(1); } let extendWebpackPlugins; extendWebpackPlugins = [ "./extends/tsExtendWebpack", "./extends/linterExtendWebpack", "./extends/antdExtendWebpack" ]; // @remove-before-eject extendWebpackPlugins = [ "handy-cli-plugin-typescript/extendWebpack", "handy-cli-plugin-linter/extendWebpack", "handy-cli-plugin-antd/extendWebpack" ]; // @remove-end-eject extendWebpackPlugins.forEach(plugin => { require(plugin)(config, presets, paths, "PRODUCTION"); }); module.exports = config;