Newer Version Available
Multiple Package Directories
In your sfdx-project.json file, list each package directory separately in the packageDirectories section. Each local package directory adheres to the standard Salesforce DX project structure.
The multiple package directory structure is client-side (local) only. When you deploy the source to the org with force:source:deploy or force:source:push, there’s no association between its local package directory location and the package in the org. You specify that metadata belongs to a specific 2GP package in an org by explicitly installing the 2GP package.
All of the force:source:* commands support multiple package directories.
Considerations
Before setting up multiple package directories, read these considerations.
- By default, both force:source:deploy and force:source:push deploy metadata to your org in a single transaction, regardless of the order that you list your multiple package directories in sfdx-project.json. The force:source:push command pushes all changed and new metadata in all package directories; force:source:deploy deploys only the metadata that you specify. If you want to use force:source:push, but also want to specify the order that the package directories are pushed, use the pushPackageDirectoriesSequentially property of sfdx-project.json. See Push Source Sequentially for details.
- By default, the force:source:deploy|retrieve commands don't track changes in your source files. Enable source tracking for these commands by specifying the --tracksource parameter each time you run the command. The force:source:deploy|retrieve commands then use the same internal source tracking files as the force:source:push|pull commands. Be sure you use this parameter if you use force:source:deploy|retrieve and force:source:push|pull together. If you don't, the internal source-tracking files get out of sync. The force:source:push|pull commands always track your source changes.
How Do I Set It Up?
Setting up multiple package directories is easy. How you organize your local source code among these directories takes more thought and planning, and depends on your development environment. Plan how to organize your code before you get started. Keep your source code well organized as your project grows to make it easier and more efficient for your developers to work.
Let’s look at a simple example. Say you put the decomposed metadata files for a custom object MyObject in the default package directory. You can then put files for a new field MyField on MyObject in a different “extension” package directory without having to also include the MyObject files. There are many ways to organize your code, and describing all the ways is out of scope of this topic. These blog posts provide some ideas.
Here’s how you set up multiple package directories. Let’s first look at a sample sfdx-project.json snippet:
This sfdx-project.json snippet defines three package directories: es-base-custom (the default), es-base-ext, and es-base-styles. Let’s say your top-level local project directory is called easy-spaces-lwc. The directory hierarchy underneath it would look something like this:
Each es-base-* directory adheres to the standard Salesforce DX project structure. For example, es-base-ext would look something like:
Now add the decomposed metadata source to these multiple package directories in the way that best suits your development environment.
How Does It Work?
Let's go through a few examples to see how force:source:push|pull and force:source:deploy|retrieve work with multiple package directories.
For new orgs, the force:source:push command pushes all the metadata in all multiple package directories listed in your sfdx-project.json file. After that, the command pushes metadata that's new, changed, or marked for delete. By default, the command pushes the metadata in a single transaction, as if you had just one package directory.
In contrast, use force:source:deploy to target the metadata you want to deploy. You can deploy specific package directories, specific metadata components, components listed in a manifest file, and more. This example deploys the metadata in the es-base-custom package directory:
This example deploys all Apex classes found in all your multiple package directories:
When you run force:source:pull, the command pulls all remote changes from the org into your local project. For each retrieved component, the command looks in all package directories for a local match. If it finds a match, the command updates it. If it doesn't find a match, the command copies the local component into the default package directory, which in our example is es-base-custom.
You can then move the pulled files into the package directory that makes sense for your project. After you push the moved files back up to the org with force:source:push, Salesforce CLI tracks their new location.
Use force:source:retrieve to retrieve targeted metadata from your org. Similar to force:source:pull, existing metadata is retrieved into its correct local package directory and new metadata into the default package directory. This example retrieves only the metadata components contained in the local es-base-custom package directory:
This example retrieves all Apex classes from your org; new classes go into the default package directory and classes that exist locally go into their corresponding package directory.
Push Source Sequentially
- The number of recomposed metadata component files in your local project exceeds the Salesforce metadata limit of 10,000 files per retrieve or deploy. One workaround is to split up your metadata into multiple package directories that each contain less than this limit and push each directory sequentially, and thus separately.
- You have dependencies between multiple package directories, which requires that they be pushed in a specific order.
- More than one package directory contains the same metadata component, and you want to specify which one is deployed last so it's not overwritten.
To specify that the multiple package directories are pushed in the order they're listed in sdfx-project.json, add "pushPackageDirectoriesSequentially": true to the file. For example:
When you run force:source:push, the command executes three separate pushes in this order: first the metadata from es-base-custom, then es-base-ext, and then es-base-styles.