Forum Discussion
Tighter security settings in browsers can impact dynamically loaded JavaScript libraries.
If you're encountering this issue, here's a heads-up. We noticed some challenges with a couple of Storyline courses that utilised unpkg.com's open-source JavaScript libraries dynamically. Specifically, our code, featuring an 'import' statement to fetch the necessary JavaScript library modules at runtime, ran into CORS-related errors in certain browsers last week.
The root cause lies in unpkg.com not consistently sending an "Access-Control-Allow-Origin: *" CORS header with all its returned files. This header is now a mandatory requirement for ESM imports. As browsers enhance their security protocols, previously functional code may encounter failures.
To address this, there are a couple of swift solutions:
- Consider using CORS-compliant CDNs like jsDelivr.net or Skypack for ESM modules.
- Alternatively, think about locally bundling critical libraries to reduce reliance on CDNs.
Stay tuned for a detailed article on this topic in the near future.
CORS Errors with pdf-lib and Storyline — Why You Should Switch from unpkg.com to jsDelivr to dynamically load code
I promised a fuller explanation - and here it is. Over the years I have posted several examples here (and seen my code appearing in other posts) where I suggested using the JavaScript library pdf-lib to create downloadable notes or certificates.
If your Storyline project has used any of my code (or other code derived from it) and it suddenly starts throwing CORS errors when generating PDFs, here’s what’s likely happening — and how to fix it.
The Problem: CORS errors from unpkg.com
In the original code, I used dynamic import() calls to load external JavaScript libraries like this:
await import("https://unpkg.com/pdf-lib@1.17.1/dist/pdf-lib.js");
This worked fine, but now browsers are enforcing stricter CORS (Cross-Origin Resource Sharing) rules, especially for JavaScript module imports.
That unpkg.com link doesn't return the proper Access-Control-Allow-Origin header, which causes this error:
Access to script at 'https://unpkg.com/...' from origin '...' has been blocked by CORS policy...
This will prevent your Storyline course from loading the library at runtime, causing PDF generation to fail.
✅ The Solution: Switch to jsDelivr
To resolve this, you simply need to load the library from a CDN that does send the correct CORS headers — like jsDelivr.
Replace this:
await import("https://unpkg.com/pdf-lib@1.17.1/dist/pdf-lib.js");
With this:
PDFLib = await import("https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/dist/pdf-lib.esm.min.js");
(Don’t forget to declare let PDFLib; at the top of your script to make it available globally - I hadn't done that in my original examples and, it worked but was risky!)
If you’re also using tiny-save-as to download the generated PDF, you’ll need to do the same in this section of code:
await import("https://cdn.jsdelivr.net/npm/tiny-save-as@1.0.1/dist/tiny-save-as.esm.min.js")
.then(({ default: saveAs }) => { saveAs(new Blob([pdfBytes]), filename); });
Why This Matters
- unpkg.com doesn’t always send CORS headers for ESM imports
- jsDelivr is fully CORS-compliant and supports modern module usage
- This fix makes your Storyline + PDF solution reliable across all modern browsers and LMS platforms
7 Replies
- JohnCooper-be3cCommunity Member
CORS Errors with pdf-lib and Storyline — Why You Should Switch from unpkg.com to jsDelivr to dynamically load code
I promised a fuller explanation - and here it is. Over the years I have posted several examples here (and seen my code appearing in other posts) where I suggested using the JavaScript library pdf-lib to create downloadable notes or certificates.
If your Storyline project has used any of my code (or other code derived from it) and it suddenly starts throwing CORS errors when generating PDFs, here’s what’s likely happening — and how to fix it.
The Problem: CORS errors from unpkg.com
In the original code, I used dynamic import() calls to load external JavaScript libraries like this:
await import("https://unpkg.com/pdf-lib@1.17.1/dist/pdf-lib.js");
This worked fine, but now browsers are enforcing stricter CORS (Cross-Origin Resource Sharing) rules, especially for JavaScript module imports.
That unpkg.com link doesn't return the proper Access-Control-Allow-Origin header, which causes this error:
Access to script at 'https://unpkg.com/...' from origin '...' has been blocked by CORS policy...
This will prevent your Storyline course from loading the library at runtime, causing PDF generation to fail.
✅ The Solution: Switch to jsDelivr
To resolve this, you simply need to load the library from a CDN that does send the correct CORS headers — like jsDelivr.
Replace this:
await import("https://unpkg.com/pdf-lib@1.17.1/dist/pdf-lib.js");
With this:
PDFLib = await import("https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/dist/pdf-lib.esm.min.js");
(Don’t forget to declare let PDFLib; at the top of your script to make it available globally - I hadn't done that in my original examples and, it worked but was risky!)
If you’re also using tiny-save-as to download the generated PDF, you’ll need to do the same in this section of code:
await import("https://cdn.jsdelivr.net/npm/tiny-save-as@1.0.1/dist/tiny-save-as.esm.min.js")
.then(({ default: saveAs }) => { saveAs(new Blob([pdfBytes]), filename); });
Why This Matters
- unpkg.com doesn’t always send CORS headers for ESM imports
- jsDelivr is fully CORS-compliant and supports modern module usage
- This fix makes your Storyline + PDF solution reliable across all modern browsers and LMS platforms
- ToddVillariCommunity Member
Thank you. This is exactly what happened in Chrome some time back.
- JohannesBurkeCommunity Member
hi there,
thanks a lot for sharing this.(Don’t forget to declare let PDFLib
Dumb question but how do I declare the PDFlib? Can you input the code here? Sorry but I'm a noob regarding javascript.
Regards,
John- JMorrisonCommunity Member
I would love to know what the code is for this line as well JohnCooper-be3c
Thanks so much!!!
- JohnCooper-be3cCommunity Member
To declare PDFLib as a global variable just add the code:
let PDFlib;
near the top of your JavaScript - perhaps just before you call the function
Constructpdf();
Hope that helps...