This project is not covered by Drupal’s security advisory policy.
S3FS Aggregation stores Drupal's aggregated CSS/JS files in Amazon S3 through the S3 File System module, and serves them straight from the s3fs host or CDN. It is meant for sites whose web servers have a read-only filesystem, such as containers on Kubernetes or ECS.
Why
Since Drupal 10.1, aggregated CSS/JS lives in the assets:// stream wrapper, a local directory. Each file is built when a browser first requests it. That needs a writable local disk on every web server, and s3fs does not take over assets:// (#3404738).
How it works
When s3fs takes over public:// ($settings['s3fs.use_s3_for_public']), the module swaps in:
- An
assets://stream wrapper that mapsassets://css/css_HASH.csstopublic://aggregation/RELEASE/css/css_HASH.css. Aggregates are stored and served like any other s3fs public file. - CSS/JS collection optimizers that write aggregates while the page renders. Core only prints aggregate URLs and builds a file when a request for it reaches Drupal. Requests to S3 or a CDN never do. A cache rebuild no longer deletes aggregates, so pages cached by a CDN keep working.
- A CSS optimizer that writes absolute
url()references, because the CSS is served from a different host than the images it points to.
Every release gets its own folder. Core names aggregates after library versions, not file contents, so a shared folder would let old and new web servers overwrite each other's files during a rolling deployment.
The module has no dependency on s3fs in its info file. Without s3fs, or with s3fs not taking over public:// (for example on a local environment), it changes nothing. With CSS/JS aggregation turned off, it has no effect either.
Difference from S3 File System for assets
S3 File System for assets also replaces the assets:// stream wrapper, but keeps aggregate URLs on Drupal's asset route. PHP then reads every CSS/JS file from S3 on every request, and core marks those responses private, no-store, so a CDN does not cache them.
| S3 File System for assets | S3FS Aggregation | |
|---|---|---|
| Aggregate URLs | Drupal's asset route | s3fs host / CDN |
| Who serves a file | PHP, reading it from S3 | S3 / CDN, no PHP |
| When a file is built | When requested | While the page renders |
| Storage | css/, js/ in the bucket root |
public://aggregation/RELEASE/ |
| Rolling deployments | Releases share file names | One folder per release |
| Cache rebuild | Deletes aggregates | Keeps aggregates |
CSS url() |
Relative | Absolute |
| Without s3fs | Requires s3fs | Does nothing, safe to keep enabled |
Requirements
- Drupal 10.3, 11 or 12 (Drupal 12 as soon as S3 File System supports it)
- S3 File System 3.x with
$settings['s3fs.use_s3_for_public'] = TRUE; - CSS and/or JS aggregation enabled
Configuration
There is no configuration UI. Optional settings in settings.php:
// Folder inside public:// for aggregates. Default: 'aggregation'. $settings['s3fs_aggregation.folder'] = 'aggregation'; // Release folder. Default: $settings['deployment_identifier'], or 'default'. // Must change on every deployment that changes CSS/JS. $settings['s3fs_aggregation.release'] = getenv('APP_RELEASE'); // Scheme and host prepended to url() references in aggregated CSS. // Default: the host of the request that builds the aggregate. $settings['s3fs_aggregation.css_url_base'] = 'https://www.example.com';
Old release folders are never deleted by the module. Expire them with an S3 lifecycle rule that is longer than your page cache lifetime.
Similar projects
- S3 File System for assets: see the comparison above.
- CDN: rewrites file URLs for origin-pull CDNs, but the origin still has to build and store aggregates.
- Advanced CSS/JS Aggregation: obsolete since Drupal 10.1.
Project information
- Project categories: Integrations, Performance
- Ecosystem: S3 File System
- Created by levmyshkin on , updated
This project is not covered by the security advisory policy.
Use at your own risk! It may have publicly disclosed vulnerabilities.
