123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- const webpack = require('webpack');
- const HtmlWebpackPlugin = require('html-webpack-plugin');
- const MiniCssExtractPlugin = require('mini-css-extract-plugin');
- const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
- const OfflinePlugin = require('offline-plugin');
- const TerserPlugin = require('terser-webpack-plugin');
- const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
- const WebpackPwaManifest = require('webpack-pwa-manifest');
- const CompressionPlugin = require('compression-webpack-plugin');
- const WebpackPluginFrTheme = require('webpack-plugin-fr-theme');
- const { HashedModuleIdsPlugin } = require('webpack');
- const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
- const { CleanWebpackPlugin } = require('clean-webpack-plugin');
- const CopyWebpackPlugin = require('copy-webpack-plugin');
- const ProgressBarPlugin = require('progress-bar-webpack-plugin');
- const paths = require('./paths');
- const getClientEnvironment = require('./env');
- const loaders = require('./loader.prod');
- const publicPath = paths.servedPath;
- const publicUrl = publicPath.slice(0, -1);
- const env = getClientEnvironment(publicUrl);
- if (env.stringified['process.env'].NODE_ENV !== '"production"') {
- throw new Error('生产环境编译,必须设定环境变量为 NODE_ENV=production.');
- }
- module.exports = {
- mode: 'production',
- // build遇到错误,中止build
- bail: true,
- target: 'web',
- entry: [require.resolve('react-app-polyfill/ie11'), paths.appIndexJs],
- output: {
- path: paths.appBuild,
- pathinfo: true,
- publicPath: '',
- filename: 'assets/js/[name].[hash].js',
- sourceMapFilename: 'assets/js/[name].[hash].map',
- chunkFilename: 'assets/js/[name].[chunkhash].chunk.js',
- },
- resolve: {
- modules: [paths.appSrc, paths.appNodeModules],
- extensions: ['.jsx', '.js', '.scss', '.css', '.json'],
- alias: {
- '@': paths.appSrc,
- },
- plugins: [
- // 阻止从src和node_modules目录之外导入模块
- new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
- ],
- },
- optimization: {
- nodeEnv: 'production',
- sideEffects: true,
- noEmitOnErrors: true,
- runtimeChunk: true,
- minimize: true,
- minimizer: [
- new TerserPlugin({
- terserOptions: {
- warnings: false,
- parse: {},
- compress: {
- ecma: 5,
- warnings: false,
- comparisons: false,
- inline: 2,
- },
- mangle: true,
- output: {
- ecma: 5,
- comments: false,
- ascii_only: true,
- },
- },
- parallel: true,
- cache: true,
- sourceMap: true,
- }),
- new OptimizeCSSAssetsPlugin(),
- ],
- splitChunks: {
- chunks: 'async', // 必须三选一: "initial直接引入" | "all"(默认就是all)全部 | "async动态引入"
- minSize: 30000, // 最小尺寸,默认0
- minChunks: 1, // 最小 chunk ,默认1
- maxAsyncRequests: 5, // 最大异步请求数, 默认1
- maxInitialRequests: 3, // 最大初始化请求书,默认1
- name: false,
- cacheGroups: {
- vendor: {
- name: 'vendor',
- test: /[\\/]node_modules[\\/]/,
- chunks: 'all',
- },
- otherBase: {
- test: module =>
- /@ant-design|swagger-ui-react|react|prop-types|antd|recharts|lodash|react-quill/.test(module.context), // 直接使用 test 来做路径匹配,抽离react相关代码
- chunks: 'all',
- name: 'otherBase',
- priority: 10,
- },
- // styles: {
- // name: 'styles',
- // test: /\.(scss|css|less)$/,
- // chunks: 'all',
- // enforce: true,
- // },
- },
- },
- },
- module: {
- // 缺少exports,报错而不是警告
- strictExportPresence: true,
- rules: [
- loaders.jsLoader,
- {
- oneOf: [
- loaders.cssLoaderRule,
- loaders.scssLoaderRule,
- loaders.lessLoaderRule,
- loaders.svgSpriteLoader,
- loaders.fontWoffLoader,
- loaders.fontTtfLoader,
- loaders.imageLoader,
- loaders.mediaLoader,
- loaders.otherLoader,
- ],
- },
- ],
- },
- performance: {
- hints: false,
- },
- plugins: [
- // new ProgressBarPlugin(),
- new WebpackPluginFrTheme(),
- new webpack.DefinePlugin(env.stringified),
- new webpack.NamedModulesPlugin(),
- new webpack.optimize.ModuleConcatenationPlugin(),
- new webpack.optimize.OccurrenceOrderPlugin(true),
- new MiniCssExtractPlugin({
- filename: 'assets/css/app.[name].css',
- chunkFilename: 'assets/css/app.[contenthash:12].css',
- }),
- new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en-gb|zh-cn/),
- new CopyWebpackPlugin([
- {
- from: paths.appPublic,
- to: paths.appBuild,
- },
- ]),
- new HtmlWebpackPlugin({
- inject: true,
- template: paths.appHtml,
- sourceMap: true,
- minify: {
- removeComments: true,
- collapseWhitespace: true,
- removeRedundantAttributes: true,
- useShortDoctype: true,
- removeEmptyAttributes: true,
- removeStyleLinkTypeAttributes: true,
- keepClosingSlash: true,
- minifyJS: true,
- minifyCSS: true,
- minifyURLs: true,
- },
- }),
- new CleanWebpackPlugin(),
- new CompressionPlugin({
- algorithm: 'gzip',
- test: /\.js$|\.css$|\.html$/,
- threshold: 10240,
- minRatio: 0.8,
- }),
- new WebpackPwaManifest({
- name: 'AISware AI²',
- short_name: 'AISquare',
- description: '通用人工智能平台',
- background_color: '#fafafa',
- theme_color: '#b1624d',
- inject: true,
- ios: false,
- }),
- new HashedModuleIdsPlugin({
- hashFunction: 'sha256',
- hashDigest: 'hex',
- hashDigestLength: 20,
- }),
- new OfflinePlugin({
- relativePaths: true,
- appShell: '/',
- caches: 'all',
- AppCache: false,
- updateStrategy: 'changed',
- safeToUseOptionalCaches: true,
- ServiceWorker: {
- output: 'assets/js/sw.js',
- publicPath: 'assets/js',
- minify: true,
- events: true,
- },
- }),
- //new BundleAnalyzerPlugin(),
- ],
- };
|