Sharing Code in SharePoint Framework (SPFx) Projects: npm vs. Library Components

Curious about sharing code in SharePoint Framework projects? Explore the advantages of npm packages over SPFx library components!

By Last Updated: October 7, 2024 8 minutes read

SharePoint Framework (SPFx) developers often face the challenge of determining how to share code or refactor it from their project in order to make it available for multiple projects. The objective is to avoid duplicating code, which is a common issue in development.

I’ve never used or found a need for an SPFx library components. There’s simply no need for a SPFx-specific solution to a problem that has already been solved with npm packages.

Andrew Connell
Andrew Connell
Microsoft MVP, Full-Stack Developer & Chief Course Artisan - Voitanos LLC.

In this article, we’ll look at two options for externalizing your code to share across multiple projects and comparing the advantages and disadvantages of each. I’ll offer my thoughts and opinions on which of the two options I prefer and explain my reasons.

But first, let’s look at the challenge and some of the unique aspects related to SPFx solutions.

Challenge: Code Reuse Across Projects

You may have code that is shared across multiple SPFx solutions. Duplicating code in your projects isn’t ideal for maintenance & performance reasons, so it’s recommended to externalize this when possible.

How can code duplication impact performance? If you have multiple web parts on a page that all reference the same code, you don’t want to load the same code multiple times. Ideally, it should only be loaded once on the page. Similar to how we don’t load React multiple times on a page when multiple web parts depend on it, we want to ensure that it is only loaded once.

So, how can you share code across your SPFx projects?

Sharing code across SPFx projects

The solution is to externalize the shared code from your project and then consume it from one or more components. There are two different options available to achieve this.

The option most SPFx developers look to are library component, introduced in SPFx v1.9.1. This is a Microsoft & SPFx-specific solution that’s covered in the documentation.

The other option is to use a npm package. This is the standard way to distribute JavaScript packages that works for all JavaScript-based projects including SPFx solutions.

Let’s explore of these two options, including the advantages and disadvantages of each one.

SPFx Library Components

SPFx library components were introduced in SPFx v1.9.1. They allow you to have code that can be versioned independently of the SPFx project that consume them. Any SPFx component can consume an SPFx library component.

Once deployed, when a SPFx component that depends on the library component is loaded on a page, the SPFx runtime loads the library component’s bundle. Subsequent requests for the same library component on the page by other components will not result in additional requests.

SPFx Library Components: Advantages

Here are some advantages of using an SPFx library component:

  1. No extra deployment step required
  2. Not publicly available outside of the deployment scope (site collection-scoped or tenant-scoped app catalog)
  3. Development process is similar to any other SPFx component
  4. Can be created using the SPFx Yeoman generator and the build toolchain

SPFx Library Components: Disadvantages

However, there are some disadvantages related to library components:

  1. Library components can only be used with SPFx solutions.
  2. You cannot have multiple versions of the same library component deployed simultaneously - there is only one version deployed at any time.
  3. Library components are limited to the scope where they have been deployed. They cannot be mixed and matched across different scopes, such as the site collection or app catalog.
  4. Harder to implement automated testing.
  5. Only available for SPFx solutions in SharePoint Online - library components were introduced in SPFx v1.9.1 & no on-prem SharePoint Server deployment supports a SPFx version higher than SPFx v1.5.1 at this time.

npm Packages

An npm package is a standardized way to share code in a Node.js based project.

In fact, we are already using npm packages for almost all of our SPFx projects. It allows for independently versioned code and any SPFx component can consume a bundled npm package. We are currently using this approach with React and other libraries listed in the package.json file.

npm Packages: Advantages

Some of the advantages of using npm packages include the following:

  1. Reusability: An npm package can be used in multiple SPFx solutions and non-SPFx solutions, providing flexibility and saving development time.
  2. Versioning: npm packages can be versioned independent of other projects that depend on it, allowing for better control and management of code changes.
  3. Automated Testing: Implementing automated testing is easier with npm packages, enhancing code quality and reliability.
  4. Standards-Based: npm packages provide a standards-based solution to a common need.
  5. Works in all SPFx versions, including the oldest SharePoint Server on-premises deployments.

npm Packages: Disadvantages

Here are the disadvantages of using npm packages for code reuse within an SPFx based solution:

  1. Additional deployment step required if you decide to externalize your bundle: You need to decide where to host the bundle that contains the entire npm package.
  2. Inability to use the existing Yeoman generator for SPFx projects in the build toolchain: You will need to create your own generator, although there are many open and standard examples available for reference.
  3. Incompatibility with SPFx based components: You cannot easily use SPFx based components inside these solutions. Technically you can, but the testing of the development process is very hard because you can’t really inject the SPFx context into them without a lot of additional work.

Using npm packages in SPFx Solutions

By default, during the build process, webpack will ingest the referenced dependencies and include them in each project’s bundle.

For smaller projects where duplicating the code in the bundles won’t add much to the size of the generated bundle, this method might be acceptable to you.

However, if you have one common package used by multiple SPFx projects, any time you update the common package you’d need to rebuild & redeploy the consuming SPFx projects.

The other option is to externalize your common package’s bundle & host it in a CDN or a location where the bundle is accessible by your deployed SPFx projects. That could be a publicly accessible CDN or one that’s only available to users within your organization.

To do this, first build & deploy your common package’s bundle to some location. For example, let’s say you’ve externalized your code into a new package mathlib and deploy the bundle to to https://cdn.contoso.com/mathlib/1.2/math.js.

Next, install the npm package of your common library in your SPFx project using a standard npm install command to list it in your project’s package.json file: npm install mathlib -SE.

Next, configure your SPFx project so that webpack will ignore the library and not include it in your SPFx project’s bundle. Instead, it will be listed as a dependency so when the SPFx runtime goes to load your dependencies, it will ensure it’s loaded on the page from the CDN location before it loads your SPFx component’s bundle. This is done in the ./config/config.json file in your SPFx project:

{
  "bundles": { .. },
  "externals": {
    "mathlib": "https://cdn.contoso.com/mathlib/1.2/math.js"
  },
  "localizedResources": { ..}
}

Now, anytime webpack sees our library referenced in a module (import MathLib from 'mathlib';), instead of including it in the generated bundle, it will ignore it assuming it’s going to get added to the page some other way.

Another part of the SPFx build process generates a component manifest file that will include our library as a dependency. When the SPFx runtime loads the manifest for a component, it will see this reference and ensure all dependencies are downloaded on the page before loading the component’s bundle that assumes those libraries are present.

Conclusion

From my point of view, an npm package is the better option for externalizing your code in SPFx solutions. It’s an established solution to a common problem. SPFx library components, in my view, simply create a SPFx-specific solution to an already solved problem and at the same time, introduce limitations that you don’t face with npm packages.

I’ve never used or found a need for an SPFx library components. I simply see no need for a SPFx-specific solution to a problem that has already been solved and doesn’t have all the baggage an SPFx library component introduces to the scenario.

In my SPFx projects, I always rely on npm packages and generate bundles that I either host in my own CDN or include the code directly in the consuming projects’ bundles. If adding the packages to the bundle doesn’t significantly increase its size and the externalized code isn’t used in more than a couple of projects, I bundle them.

Otherwise, I store them separately in my own Azure-hosted CDN, and reference them as external resources in my config.json file. An Azure CDN is incredibly cheap so cost is of no concern.

What about you?

What’s your favorite way to achieve code reuse within a project? Do you prefer using npm packages or SPFx library components?

Were you aware that you can use npm packages? If not, what do you think? If you have any questions about this approach leave a comment below 👇!