webpack.client.conf.js 3.96 KB
const webpack = require('webpack');
const merge = require('webpack-merge');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
let baseConfig = require('./webpack.base.conf');
const isProd = process.env.NODE_ENV === 'production';

const webpackConfig = merge(baseConfig, {
  entry: {
    app: './apps/entry-client.js'
  },
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        cache: true,
        parallel: true,
        sourceMap: true,
        uglifyOptions: {
          compress: {
            warnings: false
          },
          comments: false
        }
      }),
      new OptimizeCSSAssetsPlugin({
        cssProcessorOptions: { safe: true, map: { inline: false } }
      })
    ],
    runtimeChunk: true,
    splitChunks: {
      maxAsyncRequests: Infinity,
      maxInitialRequests: Infinity,
      chunks: 'all',
      cacheGroups: {
        vendors: {
          priority: -10,
          chunks: 'all',
          name: 'vendors',
          test: /[\\/]node_modules[\\/]/
        },
        vue: {
          priority: 1,
          chunks: 'all',
          name: 'vue',
          test: /vue\.runtime\.esm/,
        },
        vuedep: {
          priority: 1,
          chunks: 'all',
          name: 'vuedep',
          test: /(vue[-x])|(bscroll)/,
        },
        swiper: {
          priority: 1,
          chunks: 'all',
          name: 'swiper',
          test: /swiper/,
        },
        lottie: {
          priority: 1,
          chunks: 'all',
          name: 'lottie',
          test: /lottie-web/,
        },
        animejs: {
          priority: 1,
          chunks: 'all',
          name: 'animejs',
          test: /animejs/,
        }
      }
    }
  },
  module: {
    rules: [
      {
        test: /\.s?css$/,
        use: [
          isProd ? MiniCssExtractPlugin.loader : 'vue-style-loader',
          'css-loader',
          'postcss-loader',
          {
            loader: 'sass-loader',
            options: {
              sourceMap: isProd
            }
          }]
      }, {
        test: /\.styl(us)?$/,
        use: [
          isProd ? MiniCssExtractPlugin.loader : 'vue-style-loader',
          'css-loader',
          'postcss-loader',
          {
            loader: 'stylus-loader',
            options: {
              sourceMap: isProd,
              'resolve url': true,
              import: [path.resolve(__dirname, '../apps/statics/scss/theme.styl')]
            }
          }]
      }, {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        use: {
          loader: 'file-loader',
          options: {
            name: 'static/img/[name].[hash:7].[ext]'
          }
        }
      }, {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        use: {
          loader: 'file-loader',
          options: {
            name: 'static/img/[name].[hash:7].[ext]'
          }
        }
      }
    ]
  },
  resolve: {
    alias: {
      'create-api': 'common/create-api-client.js',
      'report-error': 'common/report-error-client.js'
    }
  },
  plugins: [
    new VueSSRClientPlugin({
      filename: '../../manifest.json'
    }),
    new webpack.DefinePlugin({
      'process.env.VUE_ENV': '"client"'
    }),
    new HtmlWebpackPlugin({
      filename: isProd ? '../../degrade.html' : 'degrade.html',
      template: 'apps/index.html',
      inject: true
    })
  ]
});

if (process.argv.some(a => a === '--report')) {
  webpackConfig.plugins.push(new BundleAnalyzerPlugin());
}
if (isProd) {
  webpackConfig.plugins.push(
    new MiniCssExtractPlugin({
      filename: 'static/css/[name].[contenthash].css',
      allChunks: true
    })
  );
}
module.exports = webpackConfig;