Dynamic External JS References in SPFx Web Parts

Hello everybody!

Today I want to show you my solution how you could make dynamic external references to JS files in SPFx Web Parts.

I’m pretty sure that you already know externals property from config.json file of your SPFx Web Parts. It is supposed to be for referencing external JS libraries from your SPFx Web Parts.

By default, the web part bundler automatically includes any library that is a dependency of the web part module. This means that the library is deployed in the same JavaScript bundle file as your web part. This is more useful for smaller libraries that are not used in multiple web parts.

But in real world you always have to create more than just one web part. So you want to have your JS libraries externally and you want to have it in your local CDN, which is for example not the same for test and production environment.

I’ve done this with modifying default GULP Tasks Definition File of SPFx Web Part.

Let’s take a look.

The idea is that we change URLs of External JS Libraries from config.json file before we run gulp bundle –ship and gulp package-solution –ship tasks and after that we modify it back to original state.

For that reason I add customJSPath custom property into external library definition:

2018-10-29_1104

This represent relative path to your local CDN inside of your SharePoint Farm.

In code section below we have custom GULP task named modifyconfigfile which you have to add it into gulpfile.js file inside of your SPFx Web Part project.

var modifyConfigFile = build.subTask('modifyconfigfile-pre', (gulp, buildConfig, done) => {
    var configFC = require("./config/config");
   
    try {
        require("./temp/config-local");
    }
    catch (Err) {
        fs.writeFileSync("./temp/config-local.json", JSON.stringify(configFC, null, 2));
    }

    Object.keys(configFC.externals).forEach(element => {
        var extJS = configFC.externals[element];
        if (extJS.customJSPath) {
            extJS.path = args.targetCdn + "/" + extJS.customJSPath;
        }
    });

    fs.writeFileSync("./config/config.json", JSON.stringify(configFC, null, 2));

    return gulp.src("./temp/config-local.json");
});
build.task('modifyconfigfile', modifyConfigFile);

As you can see this task take original config.json file and copy it into temp folder as config-local.json.

Then it go into externals section of config.json file and change path property into new one: targetCdn + “/” + customJSPath

At last it save changes back to config.json file.

Firstly you have to run that task -> modifyconfigfile. Than you could run gulp bundle –ship and gulp package-solution –ship command and after that you could run cleanconfigfile task which you have to add it into gulpfile.js too:

var cleanconfigfile = build.subTask('cleanconfigfile-post', (gulp, buildConfig, done) => {
    var configFC = require("./temp/config-local");
    fs.writeFileSync("./config/config.json", JSON.stringify(configFC, null, 2));

    var clean = require("gulp-clean");
    return gulp.src("./temp/config-local.json").pipe(clean({force: true}));
});
build.task('cleanconfigfile', cleanconfigfile);

Thats all.

Here you have commands in order which you have to run it:

gulp modifyconfigfile --target-cdn $targetCDN
gulp bundle --ship --target-cdn $targetCDN
gulp package-solution --ship
gulp cleanconfigfile

You could run all those tasks with test $targetCDN URL or production $targetCDN URL depends on for which environment you want to build SPFx Web Part.

Or you could simplify and run all those four commans with one PowerShell function like this below:

function StartProvisionExact {
    param(
        [Parameter(Mandatory=$true)]
        [string]$targetCDN,
        [Parameter(Mandatory=$true)]
        [string]$webpartName
    )

    Write-Host "TargetCDN '$targetCDN'"

    $SPFxRoot = Get-Location
    $webParts = Get-ChildItem -Directory
    $found = $false
    foreach ($webPart in $webParts) {
        if ($webPart.Name -eq $webpartName) {
            $found = $true

            Set-Location -Path $SPFxRoot"/"$webPart
            Write-Host "SPFx Web Part '$SPFxRoot'"

            gulp modifyconfigfile --target-cdn $targetCDN
            gulp bundle --ship --target-cdn $targetCDN
            gulp package-solution --ship
            gulp cleanconfigfile
        }
    }

    if (!$found) {
        Write-Error "Web Part with name '$webpartName' not found"
    }
}

Cheers!
Gašper Rupnik

{End.}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Powered by WordPress.com.

Up ↑

%d bloggers like this: