Module Resolution
NPM Modules
Bare Module Imports
In LiveCodes you can use node-style bare module imports for npm modules like you do in your local development. However, there are no installation or build steps required.
e.g. consider the following code:
import { v4 } from 'uuid';
document.body.innerHTML = v4();
If you run it directly in the browser, you get this error:
Uncaught TypeError: Failed to resolve module specifier "uuid". Relative references must start with either "/", "./", or "../".
However, in LiveCodes, bare module imports are transformed to full URLs that are imported from CDN (by default: esm.sh) which provides ESM versions of NPM packages.
import { v4 } from 'uuid';
becomes
import { v4 } from 'https://esm.sh/uuid';
This is made possible by using import maps.
Demo:
You can import from React like that:
import { useState } from 'react';
Demo:
It just works without a build step and without you having to worry about. And when you export your project to another service (e.g. CodePen) or as HTML, the full URL imports are used, so your code continues to work.
It is recommended to use this method for dependencies over using external scripts. The dependencies are explicitly stated in the code. And if you move to a local development environment, your bundler will take care of importing them and doing other optimizations like tree-shaking.
CommonJS Modules
CommonJS module require
s are also supported (they are converted to ESM imports).
So this also works (although not recommended - use ESM imports instead):
const { v4 } = require('uuid');
document.body.innerHTML = v4();
Exercise:
Copy the previous code snippet and paste it in the playground below. Check the generated code in the compiled code viewer.
Script code that contains import
, export
or require
gets served in a script tag with type="module"
.
NPM Package Search
NPM packages can be searched and added as script tags from the External Resources screen.
Deno Modules
Modules imported from deno.land/x (or any other URL ending in .ts
, .jsx
or .tsx
) are automatically transpiled (ts -> js) and bundled by bundlejs (using esbuild), including their relative imports. The project on LiveCodes that imports these modules does not need to be using TypeScript.
Example:
import { uuid } from 'https://deno.land/x/uuid/mod.ts';
document.body.innerHTML = uuid();
JSR Modules
Modules can be imported from jsr.io using the prefix jsr:
. The project on LiveCodes that imports these modules does not need to be using TypeScript.
Example:
import { yassify } from 'jsr:@kwhinnery/yassify';
document.body.innerHTML = yassify('Hello, World!');
GitHub/GitLab/Bitbucket
Modules can also be similarly imported from GitHub, Gitlab or Bitbucket. Also these imports are transpiled and bundled (see Deno Modules).
import { flatten } from 'https://github.com/remeda/remeda/blob/master/src/flatten.ts';
console.log(flatten([[1, 2], [3], [4, 5]])); // -> [1, 2, 3, 4, 5]
If you do not want the import URL to be bundled (e.g. in Deno or GitHub imports), add #nobundle
to the end of URL.
Example:
import { flatten } from 'https://github.com/remeda/remeda/blob/master/src/flatten.ts#nobundle';
If you want to bundle (and transpile) any import URL, prefix it with bundle:
(see below).
CDN Providers
By default, npm modules are imported from esm.sh. You may choose another provider by using a CDN prefix. These are examples of importing the library uuid
:
uuid
→ https://esm.sh/uuid (info)
esm.sh:uuid
→ https://esm.sh/uuid (info)
skypack:uuid
→ https://cdn.skypack.dev/uuid (info)
jsdelivr:uuid
→ https://cdn.jsdelivr.net/npm/uuid (info)
esm.run:uuid
→ https://esm.run/uuid (info)
unpkg:uuid
→ https://unpkg.com/uuid?module (info)
esbuild:uuid
→ https://esbuild.vercel.app/uuid (info)
bundlejs:uuid
→ https://deno.bundlejs.com/?file&q=uuid (info)
bundle:uuid
→ https://deno.bundlejs.com/?file&q=uuid (info)
deno:uuid
→ https://deno.bundlejs.com/?file&q=https://deno.land/x/uuid/mod.ts (info)
npm:uuid
→ https://esm.sh/uuid (info)
node:uuid
→ https://esm.sh/uuid (info)
jsr:@std/uuid
→ https://esm.sh/jsr/@std/uuid (info)
jspm:uuid
→ https://jspm.dev/uuid (info - DEPRECATED)
Example:
import { useState } from 'esm.sh:react';
Please note that importing the same module (even for dependencies) from different CDNs may cause conflicts.
Example:
// this will NOT work!
import React, { useState } from 'esm.sh:react'; // React from esm.sh
import { createRoot } from 'skypack:react-dom/client'; // React from skypack.dev
Change Default CDN
Default CDN can be changed on project-level using the custom settings property defaultCDN
which accepts a string representing one of the CDN aliases listed above.
Example: This assigns Skypack as the default CDN for all imports of the project
{
"defaultCDN": "skypack"
}
Package Version
Most CDN providers allow specifying package version using the format:
{pkgName}@{version}/{path}
.
Example:
import latest from 'lodash';
import v3 from 'lodash@3';
console.log(latest.VERSION); // -> 4.17.21
console.log(v3.VERSION); // -> 3.10.1
Custom Module Resolution
Module resolution described in this page mainly depends on import maps. The generated import map is added to the result page.
You may wish to override or customize module resolution behavior (e.g. change URL, CDN, specify version, import custom unpublished library, ...etc. ), however you cannot add another import map script because currently multiple import maps are not yet supported.
LiveCodes allows you to add your custom import map by one of the following methods:
Custom Settings
In the standalone app, via the custom settings property imports
.
Example:
{
"imports": {
"my-lib": "https://my-server.com/path/to/library.js"
}
}
SDK
For embedded playgrounds, use the SDK embed option config.imports
.
Example:
import { createPlayground } from 'livecodes';
const config = {
imports: {
'my-lib': 'https://my-server.com/path/to/library.js',
},
// other configurations ...
};
createPlayground('#container', { config });
Please note that you may also provide custom type definitions for your custom modules for editor intellisense and better development experience.