Apex Cacheable methods

Introduction  

With salesforce winter 19 release, Salesforce introduces another way to improve the performance of the lightning component cache by mark an Apex method as storable (cacheable) instead of using setStorable() on every JavaScript action. With the apex storable methods, you can centralize your caching notation for a method in the Apex class instead of doing at client side javascript. Marking a method as storable improves your component’s performance by quickly showing cached data from client-side storage without waiting for a server trip. If the cached data is stale, the framework retrieves the latest data from the server.

How to Use?

To cache data returned from an Apex method for any component with an API version of 44.0 or later, annotate the Apex method with
@AuraEnabled(cacheable=true). For example, the following method is made as cacheable

 @AuraEnabled(cacheable=true)
    public static List<Account> getAccount() {
        return [Select Id, Name,Type, Industry, BillingAddress,
                BillingCity, BillingCountry, BillingPostalCode,
                BillingState,Phone from Account  where Industry!=NULL ] ;
    }

Here is the complete apex class.

public class ApexCacheableController {
    @AuraEnabled(cacheable=true)
    public static List<Account> getAccount() {
        return [Select Id, Name,Type, Industry, BillingAddress,
                BillingCity, BillingCountry, BillingPostalCode,
                BillingState,Phone from Account  where Industry!=NULL ] ;
    }
}

Lightning Component 

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" 
                controller="ApexCacheableController">
    <aura:attribute name="accounts" type="Account[]"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
    <table class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_col-bordered">
        <thead>
            <tr class="slds-line-height_reset">
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title=" Name">Name</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="Type">Type</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="Industry">Industry</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="BillingCity">BillingCity</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="BillingCountry">BillingCountry</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="BillingPostalCode">BillingPostalCode</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="BillingState">BillingState</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="Phone">Phone</div>
                </th>
            </tr>
        </thead>
        <tbody>
            <aura:iteration items="{!v.accounts}" var="obj">
                <tr class="slds-hint-parent">
                    <td data-label="Account Name">
                        <div class="slds-truncate" title="Name">{!obj.Name}</div>
                    </td>
                    <td data-label="Type">
                        <div class="slds-truncate" title="Type">{!obj.Type}</div>
                    </td>
                    <td data-label="Industry">
                        <div class="slds-truncate" title="Industry">{!obj.Industry}</div>
                    </td>
                    <td data-label="BillingCity">
                        <div class="slds-truncate" title="BillingCity">{!obj.BillingCity}</div>
                    </td>
                    <td data-label="BillingCountry">
                        <div class="slds-truncate" title="BillingCountry">{!obj.BillingCountry}</div>
                    </td>
                    
                    <td data-label="BillingPostalCode">
                        <div class="slds-truncate" title="BillingPostalCode">{!obj.BillingPostalCode}</div>
                    </td>
                    
                    <td data-label="BillingState">
                        <div class="slds-truncate" title="BillingState">{!obj.BillingState}</div>
                    </td>
                    <td data-label="Phone">
                        <div class="slds-truncate" title="Phone">{!obj.Phone}</div>
                    </td>
                </tr>
            </aura:iteration>
            
        </tbody>
    </table>
    
    
</aura:component>

JavaScript controller

({
    doInit : function(component, event) {
        console.time("concatenation");
        var action = component.get("c.getAccount");
        action.setCallback(this, function(a) {
            component.set("v.accounts", a.getReturnValue());
        });
        $A.enqueueAction(action);
        console.timeEnd("concatenation");
    }
})

Now if the javascript code we no need to use setStorable() action instead we are using cachable apex methods.

Can I use javascript storable along with Cachable methods?

Yes ..You can able to use both setStorable and apex cacheable methods together. But recommended will update an existing component to API version 44.0, remove setStorable() calls in JavaScript code along with Apex Cachable methods.

({
    doInit : function(component, event) {
        console.time("concatenation");
        var action = component.get("c.getAccount");
        action.setStorable();
        action.setCallback(this, function(a) {
            component.set("v.accounts", a.getReturnValue());
        });
        $A.enqueueAction(action);
        console.timeEnd("concatenation");
    }
})

Can I use the Cacheable methods in visualforce?

You can able to use the cacheable methods in visualforce controller also. Here is the simple page that calls the apex controller with cachable actions.

<apex:page controller="ApexCacheableController" id="thePage" lightningStylesheets="true">
    
    <apex:pageBlock >
        <apex:pageblockTable value="{!account}" var="acc">
            <apex:column value="{!acc.Name}"/>    
            <apex:column value="{!acc.Type}"/>    
            <apex:column value="{!acc.Industry}"/> 
            <apex:column value="{!acc.BillingCity}"/>    
            <apex:column value="{!acc.BillingCountry}"/>    
            <apex:column value="{!acc.Phone}"/> 
            
        </apex:pageblockTable>  
    </apex:pageBlock>
    
</apex:page>