admin管理员组

文章数量:1297054

I need help debugging Webpack's Compression Plugin.

SUMMARY OF PROBLEM

  • Goal is to enable asset pression and reduce my app's bundle size. Using the Brotli algorithm as the default, and gzip as a fallback for unsupported browsers.
  • I expected a content-encoding field within an asset's Response Headers. Instead, they're loaded without the field. I used the Chrome dev tools' network tab to confirm this. For context, see the following snippet:
  • No errors show in my browser or IDE when running locally.

WHAT I TRIED

  • Using different implementations for the pression plugin. See below list of approaches:
    1. (With Webpack Chain API)
config
 .plugin('brotliCompress')
     .use(CompressionWebpackPlugin, [{
       exclude: /.map$/,
       cache: true,
       algorithm: 'brotliCompress',
       test: /\.(js|css|html|svg)$/,
       threshold: 10240,
       minRatio: 0.8,
     }])
  1. (With Webpack Chain 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 pressing worse that this ratio are not processed
      }])
  1. (With Webpack Chain API)
config
  .plugin('CompressionPlugin')
      .use(CompressionWebpackPlugin)
  1. (Using vue-cli-plugin: pression) This fails due to a Missing generator error when I use vue invoke pression in response to an IDE console message after I run vue add pression as an alternative to using Webpack Chain API for pression configuration.
  pluginOptions: {
    pression: {
      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
      }
    }
  },
  1. Lastly, I tried setting the threshold field to 0 as well as raising it larger than 10k bytes.

POINTS OF SIGNIFICANCE

  • The above attempts didn't achieve the goal I stated in the first summary bullet and were used in place of the previous approaches tested.
  • I prioritized my efforts with Webpack Chain API since it resulted in no errors when rebuilding and running the app.

REFERENCED LINKS/DOCS

  • /
  • (similar generator issue with another plugin)
  • /
  • Use webpack-chain to do webpack configuration in vue.config.js, so how to use speed-measure-webpack-plugin plugin? (not a valid answer, but referenced syntax nonetheless)
  • Webpack prerender-spa-plugin with pression-webpack-plugin. index.html not pressed

CODE

vue.config.js

const path = require('path')
const CompressionWebpackPlugin = require('pression-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: {
  //   pression: {
  //     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 remeneded 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 pressing 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",
    "pression-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-pression": "~1.1.5",
    "vue-template-piler": "^2.6.11",
    "webpack": "^4.46.0"
  }

I appreciate all input. Thanks.

I need help debugging Webpack's Compression Plugin.

SUMMARY OF PROBLEM

  • Goal is to enable asset pression and reduce my app's bundle size. Using the Brotli algorithm as the default, and gzip as a fallback for unsupported browsers.
  • I expected a content-encoding field within an asset's Response Headers. Instead, they're loaded without the field. I used the Chrome dev tools' network tab to confirm this. For context, see the following snippet:
  • No errors show in my browser or IDE when running locally.

WHAT I TRIED

  • Using different implementations for the pression plugin. See below list of approaches:
    1. (With Webpack Chain API)
config
 .plugin('brotliCompress')
     .use(CompressionWebpackPlugin, [{
       exclude: /.map$/,
       cache: true,
       algorithm: 'brotliCompress',
       test: /\.(js|css|html|svg)$/,
       threshold: 10240,
       minRatio: 0.8,
     }])
  1. (With Webpack Chain 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 pressing worse that this ratio are not processed
      }])
  1. (With Webpack Chain API)
config
  .plugin('CompressionPlugin')
      .use(CompressionWebpackPlugin)
  1. (Using vue-cli-plugin: pression) This fails due to a Missing generator error when I use vue invoke pression in response to an IDE console message after I run vue add pression as an alternative to using Webpack Chain API for pression configuration.
  pluginOptions: {
    pression: {
      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
      }
    }
  },
  1. Lastly, I tried setting the threshold field to 0 as well as raising it larger than 10k bytes.

POINTS OF SIGNIFICANCE

  • The above attempts didn't achieve the goal I stated in the first summary bullet and were used in place of the previous approaches tested.
  • I prioritized my efforts with Webpack Chain API since it resulted in no errors when rebuilding and running the app.

REFERENCED LINKS/DOCS

  • https://webpack.js/plugins/pression-webpack-plugin/
  • https://github./neutrinojs/webpack-chain/tree/main
  • https://neutrinojs/webpack-chain/#config-plugins-adding
  • https://github./nklayman/vue-cli-plugin-electron-builder/issues/500 (similar generator issue with another plugin)
  • https://webpack.js/plugins/pression-webpack-plugin/
  • Use webpack-chain to do webpack configuration in vue.config.js, so how to use speed-measure-webpack-plugin plugin? (not a valid answer, but referenced syntax nonetheless)
  • https://github./vuejs/vue-cli/issues/6091#issuement-738536334
  • Webpack prerender-spa-plugin with pression-webpack-plugin. index.html not pressed

CODE

vue.config.js

const path = require('path')
const CompressionWebpackPlugin = require('pression-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: {
  //   pression: {
  //     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 remeneded 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 pressing 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",
    "pression-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-pression": "~1.1.5",
    "vue-template-piler": "^2.6.11",
    "webpack": "^4.46.0"
  }

I appreciate all input. Thanks.

Share edited Sep 30, 2021 at 14:45 Dan der Mensch asked Sep 22, 2021 at 17:43 Dan der MenschDan der Mensch 3322 silver badges14 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5 +50

It seems like the pression-webpack-plugin only presses files, but it doesn't automatically configure the dev server to serve the pressed files in place of the original file.

However, you can manually setup a middleware via vue.config.js's devServer option (passed through to webpack-dev-server) to do this:

  1. Rewrite all .js requests that accept br encoding to append .br to the original URL, which matches the filename setting given to pression-webpack-plugin. This effectively fetches the .br file pressed by the plugin.

  2. Set response headers to indicate the br content encoding and application/javascript content type so that browsers could understand how to process the file.

Vue CLI 5 (Webpack 5)

Use devServer.setupMiddlewares:

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

module.exports = {
  transpileDependencies: true,
  configureWebpack: {
    plugins: [
      new CompressionPlugin({   1️⃣
        filename: '[path][base].br',
        algorithm: 'brotliCompress',
        test: /\.js$/,
      })
    ]
  },
  devServer: {
    setupMiddlewares(middlewares, devServer) {
      if (!devServer) {
        throw new Error('webpack-dev-server is not defined')
      }

      middlewares.unshift({
        name: 'serve-brotli-js',
        path: '*.js',
        middleware: (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()
        }
      })

      return middlewares
    }
  }
}

Vue CLI 4 (Webpack 4)

Use devServer.before:

Note: The only difference from Webpack 5 is the Express app is directly passed as the argument to devserver.before().

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

GitHub demo

It's not clear which server is serving up these assets. If it's Express, looking at the screenshot with the header X-Powered-By, https://github./expressjs/pression/issues/71 shows that Brotli support hasn't been added to Express yet.

There might be a way to just specify the header for content-encoding manually though.

Add these in your nginx.conf file,If the client supports gzip Parsing , So as long as the server can return gzip Can be enabled gzip

gzip on; #  Turn on Gzip
gzip_static on; #  Turn on static file pression 
gzip_min_length  1k; #  Inpressible critical value , Greater than 1K It s only a matter of time 
gzip_buffers     4 16k;
gzip_p_level 5;
gzip_types     application/javascript application/x-javascript application/xml application/xml+rss application/x-httpd-php text/plain text/javascript text/css image/jpeg image/gif image/png; #  The type of file to be pressed 
gzip_http_version 1.1;
gzip_vary on;
gzip_proxied   expired no-cache no-store private auth;
gzip_disable   "MSIE [1-6]\.";

本文标签: javascriptVuejs Webpack Compression Plugin not compressingStack Overflow