Mar 13, 2024
How to use external libraries in Theme App Extensions for your Shopify App
To integrate libraries like FlatPickr into Shopify, upload minified assets to Shopify's CDN and access them with the asset_url liquid filter, ensuring seamless UI enhancements without affecting performance.
One of the joys of programming is leveraging existing solutions rather than reinventing the wheel. When someone has already developed a library that meets your needs, there's no need to write it from scratch. This principle is especially relevant within the Shopify ecosystem, where tools like Polaris for App Bridge components and the Shopify API for GraphQL and REST endpoints are invaluable. However, when developing frontend Theme UI extensions, the approach becomes more nuanced.
Shopify takes great care to ensure Theme UI extensions do not adversely affect the storefront experience. Excessive page load times can reduce conversion rates and interactions, potentially costing store owners sales. Consequently, Shopify imposes restrictions on remote access and the methods used to access content, given the significant impact of request-reliant content on page load times. Despite these limitations, many libraries offer compelling functionalities. The challenge lies in balancing performance with added value.
Numerous libraries enable the incorporation of unique components into your application without the need to write complex code for implementation. While there are countless examples, let's use FlatPickr to illustrate the process of integrating an external library into your Theme UI extensions and accessing it within your liquid code.
Adding Libraries
Shopify restricts remote imports from CDNs, leading to CORS errors and deployment issues if attempted. While sometimes these restrictions are mere suggestions, other times they are strict prohibitions due to loading concerns. However, there is a workaround. To minimize load times, consider adding minified JS or CSS files to the Shopify CDN for your app.
Upon creating a Theme UI extension, you'll notice an assets
folder in your extension directory. This folder can contain HTML, CSS, JS, images, and other assets, which you can then incorporate into your code. When deployed, these assets receive a Shopify CDN URL. However, directly calling these assets in your liquid or JS code won't work due to the cloud storage structure. Shopify provides a liquid solution, asset_url
, to access an asset's URL based on its local path:
script.src = "{{ 'flatpickr.min.js' | asset_url }}";
This code snippet, assuming FlatPickr.min.js
is located at the root of the assets
folder (not in a subdirectory), demonstrates how to embed a script in a page using liquid within a <script>
tag. The asset_url
tag dynamically generates the asset's CDN URL, which is then assigned to the script's src
attribute.
To embed the script or stylesheet on a page, consider the following approach:
async function loadFlatPickr() { return new Promise(resolve => { const embedLocation = document.head; const script = document.createElement("script"); script.src = "{{ 'flatpickr.min.js' | asset_url }}"; script.onload = () => { resolve(flatpickr); }; const link = document.createElement("link"); link.rel = "stylesheet"; link.href = "{{ 'flatpickr.min.css' | asset_url }}"; embedLocation.appendChild(link); embedLocation.appendChild(script); }); }
This function serves as a wrapper to fetch and embed scripts on the page, resolving the promise with the library object once loaded. This ensures the library is accessible only after successful embedding, preventing errors in its usage.
To use the library:
loadFlatPickr() .then(flatpickr => { // Use your library here }) .catch(err => console.error(err)); const flatpickr = await loadFlatPickr(); // The library is also accessible in this scope
Summary
Integrating external libraries into Shopify can be challenging due to restrictions on remote CDN usage and limitations on the Shopify CDN. The method described above offers a solution that saves time and leverages the vast world of libraries to enhance your UI and streamline development.
Happy coding,
~ Josh