Export PnP reusable controls from SPFx library component

SharePoint Framework allows you to create a library component (docs) type of project that you can use to bundle all your shared resources and add as a dependency to your other projects. Once deployed, the other projects will consume the shared resources from the library.

Vardhaman Deshpande has a great blog post on how to export a custom component using Office UI Fabric React from a SPFx library component.

But you may decide to go even a step further and add some third-party dependencies to your library that are then consumed from the other solutions.While this may sound great in terms of performance, it also adds some challenges as when you update a version of a third-party package on the library solution, all the solutions consuming that package will now consume the updated version, so will need to be tested again. Use at your own judgement!

Library component solution

In order to export the PnP reusable controls and PnP property controls from a SPFx library component solution there are a few things to do.

Install packages

First install the PnP packages on your library project

npm install @pnp/spfx-controls-react --save --save-exact
npm install @pnp/spfx-property-controls --save --save-exact

Next we need to install some required SharePoint Framework packages. These are not installed by default on library component type projects but are required by the PnP controls.
This is important as otherwise your gulp bundle task will fail

  • @microsoft/sp-page-context
  • @microsoft/sp-http
  • @microsoft/sp-webpart-base
npm install @microsoft/sp-page-context @microsoft/sp-http @microsoft/sp-webpart-base --save --save-exact

Update Config.json

As mentioned on Vardhaman’s post linked above, you need to update the “entrypoint” property of the Config.json file to point to the main index.ts file. Your file should look similar to this:

{
  "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
  "version": "2.0",
  "bundles": {
    "library-component-library": {
      "components": [
        {
          "entrypoint": "./lib/index.js",
          "manifest": "./src/libraries/libraryComponent/LibraryComponentLibrary.manifest.json"
        }
      ]
    }
  },
  "externals": {},
  "localizedResources": {
    "LibraryComponentLibraryStrings": "lib/libraries/libraryComponent/loc/{locale}.js",
    "PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js",
    "ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
  }
}

Update index.ts

The last thing to do on the library is to export the required modules that can be consumed by the other solutions. Open the index.ts under the src folder of your solution and export the controls that you want to make available. Your index.ts file should look like this (or have more exports as required)

export {
    FolderExplorer, IFolder,
    Placeholder
} from '@pnp/spfx-controls-react';
export {
    PropertyFieldCollectionData, CustomCollectionFieldType
} from '@pnp/spfx-property-controls/lib/PropertyFieldCollectionData';
export { LibraryComponentLibrary } from './libraries/libraryComponent/LibraryComponentLibrary';

Consuming the controls from the library

On the consumer solutions, it’s all very simple

Install dependency

Add a dependency to the library component on the consumer project by including a reference in package.json

"library-component": "0.0.1"

Next import the PnP component from the library and use it in your code as normal

import { Placeholder } from "library-component";

Additional resources

Introduction on using the library component in SharePoint Framework solutions

Tips and Tricks working with SPFx library components

SharePoint Library Components – Simultaneous Parallel Development

Using Lerna to manage SPFx projects with library components

4 thoughts on “Export PnP reusable controls from SPFx library component

  1. Hi,

    I am trying to export PnP reusable components from library component but getting the following error.

    SPLoaderError.loadComponentError]:
    ***Failed to load component “6f080e8f-9bc6-45f7-b1cd-4c54f0e99285” (HelloWorldWebPart). Original error: ***Failed to load entry point from component “6f080e8f-9bc6-45f7-b1cd-4c54f0e99285” (HelloWorldWebPart). Original error: Cannot find module ‘ControlStrings’

    ***INNERERROR:
    ***Failed to load entry point from component “6f080e8f-9bc6-45f7-b1cd-4c54f0e99285” (HelloWorldWebPart). Original error: Cannot find module ‘ControlStrings’
    ***CALLSTACK:
    Error
    at SPLoaderError.SPError [as constructor] (https://localhost:4321/temp/workbench-packages/@microsoft_sp-webpart-workbench/local-workbench/sp-webpart-workbench-assembly_default.js:24443:24)
    at new SPLoaderError (https://localhost:4321/temp/workbench-packages/@microsoft_sp-webpart-workbench/local-workbench/sp-webpart-workbench-assembly_default.js:42161:28)
    at Function../sp-loader.js.__WEBPACK_AMD_DEFINE_RESULT__.ff4n.ErrorBuilder.buildErrorWithVerboseLog (https://localhost:4321/temp/workbench-packages/@microsoft_sp-webpart-workbench/local-workbench/sp-webpart-workbench-assembly_default.js:46155:21)
    at Function../sp-loader.js.__WEBPACK_AMD_DEFINE_RESULT__.ff4n.ErrorBuilder.buildLoadComponentError (https://localhost:4321/temp/workbench-packages/@microsoft_sp-webpart-workbench/local-workbench/sp-webpart-workbench-assembly_default.js:46024:21)
    at https://localhost:4321/temp/workbench-packages/@microsoft_sp-webpart-workbench/local-workbench/sp-webpart-workbench-assembly_default.js:45362:75

    Any idea why it could be happening?
    Thanks.

  2. Hey Joel, thankyou for the informative article! I had a question – not sure if what I am trying to do is silly or not…

    I am making a “common” SPfx library that contains @pnp/controls, but I want to also use Storybook to rapidly UAT each component in the library (and provide docs and demo’s of how to use the components). Installing storybook within the SPfx project worked fine, and components developed that don’t use @pnp/controls render within it beautifully. However components using the @pnp/controls are throwing errors trying to reference ControlStrings and resx-strings. I though possibly following the steps you have outlined above my resolve, but no such luck!

    Do you think what I am trying is sensible, or even possible??

    Thanks again for the great blog – am quite excited to try WSL2 once I upgrade Windows 😀

    1. Hi Nigel, thanks for the feedback. Never used Storybook myself, but the idea looks great.
      Hope you have solved the problem by now, but if not, I would recommend opening an issue on the PnP reusable controls repository and ask the question there. There may be someone who has done it and can provide feedback.

      WSL2 is absolutely great. Everything is faster in general, but operations involving large number of files (npm install, remove node_modules, etc) are so much faster! Around 3 seconds to delete the entire node_modules folder is quite an improvement compared to windows 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *