Overview
The StaticResource metadata type (staticresources/<Name>.resource-meta.xml) stores static files—third-party JavaScript libraries (Chart.js, D3.js), custom CSS stylesheets, SVG/PNG graphics, custom web fonts, and JSON test payload fixtures—directly inside your Salesforce org so they can be served from Salesforce’s Content Delivery Network (CDN) without violating Content Security Policy (CSP) or Lightning Web Security (LWS).
One of the best productivity features of Salesforce DX source format is unpacked ZIP Static Resources. Instead of committing opaque binary .zip files into Git, you can place a regular folder (staticresources/chartJsBundle/) next to chartJsBundle.resource-meta.xml (with <contentType>application/zip</contentType>). When you run sf project deploy start, the CLI zips the folder on the fly; when you run sf project retrieve start, the CLI extracts the archive back into clean, diffable source files.
As shown in the workflow above, unpacked folders in staticresources/ compress automatically during CLI deployment and serve both LWC frontend components (@salesforce/resourceUrl) and Apex unit tests (StaticResourceCalloutMock).
Prerequisites
- Permissions: “Customize Application” and “Modify Metadata Through Metadata API Functions” permissions.
- LWS Compatibility: Any third-party JavaScript library uploaded as a
StaticResourceand loaded vialoadScript()in LWC must comply with Lightning Web Security (LWS) and strict mode JavaScript. - API Version: Verified against API version
68.0(Winter ’27).
StaticResource XML Metadata Fields
Each StaticResource in force-app/main/default/staticresources/ consists of the asset file (or unpacked folder) and a <ResourceName>.resource-meta.xml file:
| XML Element | Type | Required | Valid Values & Best Practice |
|---|---|---|---|
cacheControl |
StaticResourceCacheControl |
✅ Yes | Private (cached per user session; default for internal assets and JSON test mocks) or Public (cached on CDN; best for Experience Cloud fonts/logos). |
contentType |
string |
✅ Yes | Standard MIME type: application/zip, application/json, text/javascript, text/css, image/svg+xml, image/png. |
description |
string |
No | Documents the library version (e.g., Chart.js v4.4.1 minified) and license for security audits. |
Tip
Always record the exact library version number in <description> (for example, Chart.js v4.4.6 SHA-256: ...) so security teams can audit third-party frontend dependencies using a simple SOQL query on StaticResource.
Querying StaticResource via SOQL
StaticResource is a standard Salesforce object queryable via standard SOQL and Tooling API.
1. Audit Org StaticResource Storage Usage Against the 250 MB Limit
Find the largest static resources and calculate total bytes consumed across your org:
SELECT Id, Name, NamespacePrefix, ContentType, CacheControl,
BodyLength, Description, LastModifiedDate, LastModifiedBy.Name
FROM StaticResource
WHERE NamespacePrefix = null
ORDER BY BodyLength DESC2. Aggregate Total Unmanaged StaticResource Megabytes Used
SELECT SUM(BodyLength) totalBytesUsed, COUNT(Id) resourceCount
FROM StaticResource
WHERE NamespacePrefix = nullExample
1. Metadata Descriptor (StripeChargeMock.resource-meta.xml) and JSON Fixture
Store mock HTTP callout payloads as .json static resources so your Apex unit tests stay clean and free of giant escaped JSON strings:
<?xml version="1.0" encoding="UTF-8"?>
<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
<cacheControl>Private</cacheControl>
<contentType>application/json</contentType>
<description>Mock 200 OK Stripe v1/charges response payload for PaymentGatewayServiceTest.</description>
</StaticResource>{
"id": "ch_3Q9xYz2eZvKYlo2C01234567",
"object": "charge",
"amount": 25000,
"currency": "usd",
"paid": true,
"status": "succeeded"
}2. Using StaticResourceCalloutMock in an Apex Unit Test
Reference StripeChargeMock in an @IsTest method without writing a custom HttpCalloutMock class:
@IsTest
private class PaymentGatewayServiceMockTest {
@IsTest
static void parsesSuccessfulStripeChargeUsingStaticResourceMock() {
StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
mock.setStaticResource('StripeChargeMock');
mock.setStatusCode(200);
mock.setHeader('Content-Type', 'application/json');
Test.setMock(HttpCalloutMock.class, mock);
Test.startTest();
HttpResponse res = PaymentGatewayService.createCharge(25000, 'USD', 'tok_visa');
Test.stopTest();
Assert.areEqual(200, res.getStatusCode());
Assert.isTrue(res.getBody().contains('ch_3Q9xYz2eZvKYlo2C01234567'));
}
}3. Loading a ZIP StaticResource in a Lightning Web Component
import { LightningElement } from 'lwc';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import CHARTJS_ZIP from '@salesforce/resourceUrl/chartJsBundle';
export default class RevenueChart extends LightningElement {
chartInitialized = false;
async renderedCallback() {
if (this.chartInitialized) {
return;
}
this.chartInitialized = true;
await Promise.all([
loadScript(this, `${CHARTJS_ZIP}/chart.umd.min.js`),
loadStyle(this, `${CHARTJS_ZIP}/chart-custom.css`)
]);
this.initializeChart();
}
initializeChart() {
// Initialize Chart.js on this.template.querySelector('canvas')
}
}Limits and Gotchas
- 5 MB Single File Ceiling: Any single
StaticResourceexceeding 5 MB (5,242,880 bytes) fails deployment immediately. Minify JS/CSS bundles and compress SVG/WebP assets before committing. - 250 MB Total Org Ceiling: An org can store at most 250 MB of total
StaticResourcebinary data across all unmanaged resources. - Avoid Querying
StaticResource.Bodyin Loops: Selecting theBody(Blob) field in SOQL loads the entire binary payload onto the 6 MB synchronous Apex heap (12 MB asynchronous). Only selectBodyfor one small resource at a time.
Related Official Documentation
- StaticResource Metadata API Reference: XML elements and manifest configuration.
- StaticResource Object Reference: Standard SOQL fields for auditing static resources.
- Use Third-Party JavaScript Libraries in LWC: Loading static resources with
platformResourceLoader.
Frequently asked questions
How do I store a ZIP StaticResource as unpacked files in Git with SFDX?
Create a folder named force-app/main/default/staticresources/ResourceName/ containing your extracted JS, CSS, or image files alongside ResourceName.resource-meta.xml with contentType set to application/zip. Salesforce CLI automatically zips the directory during deployment.
What is the maximum file size limit for a StaticResource?
A single StaticResource file or ZIP archive can be up to 5 MB (5,242,880 bytes), and an org can store up to 250 MB of StaticResources in total.
What is the difference between Private and Public cacheControl on a StaticResource?
Private caches the static resource only in the user's browser session and requires Salesforce authentication (unless accessed in Experience Cloud). Public allows caching on the Salesforce edge CDN and intermediate proxy servers for faster anonymous delivery.
How do I load a JavaScript or CSS library from a StaticResource inside an LWC?
Import the resource URL from @salesforce/resourceUrl/resourceName and pass it to loadScript() or loadStyle() from the lightning/platformResourceLoader module inside renderedCallback().
How can I use a StaticResource as a mock HTTP callout response in Apex tests?
Instantiate Built-in StaticResourceCalloutMock, call mock.setStaticResource('MyMockJsonResource'), set the status code, and register it via Test.setMock(HttpCalloutMock.class, mock).
How do I query StaticResource file sizes and MIME types using SOQL?
Query the standard StaticResource object in SOQL: SELECT Name, ContentType, BodyLength, CacheControl, LastModifiedDate FROM StaticResource ORDER BY BodyLength DESC.
Comments
Questions, corrections and tips are welcome. Comments are GitHub Discussions, so you sign in with GitHub.