惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
WordPress大学
WordPress大学
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 叶小钗
博客园 - 聂微东
阮一峰的网络日志
阮一峰的网络日志
腾讯CDC
博客园 - 三生石上(FineUI控件)
V
V2EX
有赞技术团队
有赞技术团队
V
Visual Studio Blog
小众软件
小众软件
Jina AI
Jina AI
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - Franky
量子位
T
Tailwind CSS Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
P
Palo Alto Networks Blog
Cisco Talos Blog
Cisco Talos Blog
I
Intezer
Project Zero
Project Zero
A
Arctic Wolf
P
Privacy International News Feed
V
Vulnerabilities – Threatpost
L
Lohrmann on Cybersecurity
S
Securelist
C
Cybersecurity and Infrastructure Security Agency CISA
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Tor Project blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
Security @ Cisco Blogs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Google DeepMind News
Google DeepMind News
N
News and Events Feed by Topic
TaoSecurity Blog
TaoSecurity Blog
L
LINUX DO - 热门话题
G
GRAHAM CLULEY
Help Net Security
Help Net Security
N
News | PayPal Newsroom
W
WeLiveSecurity
G
Google Developers Blog
Microsoft Security Blog
Microsoft Security Blog
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
C
Check Point Blog

ValeriaVG

Agentic Development Survival Guide Simplicity Police The sunset of Arrogance as a Service How do I delegate when I can do it faster myself? Implementing custom Calendar component Plug & Play Modular Architecture for Scalable and Maintainable Apps Me & React: 5 Years in 15 Minutes 10 Reasons NOT to Use Go for Your Next Project How Build a Web App in 11 Minutes and Fall in Love With Sveltekit Master Git in 7 Minutes Crc 32 Checksum in Wasm and Raw Js Tutorial and Benchmark Master Binary in Five Minutes Five Pro Tips to Master Promises in Js How to Use Custom Files as Modules in Nodejs How to Do Magic With Numbers 5 Ways to Use Redis in Your Next Project
ES Modules & Import Maps: Back to the Future
Valeria Viana Gusmao · 2022-09-24 · via ValeriaVG

There was a time when creating a web page meant creating an html file, yet nowadays it seems impossible to build any frontend without the bottomless pit of nodemodules, yielding a finely chewed yet hefty _bundle.xyz.js. Well, I got to learn that it might not be the case soon and, naturally, I feel the urge to share it with the rest of you.

Start with HTML

The barebones page in HTML5 looks like this:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body></body> </html>

Hint: I got this template by typing html:5 in my VSCode thanks to Emmet abbreviations

Add a module

Now, let's say we would like to add a framework to it, Preact, for example. We could do it like this:

<body> <div id="app"></div> <script type="module"> import { h, Component, render } from "https://esm.sh/preact@10.11.0"; import htm from "https://esm.sh/htm@3.1.1"; // Initialize htm with Preact const html = htm.bind(h); function App(props) { return html`<h1>Hello ${props.name}!</h1>`; } render(html`<${App} name="World" />`, document.getElementById("app")); </script> </body>

You can open the page in your browser as a simple file and see that it actually works. And that is the power of modern ECMAScript modules, that are defined by simply adding type="module" to a script tag.

For such a simple page it works great, but it can quickly become hard to work with once we add more pages.

Let's create another:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Counter</title> </head> <body> <div id="app"></div> <script type="module"> import { h, Component, render } from "https://esm.sh/preact@10.11.0"; import { useState } from "https://esm.sh/preact@10.11.0/hooks"; import htm from "https://esm.sh/htm@3.1.1"; const html = htm.bind(h); function Counter() { const [count, setCount] = useState(0); return html`<button onClick=${() => setCount((n) => n + 1)}> Count: ${count} </button>`; } render(html`<${Counter} />`, document.getElementById("app")); </script> </body> </html>

It's a good practice to specify the exact version of dependencies to avoid breaking changes, but updating those will be a mess, right?

Gladly, no! Because we could write an import-map!

Import Maps

An import map is a JSON that tells browser where to find a certain import by its alias. For example, we could create an import map with the following contents:

{ "imports": { "preact": "https://esm.sh/preact@10.11.0", "preact/": "https://esm.sh/preact@10.11.0/", "htm": "https://esm.sh/htm@3.1.1" } }

And include it on both pages like this:

<body> <div id="app"></div> <script type="importmap"> { "imports": { "preact": "https://esm.sh/preact@10.11.0", "preact/": "https://esm.sh/preact@10.11.0/", "htm": "https://esm.sh/htm@3.1.1" } } </script> <script type="module"> import { h, Component, render } from "preact"; import { useState } from "preact/hooks"; import htm from "htm"; // Initialize htm with Preact const html = htm.bind(h); function App(props) { return html`<h1>Hello ${props.name}!</h1>`; } render(html`<${App} name="World" />`, document.getElementById("app")); </script> </body>

Quite neat, right? You could also use it to reference your own components and avoid long paths. Ah, future is bright!

... But we're not quite there yet.

Unfortunately, import maps are still unofficial draft and therefore some vital features, like including an external import map from a json file, is not supported or they are not supported at all in some browsers (e.g. Safari).

But I want to use it RIGHT NOW!

I hear you, so am I!

And I do have some good news for us: there is a mature JavaScript runtime, called deno that supports ESM and import maps out of the box. And fresh framework, for example, is a delight to work with.

I've recently migrated my blog to Fresh from Hugo and I can't wait to finally implement some of the dynamic features I have been postponing for too long.