updated May 4, 2018 from the original post dated August 19, 2016
If you've been developing ISV apps on the Salesforce platform, you're familiar with the concept of Namespace. It keeps your managed package under your control exclusively.
One of the coolest feature of the platform? While generating a managed package, the platform automatically takes care of namespace for your components to a wide extent. Even in Visualforce, if you have used standard markups like Apex tags (apex:inputfield, apex:outputfield, etc) the platform automatically handles the namespace during the package build.
While there are many places in Apex if you are using string literals for your field, you have to make extra efforts to dynamically append namespace to avoid run time failures.
Lightning Components are new to the platform. Let's examine the parts of the component bundle that Salesforce automatically does a namespace and the parts that you have to handle manually.
This post assumes you are a) familiar with some Lightning framework code and b) understand environment strategy for building ISV apps. As a best practice, it's always advised to keep the code namespace independent and version the code using Code Versioning tools like SVN, TFS, or Github.
Let's build a simple Lightning component that displays a list of Account data from the org and let's use a custom field to understand the impact namespace will have on the code. We will package the code and figure out whether the platform is capable of handling namespace automatically or not.
The code that we will be packaging is as below:
Packaging this, from your packaging org, should be straight forward provided you have the test class for your Apex.
I installed this on another org and observed the Account Name renders as expected, but not the custom field. If it's a managed package, you cannot edit any code and everything is hidden.
The second attempt involved explicitly name spacing the component file to include namespace for the custom field like below and packaging it.
This time everything renders. Interesting!
Now the above approach means that for large scale apps, the codebase is updated every time and is ready for package. The component file needs to be checked and all fields need to be namespaced. Doesn't really seem like a good approach, does it? What would happen if field names change? Or if you're planning to port this code to another namespace and there are 100's of such files? Sounds like a huge pain.
Decoupling the Database field bindings from the UI Layer
The next obvious approach seems to be decoupling the field names and creating an Apex message layer. The message layer consists of a wrapper Apex class. The modified code would look like below:
Packaging the above code rendered the component well.
If you are developing a managed package using DX, you can set the namespace on all the scratch orgs to match the namespace of the Packaging org. Since all orgs have the same namespace, code can be written to be “namespace aware” and this will eliminate the challenges described above.
Lightning Data Services
Leveraging the Lightning Data Services will encounter the same difficulty as described above. In a managed package build, Lightning Data Services should only be used in the context of DX build environments.
Here are a few key observations on the best approach to keep the namespace of your Lightning components safe.
- The Salesforce platform doesn't automatically namespace fields in your component. This means if you want to keep your code clean and namespace independent, use your own wrapper Apex class.
- Keep your wrapper class in a separate file and don't use inner classes. Currently there's a bug with inner class -- please upvote this idea.
- Never hardcode namespace in any of the files inside the bundle. Even for loading static resources SFDC has provided $Resource, so use that as per guidelines.
What do you think? Consider upvoting this idea to make life easier for managed packages by directly binding fields from SFDC objects for Lightning components.