Title: File concatenation and minification
Author: WordPress VIP Documentation
Published: December 23, 2020
Last modified: July 1, 2026

---

 1. [VIP MU plugins](https://docs.wpvip.com/vip-go-mu-plugins/)
 2. File concatenation and minification

#  File concatenation and minification

By default, if [enqueued](https://developer.wordpress.org/themes/basics/including-css-javascript/#enqueuing-scripts-and-styles),
an application’s JavaScript and CSS files are concatenated in order to reduce the
number of requests that occur on a single page load. CSS files are minified as well
as concatenated, which reduces file size by removing unnecessary white space.

 * Logic for concatenation is handled by the [nginx-http-concat](https://github.com/Automattic/nginx-http-concat)
   plugin.
 * Concatenated assets can be identified in the “Network” tab of a browser inspector
   by request paths beginning with `/_static/??`.
 * [Concatenated assets are cached by NGINX](https://docs.wpvip.com/static-asset-caching/)
   with a [`Cache-Control` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)
   set to `cache-control: max-age=31536000` (1 year). This cache is busted when 
   resource versions are updated.
 * If a VIP-concatenated asset is a bundle of over 150 assets, it will return a 
   status 400 response. To fix this issue, [disable concatenation](https://docs.wpvip.com/vip-go-mu-plugins/file-concatenation-and-minification/#h-disabling-concatenation).

The responses that are generated by VIP sites are served from a global network of
[edge cache server](https://docs.wpvip.com/vip-platform/edge-cache/) locations. 
This allows a majority of a site’s traffic, including concatenated scripts and styles,
to be served directly from an edge location closest to a site’s visitors without
ever hitting a line of PHP. This results in the low-latency and high-performance
impact expected from a CDN.

## Limitations

Files that are enqueued from a resource outside of [an application’s wpcomvip GitHub repository](https://docs.wpvip.com/wpcomvip-github-repository/)
will not be minified or concatenated. This includes:

 * Files enqueued from an application’s `/uploads` directory (which is mapped to
   [ the external VIP File System object store](https://docs.wpvip.com/vip-file-system/)).
 * All third-party resources.

Some third-party performance scans may not recognize VIP’s CDN as a result of concatenated
files being served from the same domain as the VIP site.

## Versioning to bust the cache

By default, the VIP Platform concatenates JavaScript and CSS files that are enqueued
in an application’s codebase. [The concatenated files are cached](https://docs.wpvip.com/static-asset-caching/)
with a [`Cache-Control` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)
set to `cache-control: max-age=31536000` (1 year).

To bust the cache on deployment, the `$ver` value in the enqueue must be incrementally
updated when changes are made to enqueued JavaScript and CSS files. An updated `
$ver` value effectively generates a new and unique static URL for the concatenated
assets. The `$ver` value can be updated in functions such as [`wp_enqueue_script()`](https://developer.wordpress.org/reference/functions/wp_enqueue_script/),
[`wp_enqueue_style()`](https://developer.wordpress.org/reference/functions/wp_enqueue_style/),
[`wp_register_script()`](https://developer.wordpress.org/reference/functions/wp_register_script/),
and `[wp_register_style()](https://developer.wordpress.org/reference/functions/wp_register_style/)`.

    ```lang-php
    // When changes are made to js/plugin.js the $ver variable should be incrementally updated.
    $ver = '1.1';
    wp_enqueue_script( 'plugin_script', plugins_url( 'js/plugin.js', __FILE__ ), array(), $ver );
    ```

Because file Input/Output (I/O) operations can be expensive, VIP does not recommend
using the function `filemtime()` to populate a value for `$ver` on production environments.

## Script tag attributes filter

_Accepted values:_ `defer` | `async` | `nomodule` | `crossorigin` | `integrity` 
| `type` | `nonce` | `referrerpolicy`

Script attributes such as `async` or `defer` can be added to concatenated scripts
with the [`js_concat_script_attributes` filter](https://github.com/Automattic/nginx-http-concat/blob/cda3f4cf09450c267657787de976d365fc30a845/jsconcat.php#L198).

In this example, the attributes `async` and `defer` are added to all concatenated
scripts:

    ```lang-php
    add_filter( 'js_concat_script_attributes', function( $args, $href, $js_array, $jsconcat ) {

        return stristr( $href, '_static' ) !== false ? [ 'async', 'defer' ] : [];

    }, 10, 4 );
    ```

## Enable or disable concatenation

Available filters can be used to exclude specific JavaScript or CSS files from concatenation
bundles. When enabling or disabling concatenation for JavaScript or CSS, consider
including `is_admin()` logic to specify if the filter will be applied to the front
end of a site, the WordPress Admin dashboard, or both.

For example, file concatenation in the WP Admin is enabled by default for CSS and
[disabled for JavaScript](https://github.com/Automattic/vip-go-mu-plugins/blob/develop/misc.php#L171-L176).
This code example demonstrates how to modify these default settings and disable 
CSS file concatenation only in WP Admin (leaving it enabled on the front end):

    ```lang-php
    // Disable CSS concatenation for WP Admin.

    if ( is_admin() ) {
    	add_filter( 'css_do_concat', '__return_false' );
    }
    ```

### `js_do_concat` filter

Example code to exclude specific JavaScript files from concatenation with the [`js_do_concat` filter](https://github.com/Automattic/nginx-http-concat/blob/master/jsconcat.php#L122):

    ```lang-php
    add_filter( 'js_do_concat', 'my_vip_js_concat_filter', 10, 2 );

    // Do not include my-script-handle in concatenated bundles.
    function my_vip_js_concat_filter( $do_concat, $handle ) {
        if ( 'my-script-handle' === $handle ) {
    		return false;
    	}
    	return $do_concat;
     }
    ```

To disable concatenation for _all_ JavaScript files, set the `js_do_concat` filter
to return `__return_false`:

    ```lang-php
    // Disable JS concatenation.
    add_filter( 'js_do_concat', '__return_false' );
    ```

### `css_do_concat` filter

Example code to exclude specific CSS files from concatenation with the [`css_do_concat` filter](https://github.com/Automattic/nginx-http-concat/blob/master/cssconcat.php#L91):

    ```lang-php
    add_filter( 'css_do_concat', 'my_vip_css_concat_filter', 10, 2 );

    // Do not include my-custom-css-handle in concatenated CSS bundles.
    function my_vip_css_concat_filter( $do_concat, $handle ) {
        if ( 'my-custom-css-handle' === $handle ) {
    		return false;
    	}
    	return $do_concat;
    }
    ```

To disable concatenation for _all_ CSS files, set the `css_do_concat` filter to 
return `__return_false`:

    ```lang-php
    // Disable CSS concatenation.
    add_filter( 'css_do_concat', '__return_false' );
    ```

## Enable for VIP Local Development Environment

By default, the [NGINX HTTP Concat](https://github.com/Automattic/nginx-http-concat)
plugin that handles [file concatenation and minification](https://docs.wpvip.com/vip-platform/file-concatenation-and-minification/)
is disabled on a [VIP Local Development Environment](https://docs.wpvip.com/vip-local-development-environment/).
If file concatenation is needed for local development and debugging, the plugin 
can be enabled by setting the `VIP_GO_ENABLE_HTTP_CONCAT` constant to `true` in `
vip-config.php`. Wrap the code in [environment-specific logic](https://docs.wpvip.com/infrastructure/environments/environment-specific-code/#h-using-vip-go-app-environment)
to prevent it from running on a VIP Platform environment.

For example:

vip-config/vip-config.php

    ```lang-php
    if ( defined( 'VIP_GO_APP_ENVIRONMENT' ) && 'local' === VIP_GO_APP_ENVIRONMENT ) {
        // Run this only on local
        define( 'VIP_GO_ENABLE_HTTP_CONCAT', true);
    }
    ```

## Troubleshooting

Query parameters can be added to a URL in the browser to disable concatenation and
help determine if a JavaScript error or CSS issue is related to concatenation.

Adding these parameters to an affected URL in the browser will load the individual
JavaScript or CSS files for the request instead of the static concatenated bundle.
These query parameters are only meant to be used for testing in a browser and **
should not be added to code**.

 * JavaScript: `concat_js=false`
 * CSS: `concat_css=false`

### Updated concatenated assets not loading as expected

It is possible for built assets and concatenation to cause short-term brokenness
in CSS and/or JavaScript when combined with full [page caching](https://docs.wpvip.com/caching/page-cache/).

Because previously concatenated bundles are cached at the edge, newly deployed changes
will usually reference a new bundle, while existing cached pages will reference 
an old one. If either needs to be reconstructed due to a cache miss, the enqueued
files must still be available on the server – the URL [contains the filenames](https://github.com/Automattic/nginx-http-concat/blob/master/ngx-http-concat.php#L98)(
usually compressed).

Because of this, avoid deleting older versions of those built files for at least
30 minutes so they can be used as needed. If 404s occur for previously-good bundles,
this is a likely cause – one of the component files is missing. When overwriting
these files, an old URL may suddenly contain the new assets even though the page
was generated before the deploy.

### Render-blocking resources flagged in Lighthouse

If Lighthouse is flagging render-blocking JavaScript or CSS, VIP’s file concatenation
may be a factor. Concatenated bundles are loaded together, which can block rendering
if any assets in the bundle are not needed for the initial page load.

To identify which assets are causing the issue, disable concatenation temporarily
using the query parameters `?concat_js=false` or `?concat_css=false` in your browser.
Once you’ve identified the offending assets, use the `js_do_concat` or `css_do_concat`
filters to exclude them from the bundle rather than disabling concatenation entirely.

Last updated: July 01, 2026