Vuejs Webpack压缩插件不压缩

Posted

技术标签:

【中文标题】Vuejs Webpack压缩插件不压缩【英文标题】:Vuejs Webpack Compression Plugin not compressing 【发布时间】:2021-11-16 04:49:35 【问题描述】:

我需要帮助调试 Webpack 的压缩插件。

问题摘要

目标是启用资产压缩并减少我的应用程序包的大小。使用 Brotli 算法作为默认算法,并将 gzip 作为不支持的浏览器的后备。 我希望资产的响应标头中有一个 content-encoding 字段。相反,它们是在没有字段的情况下加载的。我使用 Chrome 开发工具的网络选项卡来确认这一点。有关上下文,请参阅以下 sn-p: 在本地运行时,我的浏览器或 IDE 中没有显示错误。

我尝试了什么

对压缩插件使用不同的实现。请参阅下面的方法列表:
    (使用 Webpack 链 API)
config
 .plugin('brotliCompress')
     .use(CompressionWebpackPlugin, [
       exclude: /.map$/,
       cache: true,
       algorithm: 'brotliCompress',
       test: /\.(js|css|html|svg)$/,
       threshold: 10240,
       minRatio: 0.8,
     ])
    (使用 Webpack 链 API)
config
  .plugin('gzip')
      .use(CompressionWebpackPlugin, [
        algorithm: 'gzip',
        test: new RegExp('\\.(' + ['js', 'css'].join('|') + ')$'),
        threshold: 8192, // Assets larger than 8192 bytes are not processed
        minRatio: 0.8, // Assets compressing worse that this ratio are not processed
      ])
    (使用 Webpack 链 API)
config
  .plugin('CompressionPlugin')
      .use(CompressionWebpackPlugin)
    (使用 vue-cli-plugin:压缩)当我使用 vue invoke compression 响应 IDE 控制台消息后,由于 Missing generator 错误而失败运行 vue add compression 作为使用 Webpack Chain API 进行压缩配置的替代方案。
  pluginOptions: 
    compression: 
      brotli: 
        filename: '[file].br[query]',
        algorithm: 'brotliCompress',
        include: /\.(js|css|html|svg|json)(\?.*)?$/i,
        minRatio: 0.8,
      ,
      gzip: 
        filename: '[file].gz[query]',
        algorithm: 'gzip',
        include: /\.(js|css|html|svg|json)(\?.*)?$/i,
        minRatio: 0.8
      
    
  ,
    最后,我尝试将阈值字段设置为 0 并将其提高到大于 10k 字节。

意义点

上述尝试未达到我在第一个摘要项目符号中所述的目标,并被用来代替之前测试的方法。 我优先考虑使用 Webpack Chain API,因为它在重新构建和运行应用程序时不会导致任何错误。

参考链接/文档

https://webpack.js.org/plugins/compression-webpack-plugin/ https://github.com/neutrinojs/webpack-chain/tree/main https://neutrinojs.org/webpack-chain/#config-plugins-adding https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/500(与另一个插件类似的生成器问题) https://webpack.js.org/plugins/compression-webpack-plugin/ Use webpack-chain to do webpack configuration in vue.config.js, so how to use speed-measure-webpack-plugin plugin?(不是一个有效的答案,但仍然引用了语法) https://github.com/vuejs/vue-cli/issues/6091#issuecomment-738536334 Webpack prerender-spa-plugin with compression-webpack-plugin. index.html not compressed

代码

vue.config.js

const path = require('path')
const CompressionWebpackPlugin = require('compression-webpack-plugin')

function resolve (dir) 
  return path.join(__dirname, dir)


module.exports = 
  /* ....shortened for brevity */

  // Compress option VI (with vue cli plugin, generator bug when invoked)
  // pluginOptions: 
  //   compression: 
  //     brotli: 
  //       filename: '[file].br[query]',
  //       algorithm: 'brotliCompress',
  //       include: /\.(js|css|html|svg|json)(\?.*)?$/i,
  //       minRatio: 0.8,
  //     ,
  //     gzip: 
  //       filename: '[file].gz[query]',
  //       algorithm: 'gzip',
  //       include: /\.(js|css|html|svg|json)(\?.*)?$/i,
  //       minRatio: 0.8
  //     
  //   
  // ,

  chainWebpack: config => 
    config
      .resolve.alias
        .set('@', resolve('src'))

    config
      .plugins.delete('prefetch') 
        
    config
      .optimization.splitChunks()

    config
      .output
      .chunkFilename('[id].js')

    // The below configurations are recommeneded only in prod.
    // config.when(process.env.NODE_ENV === 'production', config =>  config... )

    // Compress option VII
    // config
      // .plugin('gzip')
      // .use(CompressionWebpackPlugin, [
      //   algorithm: 'gzip',
      //   test: new RegExp('\\.(' + ['js', 'css'].join('|') + ')$'),
      //   threshold: 8192, // Assets larger than 8192 bytes are not processed
      //   minRatio: 0.8, // Assets compressing worse that this ratio are not processed
      // ])

    // Compress option VIII
    // config
      // .plugin('CompressionPlugin')
      // .use(CompressionWebpackPlugin)

    config
      .plugin('brotliCompress')
      .use(CompressionWebpackPlugin, [
        exclude: /.map$/,
        // deleteOriginalAssets: true,
        cache: true,
        algorithm: 'brotliCompress',
        test: /\.(js|css|html|svg)$/,
        threshold: 10240,
        minRatio: 0.8,
      ])
  ,

package.json

"dependencies": 
    "@auth0/auth0-spa-js": "^1.15.0",
    "audio-recorder-polyfill": "^0.4.1",
    "compression-webpack-plugin": "^6.0.0",
    "core-js": "^3.6.5",
    "dotenv": "^8.2.0",
    "dotenv-expand": "^5.1.0",
    "moment": "^2.29.1",
    "register-service-worker": "^1.7.1",
    "uuid": "^3.4.0",
    "vue": "^2.6.11",
    "vue-loader": "^15.9.8",
    "vue-router": "^3.5.1",
    "vuex": "^3.6.2"
  ,
  "devDependencies": 
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-pwa": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "vue-cli-plugin-compression": "~1.1.5",
    "vue-template-compiler": "^2.6.11",
    "webpack": "^4.46.0"
  

感谢所有的意见。谢谢。

【问题讨论】:

【参考方案1】:

compression-webpack-plugin 似乎只压缩文件,但它不会自动配置开发服务器以提供压缩文件来代替原始文件。

但是,您可以通过vue.config.jsdevServer option(传递给webpack-dev-server)手动设置中间件来执行此操作:

    重写所有接受br 编码的.js 请求,以将.br 附加到原始URL,这与filename 给定的compression-webpack-plugin 设置相匹配。这有效地获取了插件压缩的.br 文件。

    设置响应标头以指示 br content encoding 和 application/javascript content type 以便浏览器可以了解如何处理文件。

Vue CLI 5 (Webpack 5)

使用devServer.onBeforeSetupMiddleware:

// vue.config.js
const CompressionPlugin = require('compression-webpack-plugin')

module.exports = 
  transpileDependencies: true,
  configureWebpack: 
    plugins: [
      new CompressionPlugin(   1️⃣
        filename: '[path][base].br',
        algorithm: 'brotliCompress',
        test: /\.js$/,
      )
    ]
  ,
  devServer: 
    onBeforeSetupMiddleware( app ) 
      app.use('*.js', (req, res, next) => 
        if (req.get('Accept-Encoding')?.includes('br')) 
          1️⃣
          req.url += '.br'

          2️⃣
          res.set('Content-Encoding', 'br')
          res.set('Content-Type', 'application/javascript; charset=utf-8')
        
        next()
      )
    
  

Vue CLI 4 (Webpack 4)

使用devServer.before:

注意:与 Webpack 5 的唯一区别是 Express app 直接作为参数传递给 devserver.before()

// vue.config.js
⋮
module.exports = 
  ⋮
  devServer: 
    before(app) 
      // same code as Webpack 5 above
    
  

GitHub demo

【讨论】:

毫无疑问,我正在寻找的回应,谢谢托尼。我将参考代码示例和共享的文档,以增加我对 webpack 的了解。感谢您的解决方案!【参考方案2】:

目前尚不清楚哪个服务器正在提供这些资产。如果是 Express,查看带有标题 X-Powered-By、https://github.com/expressjs/compression/issues/71 的屏幕截图表明,尚未将 Brotli 支持添加到 Express 中。

可能有一种方法可以手动指定 content-encoding 的标头。

【讨论】:

你的回复让我学到了一些东西@wegry,在进一步研究了 webpack 如何提供应用程序后,我发现它确实使用了 express。不幸的是,即使在使用方法#2(使用 gzip 算法)以及为什么它没有实现最终目标之后,问题仍然存在。您能否通过手动指定内容编码的标头以及如何触发压缩来添加更多上下文?我重视你的回应。 @DanderMensch tony19 的回复进一步详细说明了服务器如何与浏览器通信以处理 brotli 编码。要点是服务器必须确定生产 vue 构建中的内容编码。

以上是关于Vuejs Webpack压缩插件不压缩的主要内容,如果未能解决你的问题,请参考以下文章

webpack各类压缩

webpack插件:压缩打包文件

webpack 如何压缩文件

webpack 如何压缩文件

webpack插件filemanager-webpack-plugin(将dist文件夹自动压缩成生成dist.zip压缩包)

在webpack用插件uglifyjs-webpack-plugin压缩ES6语法