likes
comments
collection
share

webpack3升级为webpack4实践记录

作者站长头像
站长
· 阅读数 41

参考原文:

一、调试开发环境可用

先让项目能跑起来

1. 升级webapck4

  • npm install -D webapck@4.46.0
  • npm install -D webpack-cli webpack-dev-server
  • package.json文件涉及的依赖
原来的版本升级的版本操作
webpack^3.6.0^4.46.0升级
webpack-cli^3.3.12新增
webpack-dev-server^2.9.1^3.11.1升级
html-webpack-plugin^2.30.1^4.3.0升级
vue-loader^13.3.0^15.7.0升级
mini-css-extract-plugin^0.9.0新增
babel-plugin-transform-es2015-modules-commonjs^6.26.2新增
  • 更新完之后,重新执行npm i

2. 添加VueLoaderPlugin

  • 涉及文件:webpack.base.conf.js
// webpack.base.conf.js
const { VueLoaderPlugin } = require('vue-loader') // 新增
module.exports = {
  mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
  // ...
  // 增加plugins(和entry、output同级)
  plugins: [
    new VueLoaderPlugin()
  ]
  // ...
}

3. 安装mini-css-extract-plugin

  • 涉及文件:utils.js
  • 安装mini-css-extract-plugin 去掉extract-text-webpack-plugin的配置,升级webpack4这个插件已经被取代了,使用mini-css-extract-plugin
  • 修改
// utils.js

// 替换原来的ExtractTextPlugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
exports.cssLoaders = function(options) {
  //  ...
  // 1.找到下面的内容注释或删除
  // if (options.extract) {
  //   return ExtractTextPlugin.extract({
  //     use: loaders,
  //     fallback: 'vue-style-loader',
  //     publicPath: '../../' // 作用是设置打包过程中提取css的方法
  //   })
  // } else {
  //   return ['vue-style-loader'].concat(loaders)
  // }

  // 2.替换成新的内容
  return [options.extract ? MiniCssExtractPlugin.loader : 'vue-style-loader'].concat(loaders)
  //  ...
}

改到这项目执行npm run dev应该能正常运行起来了

4. 其他报错问题解决

(1)打开页面空白,控制台 报错 webpack3升级为webpack4实践记录

  • 原因:export和import共用了导致不兼容引起的;
  • 解决办法:
    • 安装插件 npm install babel-plugin-transform-es2015-modules-commonjs
    • 然后在根目录 .babelrc文件中配置 webpack3升级为webpack4实践记录
      { "plugins": ["transform-es2015-modules-commonjs"] }
      
  • 即可解决,项目运行成功

二、调试打包可用

(一)打包前

1. 把ExtractTextPlugin替换成MiniCssExtractPlugin

  • 该插件用于把CSS提取到独立的文件中,这样JS和CSS可以作为2个请求并行下载,页面打开速度可以再快一些。
  • 在以前的webpack版本中都是使用extract-text-webpack-plugin,但是在webpack4中已经改为mini-css-extract-plugin了
  • 涉及文件:webpack.prop.conf.js
  • 打包配置中涉及的extract-text-webpack-plugin都替换成mini-css-extract-plugin 项目
// webpack.prop.conf.js文件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const webpackConfig = merge(baseWebpackConfig, {
  //  ...
  // plugins(和output同级)
  plugins: [
    // 1.找到下面的内容注释掉或删除
    // new ExtractTextPlugin({
    //  filename: utils.assetsPath('css/[name].[contenthash].css'),
    //  allChunks: true
    // }),

    // 2.替换成新的内容
    new MiniCssExtractPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css'),
      ignoreOrder: true
    })
  ]
  //  ...
})

2. uglifyjs-webpack-plugin用法变化

  • 该插件用于压缩js代码,最终编译结果就是只有一行内容的密密麻麻的很长的JS文件
  • 涉及文件:webpack.prop.conf.js
// webpack.prop.conf.js文件
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const webpackConfig = merge(baseWebpackConfig, {
  //  ...
  // 1.原来写在plugins中
  plugins: [
    // 启用代码压缩
    // new UglifyJsPlugin({
    // // minimize: true,
    // uglifyOptions: {
    //   compress: {
    //     warnings: false,
    //     drop_console: true,
    //     drop_debugger: true, // 过滤debugger,
    //     pure_funcs: ['console.log'] // 移除console
    //   }
    // },
    // sourceMap: config.build.productionSourceMap,
    // parallel: true
    // }),
  ],
  // 2.现在移到optimization中
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        parallel: true, // 开启多进程压缩。
        uglifyOptions: {
          output: { comments: false },
          compress: {
            warnings: false,
            drop_debugger: true, // 是否清除debugger
            drop_console: true // 是否清除所有console
            // pure_funcs: ['console.log','console.info','console.warn','console.debug'] //drop_console 设置false,需要特殊清除的
          }
        },
        sourceMap: config.build.productionSourceMap
      })
    ]
  }
  // ...
})

3. 去掉CommonsChunkPlugin 改用splitChunks

  • 涉及文件:webpack.prop.conf.js
  • 去掉 plugins中 所有CommonsChunkPlugin的配置
  • webpack4 使用 splitChunks & runtimeChunks进行分包
// webpack.prop.conf.js文件
const webpackConfig = merge(baseWebpackConfig, {
  // ...
  // plugins(和output同级)
  plugins: [],
  optimization: {
    // minimizer: [...],
    // 从webpack.optimize.CommonsChunkPlugin到config.optimization.splitChunk
    splitChunks: {
      chunks: 'async',
      minSize: 30000, // 大于30KB才单独分离成chunk
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      name: true,
      cacheGroups: {
        default: {
          priority: -20,
          reuseExistingChunk: true
        },
        // 生成 vendors.js,
        vendors: {
          name: 'vendors',
          test: /[\\/]node_modules[\\/]/,
          priority: 10,
          chunks: 'all'
          // enforce: true
        },
        common: {
          name: 'common',
          chunks: 'all',
          minChunks: 2,
          minSize: 0,
          maxInitialRequests: 5 // The default limit is too small to showcase the effect
        }
        // echarts: {
        //   name: 'echarts',
        //   chunks: 'all',
        //   // 对echarts进行单独优化,优先级较高
        //   priority: 20,
        //   test: function(module) {
        //     const context = module.context;
        //     return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >=
        //               0)
        //   }
        // }
      }
    },
    // 生成 manifest.js
    runtimeChunk: {
      name: 'manifest'
    }
  }
  // ...
})
  • 修改 HtmlWebpackPlugin 的 chunksSortModenew
HtmlWebpackPlugin({ chunksSortMode: 'dependency' }) //'dependency'修改为none或auto

改到这里就可以开始打包了,执行npm run build

(二)打包时

1. 提示:caniuse-lite is outdated

webpack3升级为webpack4实践记录

  • 提示:Browserslist:caniuse-lite is outdated. Please run next command `npm update
  • 解决方案
    • 先删了node_modules/caniuse-lite和node_modules/browserslist两个文件夹
    • 然后运行下面的命令:npm i --save-dev caniuse-lite browserslist
    • 再执行:npm update

(三)打包后

1. 出现警告大小超出限制

webpack3升级为webpack4实践记录

  • 涉及文件:webpack.prop.conf.js
  • 解决方案: 添加performance
 performance: {
    hints: 'warning',
    // 入口起点的最大体积 整数类型(以字节为单位)
    maxEntrypointSize: 50000000,
    // 生成文件的最大体积 整数类型(以字节为单位 300k)
    maxAssetSize: 30000000,
    // 只给出 js 文件的性能提示
    assetFilter: function(assetFilename) {
      return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
    }
  },

2. webpack打包后,登录页背景图片不显示

  • 涉及文件:webpack.base.conf.js
  • 解决方案:注释掉 limit 或值改大
// webpack.base.conf
module:{
  rules: [
    // ....
    {
      test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        // limit: 10000,// 放开打包完登录页面图片不会显示
        limit: 10 * 1024, // 放开打包完登录页面图片不会显示
        name: utils.assetsPath('img/[name].[hash:7].[ext]')
      }
    }
    // ....
  ]
}

3. 出现icon图标不显示的问题

webpack3升级为webpack4实践记录

module:{
  rules: [ 
    // ...  
         {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            loader: 'url-loader',
            options: {
              limit: 10 * 1024,
              publicPath: '../../', // 加入publicPath: '../../
              // outputPath: 'img', // 输出到img
              name: utils.assetsPath('img/[name].[hash:7].[ext]')
            }
         },
    {
      test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        publicPath: '../../', // 加入publicPath: '../../
        name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
      }
    }
    // ...  
  ]  
}

三、其他配置

(一) 混淆插件 webpack-obfuscator

1. 配置

  • 涉及文件:webpack.prop.conf.js
  • 该插件最低支持到webpack4;
  • 安装:npm install --save-dev webpack-obfuscator@2.6.0 javascript-obfuscator@2.5.0
    • 注意:这是WebPack@4环境下适用的版本,Webpack5具体版本自行查阅
  • 配置:
    • 其他混淆度配置
      • 高度混淆:低性能,性能比没有模糊处理慢 50-100%
      • 中等混淆:最佳性能:性能比没有模糊处理慢 30-35%
      • 低度混淆:高性能,性能稍微慢于没javascript教程有混淆(目前选用)
// webpack.prop.conf.js文件
const WebpackObfuscator = require('webpack-obfuscator');//代码混淆
const webpackConfig = merge(baseWebpackConfig, {
  //  ...
  // plugins(和output同级)
  plugins: [
    // 混淆代码(以下为低混淆配置)
    new WebpackObfuscator({
      // 压缩代码
      compact: true,
      // 是否启用控制流扁平化(降低1.5倍的运行速度)
      controlFlowFlattening: false,
      // 随机的死代码块(增加了混淆代码的大小)
      deadCodeInjection: false,
      // 此选项几乎不可能使用开发者工具的控制台选项卡
      debugProtection: false,
      // 如果选中,则会在“控制台”选项卡上使用间隔强制调试模式,从而更难使用“开发人员工具”的其他功能。
      debugProtectionInterval: false,
      // 通过用空函数替换它们来禁用console.log,console.info,console.error和console.warn。这使得调试器的使用更加困难。
      disableConsoleOutput: true,
      // 标识符的混淆方式 hexadecimal(十六进制) mangled(短标识符)
      identifierNamesGenerator: 'hexadecimal',
      log: false,
      // 是否启用全局变量和函数名称的混淆
      renameGlobals: false,
      // 通过固定和随机(在代码混淆时生成)的位置移动数组。这使得将删除的字符串的顺序与其原始位置相匹配变得更加困难。如果原始源代码不小,建议使用此选项,因为辅助函数可以引起注意。
      rotateStringArray: true,
      // 混淆后的代码,不能使用代码美化,同时需要配置 cpmpat:true;
      selfDefending: true,
      // 删除字符串文字并将它们放在一个特殊的数组中
      stringArray: true,
      // stringArrayEncoding: false,// !!!写false会报错
      stringArrayEncoding: ['base64'],
      stringArrayThreshold: 0.75,
      // 允许启用/禁用字符串转换为unicode转义序列。Unicode转义序列大大增加了代码大小,并且可以轻松地将字符串恢复为原始视图。建议仅对小型源代码启用此选项。
      unicodeEscapeSequence: false
    }, [])// 数组内是需要排除的文件
  ]
  //  ...
})

2. 报错问题解决

webpack3升级为webpack4实践记录

  • 将配置项stringArrayThreshold值false改为base64
  plugins: [
    // 混淆代码(以下为低混淆配置)
    new WebpackObfuscator({
      // ...
      // stringArrayEncoding: false,// !!!写false会报错
      stringArrayEncoding: ['base64'],
      // ...
    }, [])// 数组内是需要排除的文件
 ]

四、涉及文件的完整代码

1. 文件 utils.js

'use strict'
const path = require('path')
const config = require('../config')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

const packageConfig = require('../package.json')
// const isBuild = process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'staging'
const isBuild = ['production', 'test', 'staging'].includes(process.env.NODE_ENV)

exports.assetsPath = function(_path) {
  const assetsSubDirectory = isBuild// process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory

  return path.posix.join(assetsSubDirectory, _path)
}

exports.cssLoaders = function(options) {
  options = options || {}

  const cssLoader = {
    loader: 'css-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }

  const postcssLoader = {
    loader: 'postcss-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }

  // generate loader string to be used with extract text plugin
  function generateLoaders(loader, loaderOptions) {
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]

    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    // if (options.extract) {
    //   return ExtractTextPlugin.extract({
    //     use: loaders,
    //     fallback: 'vue-style-loader',
    //     publicPath: '../../' // 作用是设置打包过程中提取css的方法
    //   })
    // } else {
    //   return ['vue-style-loader'].concat(loaders)
    // }
    return [options.extract ? MiniCssExtractPlugin.loader : 'vue-style-loader'].concat(loaders)
  }

  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }
}

// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function(options) {
  const output = []
  const loaders = exports.cssLoaders(options)

  for (const extension in loaders) {
    const loader = loaders[extension]
    output.push({
      test: new RegExp('\\.' + extension + '$'),
      use: loader
    })
  }

  return output
}

exports.createNotifierCallback = () => {
  const notifier = require('node-notifier')

  return (severity, errors) => {
    if (severity !== 'error') return

    const error = errors[0]
    const filename = error.file && error.file.split('!').pop()

    notifier.notify({
      title: packageConfig.name,
      message: severity + ': ' + error.name,
      subtitle: filename || ''
    })
  }
}

2. 文件 webpack.base.conf.js

'use strict'
// 存放基础的配置文件
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const { VueLoaderPlugin } = require('vue-loader') // 新增

const isBuild = process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'staging'
function resolve(dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  // 代码混淆压缩:webpack4中已经内置了UglifyJs插件,当打包模式参数mode设置为production时就会自动开启
  mode: isBuild ? 'production' : 'development',
  context: path.resolve(__dirname, '../'),
  entry: {
    app: ['babel-polyfill', './src/main.js']
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: isBuild// process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src')
    }
  },
  plugins: [
    new VueLoaderPlugin()
  ],
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10 * 1024, // TODO:放开打包完登录页面图片不会显示
          publicPath: '../../',
          // outputPath: 'img', // 输出到img
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          publicPath: '../../',
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  },
  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).
    setImmediate: false,
    // prevent webpack from injecting mocks to Node native modules
    // that does not make sense for the client
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  }
}

3. 文件 webpack.prod.conf.js

'use strict'
// 打包环境配置
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')// 合并config
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')// 压缩css文件
// 该插件用于压缩js代码,最终编译结果就是只有一行内容的密密麻麻的很长的JS文件
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
// 该插件用于把CSS提取到独立的文件中,这样JS和CSS可以作为2个请求并行下载,页面打开速度可以再快一些。
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
/* 加载env Start */
const NODE_ENV = process.env.NODE_ENV || 'staging'// (在package.json中的script中通过“cross-env NODE_ENV=环境变量”指定环境)
let env // = require('../config/test.env')// 加载测试环境配置
switch (NODE_ENV) {
  case 'production':// 打包生产环境
    env = require('../config/prod.env') // 加载对应环境的变量
    break;
  case 'test':// 打包测试环境
    env = require('../config/test.env')
    break;
  case 'staging':// 打包开发环境配置
    env = require('../config/staging.env') // 加载对应环境的变量
    break;
  default:
    env = require('../config/staging.env') // 加载对应环境的变量
}
/* 加载env end */

const webpackConfig = merge(baseWebpackConfig, {
  performance: {
    hints: 'warning',
    // 入口起点的最大体积 整数类型(以字节为单位)
    maxEntrypointSize: 50000000,
    // 生成文件的最大体积 整数类型(以字节为单位 300k)
    maxAssetSize: 30000000,
    // 只给出 js 文件的性能提示
    assetFilter: function(assetFilename) {
      return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
    }
  },
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true,
      usePostCSS: true
    })
  },
  devtool: config.build.productionSourceMap ? config.build.devtool : false,
  output: {
    publicPath: './',
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].min.js'),
    chunkFilename: utils.assetsPath('js/[name].min.js')
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': env// 传入配置
    }),
    // extract css into its own file
    new MiniCssExtractPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css'),
      // chunkFilename: '[id].[hash].css',
      ignoreOrder: true
    }),
    // Compress extracted CSS. We are using this plugin so that possible
    // duplicated CSS from different components can be deduped.
    // 压缩CSS文件
    new OptimizeCSSPlugin({
      cssProcessorOptions: config.build.productionSourceMap
        ? { safe: true, map: { inline: false }}
        : { safe: true }
    }),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      chunks: ['manifest', 'vendor', 'app'],
      minify: {// 压缩HTML文件
        removeComments: true, // 移除HTML中的注释
        collapseWhitespace: true, // 删除空白符与换行符
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunksPlugin
      chunksSortMode: 'auto'
    }),
    // keep module.id stable when vendor modules does not change
    new webpack.HashedModuleIdsPlugin(),
    // enable scope hoisting
    // new webpack.optimize.ModuleConcatenationPlugin(),
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../src/static/js'),
        to: config.build.assetsSubDirectory + '/js',
        ignore: ['.*']
      }
    ]),
    // 提供全局的变量,在模块中使用无需用require引入
    new webpack.ProvidePlugin({
      cube: [path.resolve('src/utils/Cube.js'), 'default'],
      $config: [path.resolve('src/config/index.js'), 'default'],
      $messages: [path.resolve('src/locales/zh_CN/messages.js'), 'default']
    })
  ],
  optimization: {
    minimize: true, // 正常情况下开发环境为false,生产环境设置为true;表示是否开启优化。
    usedExports: true, // 开启 Tree Shaking 功能,用于删除未被使用的代码。
    minimizer: [
      // 代码压缩
      new UglifyJsPlugin({
        sourceMap: config.build.productionSourceMap,
        parallel: true, // 开启多进程压缩。
        uglifyOptions: {
          output: { comments: false },
          compress: {
            // dead_code: true, // 移除没被引用的代码
            warnings: false,
            drop_debugger: true, // 是否清除debugger
            drop_console: true // 是否清除所有console
            // pure_funcs: ['console.log','console.info','console.warn','console.debug'] //drop_console 设置false,需要特殊清除的
          }
        }
      })
    ],
    // 从webpack.optimize.CommonsChunkPlugin到config.optimization.splitChunk
    splitChunks: {
      chunks: 'async', // 默认只作用于异步模块,为`all`时对所有模块生效,`initial`对同步模块有效
      minSize: 30000, // 大于30KB才单独分离成chunk
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      name: true,
      cacheGroups: {
        default: {
          priority: -20,
          reuseExistingChunk: true
        },
        // 生成 vendors.js,node_modules中的第三方引用被分离了出来,放在了vendors.js
        vendors: {
          name: 'vendors',
          test: /[\\/]node_modules[\\/]/,
          priority: 10,
          // minChunks:1,//敲黑板
          chunks: 'all'
          // enforce: true
        },
        common: {
          name: 'common',
          chunks: 'all',
          minChunks: 2,
          minSize: 0,
          maxInitialRequests: 5 // The default limit is too small to showcase the effect
        }
        // echarts: {
        //   name: 'echarts',
        //   chunks: 'all',
        //   // 对echarts进行单独优化,优先级较高
        //   priority: 20,
        //   test: function(module) {
        //     const context = module.context;
        //     return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >=
        //               0)
        //   }
        // }
      }
    },
    // 生成 manifest.js
    // 配置 Webpack 为每个入口添加一个额外的 chunk,用于存放公共代码和运行时代码。这个选项可以有效减少打包后的文件大小,提高网站性能
    runtimeChunk: {
      name: 'manifest'
    }
  }
})

if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')
  // 代码压缩打包
  webpackConfig.plugins.push(
    // 此插件不能使用太高的版本,否则报错:TypeError: Cannot read property 'tapPromise' of undefined
    new CompressionWebpackPlugin({
      filename: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8,
      // 是否删除原有静态资源文件,即只保留压缩后的.gz文件,建议这个置为false,还保留源文件。以防:
      // 假如出现访问.gz文件访问不到的时候,还可以访问源文件双重保障
      deleteOriginalAssets: false
    })
  )
}
// 是否混淆代码
if (config.build.webpackObfuscator) {
  const WebpackObfuscator = require('webpack-obfuscator');// 代码混淆
  // 代码压缩打包
  webpackConfig.plugins.push(
    // 混淆代码
    new WebpackObfuscator({
      // 压缩代码
      compact: true,
      // 是否启用控制流扁平化(降低1.5倍的运行速度)
      controlFlowFlattening: false,
      // 随机的死代码块(增加了混淆代码的大小)
      deadCodeInjection: false,
      // 此选项几乎不可能使用开发者工具的控制台选项卡
      debugProtection: false,
      // 如果选中,则会在“控制台”选项卡上使用间隔强制调试模式,从而更难使用“开发人员工具”的其他功能。
      debugProtectionInterval: false,
      // 通过用空函数替换它们来禁用console.log,console.info,console.error和console.warn。这使得调试器的使用更加困难。
      disableConsoleOutput: true,
      // 标识符的混淆方式 hexadecimal(十六进制) mangled(短标识符)
      identifierNamesGenerator: 'hexadecimal',
      log: false,
      // 是否启用全局变量和函数名称的混淆
      renameGlobals: false,
      // 通过固定和随机(在代码混淆时生成)的位置移动数组。这使得将删除的字符串的顺序与其原始位置相匹配变得更加困难。如果原始源代码不小,建议使用此选项,因为辅助函数可以引起注意。
      rotateStringArray: true,
      // 混淆后的代码,不能使用代码美化,同时需要配置 cpmpat:true;
      selfDefending: true,
      // 删除字符串文字并将它们放在一个特殊的数组中
      stringArray: true,
      // stringArrayEncoding: false,
      stringArrayEncoding: ['base64'],
      stringArrayThreshold: 0.75,
      // 允许启用/禁用字符串转换为unicode转义序列。Unicode转义序列大大增加了代码大小,并且可以轻松地将字符串恢复为原始视图。建议仅对小型源代码启用此选项。
      unicodeEscapeSequence: false
    }, [])// 数组内是需要排除的文件
  )
}

if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

转载自:https://juejin.cn/post/7223688436430487589
评论
请登录