If we want to deploy an SPFx webpart or extension which uses SPFx library components, then we need to handle this differently while we need to bundle and package our webpart or extension.
According to MS doc for SPFx Library component, if we want to use the library in other solution (webpart or extension) then we need to do npm link to the root directory of the library solution and run npm link <library-name> in the solution (webpart or extension) that will create symbolic link to the webpart. If we want to handle this build process in a pipeline with a symbolic link then you can refer below YML,
For this blog, let’s take PnP Modern Search v4 as an example. In v4 there is a possibility to make an extensibility library that is used for custom render.
You can download latest PnP Moder Search sppkg from here, select latest release and at the bottom you can find files that contains .sppkg
Below you can find the folder structure that’s used to deploy PnP Search Extensibility library in our site,
- pnp-package -> pnp-modern-search-parts-v4.sppkg which will be deployed to the tenant.
- search-extensibility -> which is cloned repo of folder https://github.com/microsoft-search/pnp-modern-search/tree/main/search-extensibility
- search-result-customlibrary -> which is the new spfx library that has been created for my custom render
azure-pipeline.yml for the above solution,
trigger:
branches:
include:
- master
- develop
- release/*
- feature/*
steps:
- checkout: self
- task: NodeTool@0
displayName: 'Use Node 10.x'
inputs:
versionSpec: 10.x
checkLatest: true
#region Install and bundle lib
- task: Npm@1
displayName: "npm install search-extensibility"
inputs:
command: "install"
workingDir: "search-extensibility/"
- task: Gulp@0
displayName: "Bundle search-extensibility"
inputs:
gulpFile: search-extensibility/gulpfile.js
targets: bundle
arguments: "--ship"
workingDirectory: "search-extensibility"
- script: npm link
displayName: "npm link"
workingDirectory: "search-extensibility/"
- task: Npm@1
displayName: "npm install search-result-customlibrary"
inputs:
command: "install"
workingDir: "search-result-customlibrary/"
continueOnError: false
- script: npm link @pnp/modern-search-extensibility
displayName: "npm link @pnp/modern-search-extensibility"
workingDirectory: "search-result-customlibrary/"
- task: Gulp@0
displayName: "Bundle project"
inputs:
gulpFile: search-result-customlibrary/gulpfile.js
targets: bundle
arguments: "--ship"
workingDirectory: "search-result-customlibrary"
- task: Gulp@0
displayName: "Package Solution"
inputs:
gulpFile: search-result-customlibrary/gulpfile.js
targets: "package-solution"
arguments: "--ship"
workingDirectory: "search-result-customlibrary"
- task: CopyFiles@2
displayName: "Copy Files to drop"
inputs:
Contents: |
search-result-customlibrary/sharepoint/**/*.sppkg
TargetFolder: "$(Build.ArtifactStagingDirectory)"
- task: CopyFiles@2
displayName: 'Copy PnP sppkg to drop'
inputs:
Contents: |
pnp-package/*.sppkg
TargetFolder: '$(Build.ArtifactStagingDirectory)/sharepoint'
#endregion
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: drop'
These are the tasks that will be executed if we run above yml,
And the output of the published files looks from build pipeline will be like this,
Now we successfully generated sppkg’s for our custom library through build pipeline, the next step is to deploy this in release pipeline. The below powershell can be helpful to deploy the solution (please ignore the $env variable and change those according to your need),
try {
$clientId = $env:SPO_AppID
$clientSecret = $env:SPO_AppSecret
$spoUrl = "https://tenantName.sharepoint.com"
$pnpSearchWebpartFileName = "$(System.ArtifactsDirectory)$(ArtifactAlias)dropsharepointpnp-packagepnp-modern-search-parts-v4.sppkg"
$pnpSearchExtensibilityFileName = "$(System.ArtifactsDirectory)$(ArtifactAlias)dropsharepointpnp-packagepnp-modern-search-extensibility.sppkg"
$customSearchLibraryFileName = Get-ChildItem -Path '$(System.ArtifactsDirectory)$(ArtifactAlias)dropsearch-result-customlibrarysharepointsolution' -Recurse | Where-Object { $_.PSIsContainer -eq $false -and $_.Extension -eq '.sppkg' }
Write-Host "PnP Connection to $spoUrl" -ForegroundColor Yellow
Connect-PnPOnline -Url $spoUrl -ClientId $clientId -ClientSecret $clientSecret
Write-Host "Successfully connected" -ForegroundColor Green
#region Installing PnP Search WebPart
Write-Host "Installing PnP Search WebPart" -ForegroundColor Green
$appMetadata = Add-PnPApp $pnpSearchWebpartFileName -Overwrite -Publish
$appId = $appMetadata.Id
Write-Host "Package ID: $appId"
Write-Host "Added PnP Search WebPart - DONE" -ForegroundColor Green
#endregion
#region Installing PnP Search Extensibility
Write-Host "Installing PnP Search Extensibility" -ForegroundColor Green
$appMetadata = Add-PnPApp $pnpSearchExtensibilityFileName -Scope Tenant -Overwrite -Publish -SkipFeatureDeployment
$appId = $appMetadata.Id
Write-Host "Package ID: $appId"
Write-Host "Added PnP Search Extensibility - DONE" -ForegroundColor Green
$existingApp = Get-PnPApp -Identity $appId -Scope Tenant
if ($null -ne $existingApp) {
write-host "Start: Update-PnPApp -Identity $appId"
Update-PnPApp -Identity $appId -Scope Tenant
}
else {
write-host "No installed app found"
write-host "Start Install-PnPApp -Identity $appId"
Install-PnPApp -Identity $appId -Scope Tenant
}
write-host "Publish-PnPApp -Identity $appId"
Publish-PnPApp -Identity $appId -Scope Tenant
Write-Host "Installing PnP Search Extensibility - DONE" -ForegroundColor Green
#endregion
#region Installing PnP Search Custom Library
Write-Host "Installing PnP Search Custom Library" -ForegroundColor Green
$appMetadata = Add-PnPApp $customSearchLibraryFileName.FullName -Scope Tenant -Overwrite -Publish -SkipFeatureDeployment
$appId = $appMetadata.Id
Write-Host "Package ID: $appId"
$existingApp = Get-PnPApp -Identity $appId -Scope Tenant
if ($null -ne $existingApp) {
write-host "Start: Update-PnPApp -Identity $appId -Scope Tenant"
Update-PnPApp -Identity $appId -Scope Tenant
}
else {
write-host "No installed app found"
write-host "Start Install-PnPApp -Identity $appId -Scope Tenant"
Install-PnPApp -Identity $appId -Scope Tenant
}
write-host "Publish-PnPApp -Identity $appId"
Publish-PnPApp -Identity $appId -Scope Tenant
Write-Host "Installing PnP Search Custom Library - DONE" -ForegroundColor Green
#endregion
}
catch {
Write-Host -f Red "Error while installing PnP search webpart & libraries! - " $_.Exception.Message
}
Below is the screenshot from release pipeline,
Happy Coding
Fazil
Leave a comment