Skip to main content
Bring your team and maximize your impact at Dreamforce. Register three or more to unlock $999 passes.

Explore the Visualforce App Container

Learning Objectives

After completing this unit, youโ€™ll be able to:

  • Describe three differences between Visualforce pages running in Salesforce Classic compared to the same pages running in Lightning Experience.
  • Describe two common code patterns that need updating to work in Lightning Experience.
  • List two changes to Visualforce page default values when running in Lightning Experience.

Exploring the Visualforce App Container

The largest difference between Visualforce in Lightning Experience and Visualforce in Salesforce Classic is the environment it runs in. In Salesforce Classic, Visualforce โ€œownsโ€ the page, the request, the environment. Visualforce is the application container. But in Lightning Experience, Visualforce runs inside an iframe thatโ€™s wrapped inside the larger Lightning Experience container.

This change to the execution context has a number of effects on the way Visualforce pages can affect the overall Salesforce application. Weโ€™ll talk about these changes in this unit, but save the full details of a few of them for their own units.

Note

This unit is a little more โ€œunder constructionโ€ than the rest. The reason is simple: The impact of the issues described here is highly dependent on your code. Weโ€™ve worked really hard to make things โ€œjust workโ€ for you, and in most cases little or nothing here will show on your radar. But we canโ€™t anticipate every way that youโ€™re using Visualforce. Here weโ€™re outlining the general aspects of how Lightning Experience affects Visualforce. When you have conversations with us, and as we learn more from you about actual impact, we can offer explanations with more details about how to address specific issues.

The Outer Lightning Experience Container

Letโ€™s start with the outer container, the Lightning Experience application. The Lightning Experience container is a โ€œsingle-page application,โ€ or SPA, which is accessed at the /lightning URL. The /lightning page loads, its code starts up, and that application code takes over the environment.

The process by which a single-page application loads its resourcesโ€”usually a static HTML shell and a lot of JavaScriptโ€”is both interesting and complex. If youโ€™ve worked with JavaScript frameworks like AngularJS or React, youโ€™re reasonably familiar with the basics of how Lightning Experience, in the form of /lightning, starts up. And to be honest, the full details donโ€™t matter. You donโ€™t have any control over it, and the implementation continues to evolve.

Hereโ€™s whatโ€™s important to know: Lightning Experience, or /lightning, is in charge of the request. Your Visualforce page is not. Your page needs to work within constraints that Lightning Experience imposes upon it. Lightning Experience is the parent context, and your Visualforce page is the child context. Children need to obey their parents.

Some of these constraints, such as the size of the frame in which your Visualforce page is displayed, are imposed directly by Lightning Experience. Theyโ€™re easier to understand and work with, and weโ€™ll talk about them in a minute.

Other constraints are implicit, and enforced not by Lightning Experience but by the browser running it. These are mostly security and JavaScript execution constraints. Most pages arenโ€™t impacted by these security constraints, and those that are usually fail early and with clear error messages. JavaScript errors are harder to discover and diagnose, but there are some general rules weโ€™ll cover in a bit.

The Visualforce iframe

When your Visualforce page runs in Lightning Experience, itโ€™s displayed inside an HTML iframe. An iframe creates an embedded browsing context thatโ€™s effectively a separate browser โ€œwindowโ€ from the main Lightning Experience browsing context. The iframe creates a boundary between the Visualforce page and its parent, the Lightning Experience application.

The advantage of running Visualforce pages inside an iframe is that, for pages that donโ€™t need to access or change the top-level browsing context, running inside the iframe looks almost exactly like running as a page in Salesforce Classic. This is why you donโ€™t need to modify all of your Visualforce pages to adapt to the wildly different behind-the-scenes request environment of Lightning Experience. Itโ€™s an important part of the โ€œjust worksโ€ strategy for supporting Visualforce.

Of course, the flip side is that pages that do need to access the top-level browsing context, well, thereโ€™s some things that need to change. Weโ€™ll cover some specifics in the next section.

If your page is communicating with services besides Salesforce, the iframe boundary might also result in you needing to update your organizationโ€™s CORS settings, remote site settings, clickjack settings, or content security policy. Since these depend on security policies and settings outside of Salesforce, we canโ€™t provide a recipe for specific changes. We simply call it to your attention here.

Impact of the New Container

The effects of the new Visualforce containerโ€”embedding the Visualforce page into an iframe within the Lightning Experience appโ€”can be broadly divided into two categories, which weโ€™ll call security and scope.

Again, we want to emphasize: many, or even most Visualforce pages wonโ€™t be affected by these issues. But for those that are, weโ€™re thinking โ€œforewarned is forearmed.โ€ Youโ€™ll find the source of the problem faster if weโ€™ve already talked about it together.

Security Impact

Elements of security that might be affected include the following.

  • Session maintenance and renewal
  • Authentication
  • Cross-domain requests
  • Embedding restrictions

We discussed a few of these briefly already, the items dealing with cross-domain requests. That is, when the content in the full browser window comes from requests to different servers and services, thereโ€™s the potential for any of those requests to balk at being displayed in a context that itโ€™s not prepared for. Your mission, should the need arise, is to prepare those services to handle requests intended to be put together within the Lightning Experience context. As we said before, the details vary, so we canโ€™t provide specific answers here.

One thing we do want to mention specifically is session maintenance. A โ€œsessionโ€ for our purposes here is basically some kind of token that your browser re-uses from request to request so that you donโ€™t need to enter your username and password for every request. You often need to access the current session using the global variable $Api.Session_ID .

Hereโ€™s the thing to keep in mind. $Api.Session_ID returns different values depending on the domain of the request. This is because the session ID varies during a session whenever you cross a hostname boundary, such as .salesforce.com to .force.com. Normally Salesforce transparently handles session hand-off between domains, but if youโ€™re passing the session ID around yourself, be aware that you might need to re-access $Api.Session_ID from the right domain to ensure a valid session ID.

Lightning Experience and Visualforce pages are not only held in different browser contexts, theyโ€™re also served from different domains. So, even though itโ€™s all showing in one browser window, the session ID inside the Visualforce iframe will be different than the session ID outside the iframe, in another part of Lightning Experience. Salesforce and Lightning Experience handle this transparently in normal use. But if youโ€™re passing around the session ID like hors d'oeuvre at a party (not usually a good idea), you might need to review how youโ€™re handling it.

Scope Impact

When we talk about scope weโ€™re mainly talking about the following kinds of things.

  • DOM access and modification
  • JavaScript scope, visibility, and access
  • JavaScript global variables such as window.location

If this list sounds complicated or confusing, donโ€™t worry, we can boil it down to something simple and easy to remember: Donโ€™t touch someone elseโ€™s stuff. Specifically, your JavaScript code (and stylesheet rules, for that matter) can affect elementsโ€”DOM nodes, JavaScript variables, and so onโ€”in your pageโ€™s browsing context, but it canโ€™t access elements in any other browsing context, like the parent Lightning Experience context. Donโ€™t touch other contextsโ€™ stuff!

Practically speaking, the most common code pattern where youโ€™d want to do this kind of thing is to manipulate window.location to navigate to another page. This is such a common thing to do, weโ€™ve written up details on this specific issue...well, by the time youโ€™re done with this module, youโ€™ll be sick of hearing about it, we promise.

One last note. If youโ€™re an experienced JavaScript developer, youโ€™re probably already thinking you know how to deal with โ€œI donโ€™t have access to the parent browsing contextโ€ issues, by using contentWindow, window.parent, or the like. Please donโ€™t. Youโ€™ll likely run afoul of the same-origin policy (Visualforce and Lightning Experience are served from different domains, remember?). Even if you donโ€™t, youโ€™re probably replacing obvious, blocking bugs with subtle, intermittent bugs. Where do you want to spend your time: Doing things right, or the debugger?

Doing things right means calling APIs weโ€™ve made available in your Visualforce pages, primarily for navigation. If you really need to affect things across frame boundaries, use window.postMessage to send a message to receiving code in the other frame.

Visualforce Defaults and Environment Changes in Lightning Experience

When your Visualforce pages run in Lightning Experience a number of low-level changes happen behind the scenes. These changes enable most pages to โ€œjust workโ€ in the Lightning Experience container, and sometimes you can just be happy theyโ€™re there. But youโ€™ll still want to know theyโ€™re happening, especially when youโ€™re working on advanced application flows, or troubleshooting a tricky problem.

Some of these changes are simple, and obvious once you think about them. For example, Visualforce pages that run in Lightning Experience always have the standard Salesforce Classic header and sidebar suppressed. Other changes arenโ€™t as visible, but have just as large an impact.

showHeader and sidebar Attributes Are Always false

These attributes affect the Salesforce Classic header and sidebar on Visualforce pages. The Salesforce Classic header and sidebar are always suppressed when pages run in Lightning Experience, in favor of Lightning Experience navigation elements. There are no corresponding attributes to affect the Lightning Experience header or sidebar because they canโ€™t be suppressed.

If your page is shared between Salesforce Classic and Lightning Experience, you can still set these attributes to the values youโ€™d like to use when the page runs in Salesforce Classic.

Note

The standardStylesheets attribute of <apex:page>, which determines whether to include or suppress the standard Salesforce Classic stylesheets, is unaffected by Lightning Experience. That is, it defaults to true in Lightning Experience, but youโ€™re able to change it.

The sforce.one JavaScript Utility Object

Although sforce.one sounds like a droid working in the Salesforce cantina, * itโ€™s actually a utility object that provides a number of useful functions you can use in your own JavaScript code.

sforce.one is automatically injected into your page when it runs in Lightning Experience or the Salesforce app. Youโ€™ll see it in your JavaScript debugger console and web developer resources list. Thereโ€™s nothing you need to do to add it, and thereโ€™s no way to suppress it, either. (Sadly, thereโ€™s no way to get sforce.one in your Visualforce pages in Salesforce Classic.)

sforce.one is primarily used to fire navigation events. The full details are in an upcoming unit, Managing Navigationย .

____________________

* There is no Salesforce cantina. Alas.

Resources

Salesforce ๋„์›€๋ง์—์„œ Trailhead ํ”ผ๋“œ๋ฐฑ์„ ๊ณต์œ ํ•˜์„ธ์š”.

Trailhead์— ๊ด€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์˜๊ฒฌ์— ๊ท€ ๊ธฐ์šธ์ด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด์ œ Salesforce ๋„์›€๋ง ์‚ฌ์ดํŠธ์—์„œ ์–ธ์ œ๋“ ์ง€ ์ƒˆ๋กœ์šด ํ”ผ๋“œ๋ฐฑ ์–‘์‹์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ ์˜๊ฒฌ ๊ณต์œ ํ•˜๊ธฐ