Skip to main content
RapidDev - Software Development Agency
retool-tutorial

How to Import Libraries in Retool's JavaScript Editor

To import JavaScript libraries in Retool, open App Settings (gear icon in the top toolbar) and add CDN URLs to the Preloaded JavaScript section. Libraries loaded this way are available as global variables (e.g., _ for lodash, moment for moment.js) in all JS Queries in the app. Retool also pre-bundles lodash and moment.js — they are available without any import configuration.

What you'll learn

  • How to add external JavaScript libraries via Retool's Preloaded JavaScript setting
  • How to load libraries from a CDN URL and make them available in all JS Queries
  • How to use lodash (_) and moment.js for data manipulation in Retool
  • How to load a custom or self-hosted JavaScript library into a Retool app
  • Limitations of library imports in Retool vs standard Node.js environments
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read10-15 minRetool Cloud and Self-hostedLast updated March 2026RapidDev Engineering Team
TL;DR

To import JavaScript libraries in Retool, open App Settings (gear icon in the top toolbar) and add CDN URLs to the Preloaded JavaScript section. Libraries loaded this way are available as global variables (e.g., _ for lodash, moment for moment.js) in all JS Queries in the app. Retool also pre-bundles lodash and moment.js — they are available without any import configuration.

Quick facts about this guide
FactValue
ToolRetool
DifficultyBeginner
Time required10-15 min
CompatibilityRetool Cloud and Self-hosted
Last updatedMarch 2026

Loading External JavaScript Libraries in Retool

Retool's JavaScript editor lets you write custom logic using any globally available JavaScript library. Retool pre-bundles several popular libraries — lodash (available as _), moment.js (available as moment), and others — so you can use them without any configuration.

For libraries not included by default, you can load them from a CDN (like jsDelivr or unpkg) by adding the URL to the Preloaded JavaScript section in App Settings. The library's script tag loads before your queries run, making any global it exports (like Chart, Papa, or dayjs) available in your JS Queries.

This tutorial covers loading libraries from CDN, using the pre-bundled lodash and moment.js, and practical examples of each in Retool workflows.

Prerequisites

  • A Retool account (Cloud or Self-hosted)
  • Editor access to a Retool app (Edit permissions or above)
  • Basic familiarity with writing JS Queries in Retool
  • The CDN URL of the library you want to import (from jsDelivr, unpkg, or your own host)

Step-by-step guide

1

Check if your library is already pre-bundled in Retool

Before adding a CDN URL, check whether Retool already bundles the library you need. Retool includes lodash (accessed as _ or lodash), moment.js (accessed as moment), numbro (number formatting), Papa Parse (CSV parsing, accessed as Papa), and several others. Create a quick JS Query and log _ to the console — if it prints the lodash object, it is already available. You do not need Preloaded JavaScript for these built-ins.

typescript
1// Test in a JS Query — check which libraries are pre-bundled
2console.log('lodash:', typeof _); // 'object' if available
3console.log('moment:', typeof moment); // 'function' if available
4console.log('Papa:', typeof Papa); // 'object' if available
5
6// Use lodash immediately if available
7const grouped = _.groupBy(query1.data, 'category');
8console.log(grouped);

Expected result: The console shows the type of each library. If 'object' or 'function', the library is pre-bundled and ready to use.

2

Open App Settings to access Preloaded JavaScript

In the Retool editor, click the gear icon in the top toolbar to open App Settings. In the left sidebar of the settings panel, look for the Scripts & Styles section (sometimes labeled Advanced). You will find two text areas: Preloaded JavaScript and Preloaded CSS. The Preloaded JavaScript section is where you add script tags for external libraries. These scripts load before any queries run when a user opens the app.

Expected result: App Settings panel is open and you can see the Preloaded JavaScript text area.

3

Add a CDN script tag for your library

In the Preloaded JavaScript text area, add a standard HTML script tag pointing to the library's CDN URL. Get the CDN URL from jsDelivr (https://www.jsdelivr.com) or unpkg (https://unpkg.com) by searching for the package name. Always pin to a specific version to prevent unexpected breaking changes when the library updates.

typescript
1<!-- In App Settings Scripts & Styles Preloaded JavaScript -->
2
3<!-- Load date-fns for modern date manipulation -->
4<script src="https://cdn.jsdelivr.net/npm/date-fns@3.6.0/cdn.min.js"></script>
5
6<!-- Load Papa Parse for CSV processing -->
7<script src="https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js"></script>
8
9<!-- Load numeral.js for number formatting -->
10<script src="https://cdn.jsdelivr.net/npm/numeral@2.0.6/numeral.min.js"></script>
11
12<!-- Load a custom analytics helper from your own CDN -->
13<script src="https://cdn.yourcompany.com/retool-helpers/v1.2.0/helpers.min.js"></script>

Expected result: The script tag is saved in Preloaded JavaScript. The library loads when the app is next opened.

4

Use the library in a JS Query

After saving the Preloaded JavaScript setting, create or open a JS Query. The library is now available as a global variable — for example, dateFns, numeral, or whatever global the library exports. Reference it directly without any import statement. If you are unsure of the global name, check the library's documentation for 'UMD global name' or 'browser global'.

typescript
1// Using date-fns (loaded from CDN as dateFns)
2const rawDates = query1.data.map(row => row.created_at);
3const formattedDates = rawDates.map(date =>
4 dateFns.format(new Date(date), 'MMM d, yyyy')
5);
6return query1.data.map((row, i) => ({
7 ...row,
8 created_at_formatted: formattedDates[i]
9}));
10
11// Using numeral for currency formatting
12const totalRevenue = query1.data.reduce((sum, row) => sum + row.amount, 0);
13const formatted = numeral(totalRevenue).format('$0,0.00');
14return { total: formatted };

Expected result: The JS Query executes without 'is not defined' errors and returns data processed by the library.

5

Use the pre-bundled lodash library for data manipulation

Lodash is available in all Retool JS Queries as _ (underscore) without any configuration. It is one of the most useful tools for transforming query data — grouping rows by a field, picking specific properties, flattening nested arrays, or sorting by multiple keys. Here are several practical patterns you can use immediately.

typescript
1// Group orders by status
2const byStatus = _.groupBy(getOrders.data, 'status');
3// { pending: [...], completed: [...], cancelled: [...] }
4
5// Pick only certain columns (useful before sending to a mutation)
6const sanitized = _.map(getOrders.data, row =>
7 _.pick(row, ['id', 'customer_name', 'total'])
8);
9
10// Sort by multiple fields
11const sorted = _.orderBy(
12 getOrders.data,
13 ['status', 'created_at'],
14 ['asc', 'desc']
15);
16
17// Get unique values from a column
18const uniqueStatuses = _.uniq(_.map(getOrders.data, 'status'));
19
20// Flatten nested arrays from a join
21const flat = _.flatMap(getOrders.data, row => row.line_items || []);
22
23return sorted;

Expected result: JS Query returns transformed data using lodash operations without any import configuration.

6

Use moment.js for date formatting and calculation

Moment.js is pre-bundled in Retool as moment without any import needed. Use it to format dates for display, calculate relative times (e.g., '3 days ago'), or compare dates. Note that for new projects, the moment.js team recommends using date-fns or Luxon, but moment works fine in Retool if you are already familiar with it.

typescript
1// Format a date from query data for display
2const rows = getData.data;
3return rows.map(row => ({
4 ...row,
5 created_display: moment(row.created_at).format('MMM D, YYYY'),
6 relative_time: moment(row.created_at).fromNow(), // '3 days ago'
7 days_old: moment().diff(moment(row.created_at), 'days')
8}));
9
10// Check if a deadline has passed
11const isOverdue = moment(table1.selectedRow.data?.due_date).isBefore(moment());
12console.log('Is overdue:', isOverdue);
13
14// Add 30 days to today (for default expiry)
15const expiryDate = moment().add(30, 'days').format('YYYY-MM-DD');

Expected result: Dates in query results are formatted and compared using moment.js methods.

Complete working example

App Settings: Preloaded JavaScript + JS Query: dataProcessor
1// === App Settings → Preloaded JavaScript ===
2// <script src="https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js"></script>
3// <script src="https://cdn.jsdelivr.net/npm/date-fns@3.6.0/cdn.min.js"></script>
4
5// === JS Query: processOrdersReport ===
6// Combines pre-bundled lodash + CDN-loaded date-fns + pre-bundled moment
7
8const orders = getOrders.data;
9
10if (!orders || orders.length === 0) {
11 return [];
12}
13
14// Step 1: Format dates with date-fns (from CDN)
15const withFormattedDates = orders.map(order => ({
16 ...order,
17 created_display: dateFns.format(new Date(order.created_at), 'MMM d, yyyy'),
18 days_since_order: dateFns.differenceInDays(new Date(), new Date(order.created_at))
19}));
20
21// Step 2: Sort by days overdue using lodash
22const sorted = _.orderBy(
23 withFormattedDates,
24 ['days_since_order'],
25 ['desc']
26);
27
28// Step 3: Group by status
29const grouped = _.groupBy(sorted, 'status');
30
31// Step 4: Add summary stats per group
32const summary = _.mapValues(grouped, (groupOrders, status) => ({
33 status,
34 count: groupOrders.length,
35 total_value: _.sumBy(groupOrders, 'total_amount'),
36 oldest_order_days: _.maxBy(groupOrders, 'days_since_order')?.days_since_order
37}));
38
39return {
40 orders: sorted,
41 summary: Object.values(summary)
42};

Common mistakes

Why it's a problem: Using require() or import statements in a Retool JS Query

How to avoid: Retool JS Queries run in a browser context, not Node.js. Use the global variable exported by the library's UMD build instead. Load libraries via Preloaded JavaScript and reference their global (e.g., _, moment, dateFns).

Why it's a problem: Adding a library to Preloaded JavaScript but getting 'X is not defined' errors

How to avoid: Reload the app after saving Preloaded JavaScript settings. Also check the library's global name — it may be different from the package name (e.g., Papa Parse exports as Papa, not papaparse).

Why it's a problem: Loading the same library twice (once pre-bundled, once from CDN)

How to avoid: Retool pre-bundles lodash, moment, and others. Adding them again from CDN creates two instances and can cause version conflicts. Remove the CDN import for pre-bundled libraries.

Why it's a problem: Using the minified source map URL instead of the production bundle

How to avoid: Use .min.js (not .js or .map) in your CDN URL. The source map (.map) file is for debugging, not execution.

Best practices

  • Always pin library versions in your CDN URLs (e.g., papaparse@5.4.1) — using 'latest' can break your app when the library releases a breaking change.
  • Check Retool's pre-bundled library list before adding a CDN script — lodash, moment, Papa Parse, and others are already included.
  • Load libraries from a reputable CDN with SRI (Subresource Integrity) hash for security — jsDelivr and unpkg both support SRI.
  • Keep the number of Preloaded JavaScript libraries small — each library adds to initial load time for end users.
  • For self-hosted Retool with strict CSP, host libraries on your own CDN rather than external CDN URLs.
  • Prefer smaller, modern alternatives when possible (date-fns over moment, native Array methods over lodash for simple operations).
  • Document which libraries are loaded and why in a comment at the top of the Preloaded JavaScript field.

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I am building a Retool app and need to use the date-fns JavaScript library in my JS Queries. Retool does not include date-fns by default. Show me: (1) where to add the CDN script tag in Retool App Settings, (2) the correct CDN URL for date-fns from jsDelivr, (3) how to use date-fns functions in a JS Query to format dates from query results, and (4) what global variable name date-fns exports in its UMD bundle.

Retool Prompt

In my Retool app's Preloaded JavaScript setting, I have added the Papa Parse CDN script. Write a JS Query that: (1) reads a CSV string from a text area component (textArea1.value), (2) uses the globally available Papa.parse() function to parse it, (3) returns the parsed array of objects, and (4) handles parse errors by showing a utils.showNotification() error.

Frequently asked questions

Does Retool include lodash by default, or do I need to import it?

Lodash is pre-bundled in Retool and available as _ in all JS Queries without any import configuration. You can use _.groupBy, _.orderBy, _.pick, and all other lodash methods immediately. You do not need to add a CDN script tag for lodash.

Can I use ES modules (import/export) in Retool JS Queries?

No. Retool JS Queries run in a sandboxed browser context that does not support ES module syntax. All libraries must be loaded as UMD bundles via Preloaded JavaScript and accessed as global variables. Use require() or import is not available.

How do I load a private or internal JavaScript library into Retool?

Host your library on an internal CDN or file server accessible from your Retool instance. Add the script tag with the internal URL to App Settings → Preloaded JavaScript. For Retool Cloud, the URL must be publicly accessible or served with appropriate CORS headers.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Learning is great. Shipping is faster with help.

Our engineers have built 600+ apps on Retool and the tools around it. If your project needs to be live sooner than your learning curve allows — book a free consultation.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.