A fast, smart, & global CDN for modern(es2015+) web development.
MIT License
Bot releases are visible (Hide)
🎉🎉🎉 Introducing esm.sh/run, a 1KB script allows you to write jsx/tsx
in HTML without build!
<script type="module" src="https://esm.sh/run"></script>
Then you can add <script>
elements with non-javascript type in your HTML, for example text/babel
:
<script type="text/babel">
console.log("esm.sh run!" as string)
</script>
Supported types:
text/babel
(recommended, highlight is working in vscode)text/jsx
text/ts
text/tsx
esm.sh run supports import maps, it even works in outdated browser that doesn't support the feature.
<script type="importmap">
{
"imports": {
"@jsxImportSource": "https://esm.sh/[email protected]",
"react-dom/client": "https://esm.sh/[email protected]/client"
}
}
</script>
The special @jsxImportSource
in the imports
is using for JSX transform, you can alternate it to your preferred runtime, for example https://esm.sh/[email protected]
.
After the page loaded, the 1KB tiny script computes the hash of the source of non-javascript <script>
elements, then checks the compiled JS exists in the cache, otherwise sends the source code to esm.sh build API and stores it in the cache system.
The cache system includes two iters of storage, are the localStoarge and the Cloudflare Edge network, to make the compiled JS load fast!
There are some limitations you need to be aware of:
raw.esm.sh
hostname for ?raw
option?no-bundle
optionesm.sh
field in package.jsonesm.sh v134 mainly includes some bugfix patches. And now you can add allowList option to serve specific packages on you self-hosting esm.sh server. (Thanks @olekenneth for contributing to this!)
transformOnly
option for build apiallowList
in config (#745 by @olekenneth).npmrc
file if NpmRegistry
is set (close #737) (#751 by @edeustace)In v133, we introduced the ?raw
mode that returns the raw JS files and fixed a bunch of bugs.
In rare cases, you may want to request JS source files from packages, as-is, without transformation into ES modules. To do so, you need to add a ?raw
query to the request URL.
For example, you might need to register a package's source script as a service worker in a browser that does not yet support the type: "module"
option:
await navigator.serviceWorker.register(
new URL(
"https://esm.sh/[email protected]/playground-service-worker.js?raw",
import.meta.url.href
),
{ scope: '/' }
);
You may alternatively specify an &raw
extra query after the package version:
<playground-project sandbox-base-url="https://esm.sh/[email protected]&raw/"
></playground-project>
so that transitive references in the raw assets will also be raw requests.
Thanks @johnyanarella for contributing to this.
?raw
to support requests for raw package source files (#731 by @johnyanarella)setMaxListeners
to node:events
polyfill (#719)cwd
method of node:process
polyfill (close #718)applyConditions
function use node
condition for browser (close #732)*.css.js
path (close #728)browser
in package.jsonIn v132, no features are added but some bugs have been fixed.
?external=*
set (close #714)bigint
and top-level-await
for all targets (close #711)node:process
ployfill module mssing the hrtime
methodgit
commandvaryUA
option for polyfill modulesIn v131, we improved the /build
API to avoid duplicated builds of same input code, and fixed some bugs:
/build
API*.mjs
url?external
option ignoring sub-modulesexports
in package.json (close #705).js
) to new build path (.mjs
) (close #703)esm.sh v130 improves the esm-cjs-lexer to get correct exports
of a minified UMD module, this can fix error "missed named exports" of some cjs only packages. The great change was contributed by @lewisl9029, huge thanks ❤️
.mjs
module (close #691)?bundle
mode ignores node_process.js
(close #694)@types/react@18
to 18.2.15
esbuild
to 0.18.17
esm.sh v129 mainly inclueds some bug fixs:
X-Esm-Deps
header (close #683)exports
of package.json when looping (close #683)typeof window
for deno target (close #681)?target=node
"
cacheKey
with X-Real-Origin
headerIn v128, we added an official Docker image to allow you to self-host esm.sh more easily (This is based on johnpangalos/docker-esm-dot-sh by @johnpangalos, thank you!).
docker pull ghcr.io/esm-dev/esm.sh
More usage check HOSTING.md
For Deno users, we upgraded stableBuild to latest(v128) this may break your deno.lock.
?external
for depsAccess-Control-Expose-Headers
headersIn v127, we improved the network waterfall by adding the dependency imports of current module in the entry module (aka. preload).
For example: https://esm.sh/[email protected]
import "https://esm.sh/stable/[email protected]/es2022/react.mjs"; /* Added in v127 */
import "https://esm.sh/v127/[email protected]/es2022/scheduler.mjs"; /* Added in v127 */
export * from "https://esm.sh/v127/[email protected]/es2022/react-dom.mjs";
export { default } from "https://esm.sh/v127/[email protected]/es2022/react-dom.mjs";
For framework authors, esm.sh provides an extra X-Esm-Deps
header that allows you to get those preload import urls.
const res = await fetch("https://esm.sh/[email protected]")
console.log(res.headers.get(`X-Esm-Deps`)?.split(", "))
preload
importsmodern-normalize
to the cssPackages
?alias
(close #671)esm
tag function of build API now imorts module
import { esm } from "https://esm.sh/build";
const mod = await esm`
export const foo:string = "bar"
`;
console.log(mod.foo); // "bar"
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
foo,
bar
});
this is created by esbuild with cjs
format, the cjs-lexer of esm.sh v125 or lower can't get the [foo,bar]
export names.Published by ije over 1 year ago
esm.sh v125 has been deployed to the edge(earth), includes some bugfixs and promoted denonext
target for Deno >= 1.33.2 that uses node:
specifier for the node compatibility layer.
node-fetch
import in cjs modules (close #649)node:worker_threads
polyfill(fake) (close #648)denonext
target for Deno >= 1.33.2 (close #646).json.js
path (close #645)deno/std
to 0.177.1
In v123, we added a server module for Deno runtime that allows you to serve esm.sh locally with command deno run -A https://esm.sh/server
, zero config and no code need! 🦕
Or build your deno app with esm.sh server:
// server.js
import { serve } from "https://esm.sh/v123/server";
serve((req) => {
const url = new URL(req.url);
// your routes override esm.sh routes
if (url.pathname === "/") {
// using a custom homepage
return new Response("<h1>Welcome to use esm.sh!</h1>", {
headers: { "Content-Type": "text/html" },
});
}
});
// $ deno run -A -r server.js
Warning: currently the server doesn't work with Deno Deploy, we are working on it.
/server
endpoint for Deno to serve esm.sh locally.d.ts
walker (close #640)v
prefix in version
(close #639)findFiles
function (close #638)esm.sh v122 has been deployed to the edge(earth), includes some bugfixs and worker improvement:
We used
map
data structure of Golang to mark requires(imports) in a cjs moudle before v122,
it creates import exprs in random order, that may break the loop imports.
X-Real-Origin
and X-Esm-Worker-Version
headersCORS
issue (close #631)esm.sh v121 includes some bug fix patches:
browser
field for package main if possible
{
"name": "pkg",
"version": "1.0.0",
"main": "./index.js",
"browser": {
"./index.js": "./browser.js"
}
}
?css
and GET /build
*.js.js
module path (close #627)pako
to the requireModeAllowList
Published by ije over 1 year ago
In v120, we open-sourced the Cloudflare worker that reveals how we handle 10M requests pre day at edge(earth). You can use it to build your own fast CDN easily:
import worker from "esm-worker";
export default worker((req, ctx) => {
// your routes override esm.sh routes
if (ctx.url.pathname === "/") {
return new Response("<h1>Welcome to use esm.sh!</h1>", {
headers: { "content-type": "text/html" },
});
}
})
More details please check esm-worker.
We improved the build API allows you to add types
for your modules, it's useful for types checking and lsp completion:
import { build } from "https://esm.sh/build"
const { url } = await build({
dependencies: {
preact: "^10.13.2",
},
code: `
export { h } from "preact";
`,
types: `
export { h } from "preact"
`,
})
types
optionHEAD
methodnull
for browser exclude (close #613)zlib-sync
to nativeNodePackages (close #621)X-Typescript-Types
headerexports
resloving*.json
urlin v118, we added an experimental API that allows you to build a module with custom input(code).
import build, { esm } from "https://esm.sh/build"
const ret = await esm`
/* @jsx h */
import { h } from "[email protected]";
import { renderToString } from "[email protected]";
export default () => renderToString(<h1>Hello world!</h1>);
`
// use `build` function
const ret = await build({
dependencies: {
"preact": "^10.13.2",
"preact-render-to-string": "^6.0.2"
},
code: `
/* @jsx h */
import { h } from "preact";
import { renderToString } from "preact-render-to-string";
export default () => renderToString(<h1>Hello world!</h1>);
`
})
const { default: render } = await import(ret.url)
render() // "<h1>Hello world!</h1>"
// use bundled module
const { default: render } = await import(ret.bundleUrl)
Changelog:
__export(require("..."))
pattern (close #611)Auth
middlewarestableBuild
to v118stableBuild
In v116, we added new feature to allow you to import modules or load assert from a Github repo: /gh/OWNER/REPO/PATH
. For example:
// ensure there is a `package.json` in the root of the repo
import tslib from "https://esm.sh/gh/microsoft/tslib"
load a svg image via https://esm.sh/gh/microsoft/fluentui-emoji/assets/Party popper/Color/party_popper_color.svg
This also fix some packages with dependency like git+http://github.com/microsoft/tslib
For Deno users, we fixed some missed/incorrect dts by respecting the typesVersions
field of package.json.
Changelog:
nativeNodePackages
(close #591)typesVersions
(close #593)exports
glob condition resloving (close #594)