DEV Community

KahWee Teng
KahWee Teng

Posted on Originally published at kahwee.com on

Vite’s ?url Import Gives You a URL, Not jQuery

The confusing part is only four characters long: ?url. Add it to a Vite import and the value changes from executable JavaScript to the address of an asset.

import $ from 'jquery/dist/jquery.slim.js';
import jqueryUrl from 'jquery/dist/jquery.slim.js?url';

typeof $;          // "function"
typeof jqueryUrl;  // "string"
Enter fullscreen mode Exit fullscreen mode
Import Value in your code What happens at import time
jquery.slim.js jQuery’s API JavaScript is loaded as a dependency
jquery.slim.js?url A URL string The file is treated as an asset

[!TIP]
If the next line calls the imported value, you probably do not want ?url. If the next line passes it to src, addModule(), or another URL-based browser API, you probably do.

The 20-second fix

This fails because jqueryUrl is a string, not the jQuery function:

import jqueryUrl from 'jquery/dist/jquery.slim.js?url';

jqueryUrl('#app').hide();
// TypeError: jqueryUrl is not a function
Enter fullscreen mode Exit fullscreen mode

Remove the suffix when you need to use jQuery in the current module:

import $ from 'jquery/dist/jquery.slim.js';

$('#app').hide();
Enter fullscreen mode Exit fullscreen mode

For jQuery 4, prefer the package’s public slim entry point instead of reaching into dist:

import { $ } from 'jquery/slim';

$('#app').hide();
Enter fullscreen mode Exit fullscreen mode

The jQuery project documents jquery/slim as the supported npm import for the slim build. Older jQuery 3 projects often use the dist/jquery.slim.js path shown above.

What Vite actually does

Vite calls ?url an explicit URL import. It opts a file into the asset pipeline and makes the module’s default export a string.

During development, that string may point to the source file. In a production build, Vite can give the asset a hashed filename or inline it as a data URL, depending on the file and configuration. The stable contract is not the exact path. The stable contract is: you receive a string that the browser can use as a URL.

Importing that URL does not execute the file in the current module. The file can still execute later if you load the URL through a browser API such as a script element or a worklet loader.

When ?url is the right tool

A Paint Worklet is the clean example because addModule() asks for a URL:

import workletUrl from './paint-worklet.js?url';

CSS.paintWorklet.addModule(workletUrl);
Enter fullscreen mode Exit fullscreen mode

The same idea applies when a document needs a classic script URL. For example, you can load the jQuery distribution into an iframe rather than importing jQuery into the parent page:

import jqueryUrl from 'jquery/dist/jquery.slim.js?url';

const script = iframe.contentDocument.createElement('script');
script.src = jqueryUrl;
iframe.contentDocument.head.append(script);
Enter fullscreen mode Exit fullscreen mode

Here the string is exactly what script.src needs. jQuery executes when the iframe loads the script, not when Vite imports the URL.

Do not use bare ?url for a worker graph

If a worker imports other modules, let Vite process the worker and its dependencies. Vite’s recommended worker syntax stays close to the browser standard:

const worker = new Worker(
  new URL('./worker.js', import.meta.url),
  { type: 'module' },
);
Enter fullscreen mode Exit fullscreen mode

Vite also supports ?worker when you want an imported constructor, and ?worker&url when an API specifically needs the URL of a processed worker.

Need Use You receive
Call jQuery in this module jquery/slim or jquery.slim.js jQuery’s API
Pass a file to a URL-based API ?url URL string
Read a file’s contents ?raw Source string
Create a processed worker new Worker(new URL(...)) or ?worker Worker instance or constructor

The rule worth remembering

?url does not mean “import this module from a URL.” It means “import the URL of this file.”

That one distinction explains both the error and the fix.

Sources


Go deeper

Read the original guide and future updates on KahWee.com

Top comments (0)