Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
f217db5
Move `server/cmd/main.go` to `server/esmd/main.go`
ije Mar 4, 2025
a66bf04
Add dev command
ije Mar 4, 2025
0e2426d
cli: Update package.json
ije Mar 4, 2025
4f85579
Update tsx script
ije Mar 4, 2025
040a35b
Improve loader
ije Mar 4, 2025
b4b5f6a
Update unocss demo apps
ije Mar 4, 2025
f54c0bb
Merge branch 'main' into cli-im-command
ije Mar 5, 2025
39b7e60
Merge branch 'main' into cli-im-command
ije Mar 5, 2025
b74366c
Refactor
ije Mar 6, 2025
13e7b0d
Introduce web package
ije Mar 6, 2025
6414dd2
Use unocss/preset-wind3
ije Mar 6, 2025
8e4803b
Update demo apps
ije Mar 6, 2025
23665ad
wip
ije Mar 6, 2025
4eb0985
Improve web server
ije Mar 6, 2025
17fd4bc
Update cli help message
ije Mar 6, 2025
0f7fb08
Update CLI help message
ije Mar 6, 2025
94f38cc
Update go mod
ije Mar 6, 2025
1999679
Improve web server
ije Mar 6, 2025
3223689
Rename
ije Mar 6, 2025
cfec3f6
Improve web handler
ije Mar 7, 2025
ce690a2
Improve css module
ije Mar 7, 2025
fd3585d
Use `@esm.sh/tsx` 1.1.0
ije Mar 8, 2025
d31336e
Improve HMR
ije Mar 8, 2025
83db2e7
Update loader.js
ije Mar 8, 2025
eda29f2
refactor
ije Mar 8, 2025
04ba1b1
Improve hmr
ije Mar 10, 2025
2c3e1ec
Update demo apps
ije Mar 10, 2025
0e9e8bd
wip
ije Mar 10, 2025
d116b35
Refactor
ije Mar 11, 2025
6e77a67
Use go-json
ije Mar 12, 2025
02a295a
Update readme
ije Mar 16, 2025
40e8b41
wip
ije Mar 22, 2025
dc7f85e
wip
ije Mar 22, 2025
cb6c23b
Fix wasm url related to `import.meta.url` (#1110)
ije Mar 22, 2025
3eec88b
Don't analyze splitting when the `sideEffects` set to `false` (#1111)
ije Mar 23, 2025
f57d7ba
Fix merge conflict
ije Mar 23, 2025
f33877c
Update demo apps
ije Mar 24, 2025
14630ad
Revert "Update demo apps"
ije Mar 26, 2025
ea8a575
Refactor
ije Mar 30, 2025
8241f6a
add fetch package
ije Apr 2, 2025
036fba6
typo
ije Apr 2, 2025
52fba95
remove purge api
ije Apr 2, 2025
1ba79a2
refactor
ije Apr 2, 2025
f1106fd
Update go mod
ije Apr 2, 2025
f3086c1
Update deps
ije Apr 5, 2025
959bdc4
Update readme
ije Apr 6, 2025
af7f43f
Support rpc
ije Apr 6, 2025
0e396e1
refactor
ije Apr 6, 2025
83a1397
Merge branch 'main' into cli-im-command
ije Apr 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ jobs:
registry-url: 'https://registry.npmjs.org'

- name: Build CLI
run: go build -ldflags="-s -w -X 'github.com/esm-dev/esm.sh/server.VERSION=${{ github.ref_name }}'" -o cli/build/bin/esm.sh-cli-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }} cli/cmd/main.go
run: go build -ldflags="-s -w -X 'github.com/esm-dev/esm.sh/server.VERSION=${{ github.ref_name }}'" -o cli/build/bin/esm.sh-cli-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }} cli/esmd/main.go
env:
GOOS: ${{ matrix.os }}
GOARCH: ${{ matrix.arch }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
deno-version: ${{ matrix.deno-version }}

- name: Run Unit Tests
run: go test ./server ./server/storage -v
run: go test ./server ./internal/* -v
env:
GO_TEST_S3_ENDPOINT: ${{ secrets.GO_TEST_S3_ENDPOINT }}
GO_TEST_S3_REGION: ${{ secrets.GO_TEST_S3_REGION }}
Expand Down
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
.DS_Store
.idea/
.vscode/
*.log
config.json
esmd
.esmd/
node_modules/
dist/
!server/esmd
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ Create a `config.json` file in the project root directory following the example

More server options please check [config.exmaple.jsonc](./config.example.jsonc).

## Running the Server from Source Code
## Running the Server in Debug Mode

```bash
make dev/server
make debug/server
```

Then you can import `React` from "http://localhost:8080/react"
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ RUN apk update && apk add --no-cache git
RUN git clone --branch $SERVER_VERSION --depth 1 https://github.com/esm-dev/esm.sh /tmp/esm.sh

WORKDIR /tmp/esm.sh
RUN go build -ldflags="-s -w -X 'github.com/esm-dev/esm.sh/server.VERSION=${SERVER_VERSION}'" -o esmd server/cmd/main.go
RUN go build -ldflags="-s -w -X 'github.com/esm-dev/esm.sh/server.VERSION=${SERVER_VERSION}'" -o esmd server/esmd/main.go
# ---

FROM alpine:latest
Expand Down
2 changes: 1 addition & 1 deletion HOSTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ You can find all the server options in [config.example.jsonc](./config.example.j
You will need [Go](https://golang.org/dl) 1.22+ to compile and run the server.

```bash
go run server/cmd/main.go --config=config.json
go run server/esmd/main.go --config=config.json
```

Then you can import `React` from <http://localhost:8080/react>.
Expand Down
21 changes: 6 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
dev/cli/serve:
@go run -tags debug main.go serve cli/demo/${app}

dev/cli/init:
@go run -tags debug main.go init

dev/cli/i:
@go run -tags debug main.go i ${package}
debug/cli/dev:
@go run -tags debug main.go dev cli/demo/${app}

dev/cli/im/add:
@go run -tags debug main.go im add ${package}

dev/cli/im/update:
@go run -tags debug main.go im update ${package}
debug/cli/serve:
@go run -tags debug main.go serve cli/demo/${app}

dev/server: config.json
debug/server: config.json
@rm -rf .esmd/log
@rm -rf .esmd/storage
@rm -rf .esmd/esm.db
@go run -tags debug server/cmd/main.go --config=config.json
@go run -tags debug server/esmd/main.go --config=config.json

test/server:
@./test/bootstrap.ts ${dir}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ esm.sh allows you to import [JavaScript modules](https://developer.mozilla.org/e
import * as mod from "https://esm.sh/PKG[@SEMVER][/PATH]";
```

With [import maps](https://github.com/WICG/import-maps), you can even use bare import specifiers intead of URLs:
With [import maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap), you can even use bare import specifiers intead of URLs:

```html
<script type="importmap">
Expand Down Expand Up @@ -244,7 +244,7 @@ worker.postMessage("The string that is being hashed");

## Using Import Maps

[**Import Maps**](https://github.com/WICG/import-maps) has been supported by most modern browsers and Deno natively.
[**Import Maps**](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) has been supported by most modern browsers and Deno natively.
This allows _**bare import specifiers**_, such as `import React from "react"`, to work.

esm.sh introduces the `?external` for specifying external dependencies. By employing this query, esm.sh maintains the import specifier intact, leaving it to the browser/Deno to resolve based on the import map. For example:
Expand Down Expand Up @@ -279,7 +279,7 @@ Alternatively, you can **mark all dependencies as external** by adding a `*` pre
}
```

Import maps supports [**trailing slash**](https://github.com/WICG/import-maps#packages-via-trailing-slashes) that can
Import maps supports [**trailing slash**](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap#packages-via-trailing-slashes) that can
not work with URL search params friendly. To fix this issue, esm.sh provides a special format for import URL that allows
you to use query params with trailing slash: change the query prefix `?` to `&` and put it after the package version.

Expand Down
13 changes: 8 additions & 5 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

A _nobuild_ tool for modern web development.

> [!WARNING]
> The `esm.sh` CLI is still in development and may not be stable. Use it at your own risk.

## Installation

You can install `esm.sh` CLI from source code:
Expand Down Expand Up @@ -29,9 +32,9 @@ $ esm.sh --help
Usage: esm.sh [command] <options>

Commands:
i, add [...pakcage] Alias to 'esm.sh im add'.
im, importmap Manage "importmap" script.
init Create a new nobuild web app with esm.sh CDN.
serve Serve a nobuild web app with esm.sh CDN, HMR, transforming TS/Vue/Svelte on the fly.
build Build a nobuild web app with esm.sh CDN.
add, i [...packages] Alias to 'importmap add'.
importmap, im Manage "importmap" script.
init Create a new web application.
serve Serve a web application.
dev Serve a web app in development mode.
```
176 changes: 176 additions & 0 deletions cli/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package cli

import (
"bytes"
"flag"
"fmt"
"io"
"os"

"github.com/esm-dev/esm.sh/internal/importmap"
"github.com/goccy/go-json"
"github.com/ije/gox/term"
"golang.org/x/net/html"
)

const addHelpMessage = "\033[30mesm.sh - A nobuild tool for modern web development.\033[0m" + `

Usage: esm.sh add [...packages] <options>

Examples:
esm.sh add react@19.0.0
esm.sh add react@19 react-dom@19
esm.sh add react react-dom @esm.sh/router

Options:
--help Show help message
`

const htmlTemplate = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello, world!</title>
<script type="importmap">
%s
</script>
</head>
<body>
<h1>Hello, world!</h1>
</body>
</html>
`

// Add adds packages to "importmap" script
func Add() {
help := flag.Bool("help", false, "Show help message")
arg0, argMore := parseCommandFlag(2)

if *help {
fmt.Print(addHelpMessage)
return
}

var packages []string
if arg0 != "" {
packages = append(packages, arg0)
packages = append(packages, argMore...)
}

err := updateImportMap(packages)
if err != nil {
fmt.Println(term.Red("✖︎"), "Failed to add packages: "+err.Error())
}
}

func updateImportMap(packages []string) (err error) {
indexHtml, exists, err := lookupCloestFile("index.html")
if err != nil {
return
}

if exists {
var f *os.File
f, err = os.Open(indexHtml)
if err != nil {
return
}
tokenizer := html.NewTokenizer(f)
buf := bytes.NewBuffer(nil)
updated := false
for {
token := tokenizer.Next()
if token == html.ErrorToken && tokenizer.Err() == io.EOF {
break
}
if token == html.EndTagToken {
tagName, _ := tokenizer.TagName()
if string(tagName) == "head" && !updated {
buf.WriteString(" <script type=\"importmap\">\n ")
importMap := importmap.ImportMap{}
if !importMap.AddPackages(packages) {
return
}
imJson, _ := importMap.MarshalJSON()
buf.Write(imJson)
buf.WriteString("\n </script>\n")
buf.Write(tokenizer.Raw())
updated = true
continue
}
}
if token == html.StartTagToken {
tagName, moreAttr := tokenizer.TagName()
if string(tagName) == "script" && moreAttr {
var typeAttr string
for moreAttr {
var key, val []byte
key, val, moreAttr = tokenizer.TagAttr()
if string(key) == "type" {
typeAttr = string(val)
break
}
}
if typeAttr != "importmap" && !updated {
buf.WriteString("<script type=\"importmap\">\n ")
importMap := importmap.ImportMap{}
if !importMap.AddPackages(packages) {
return
}
imJson, _ := importMap.MarshalJSON()
buf.Write(imJson)
buf.WriteString("\n </script>\n ")
buf.Write(tokenizer.Raw())
updated = true
continue
}
if typeAttr == "importmap" && !updated {
buf.Write(tokenizer.Raw())
token := tokenizer.Next()
var importMap importmap.ImportMap
if token == html.TextToken {
importMapRaw := bytes.TrimSpace(tokenizer.Text())
if len(importMapRaw) > 0 {
if json.Unmarshal(importMapRaw, &importMap) != nil {
err = fmt.Errorf("invalid importmap script")
return
}
}
}
buf.WriteString("\n ")
if !importMap.AddPackages(packages) {
return
}
imJson, _ := importMap.MarshalJSON()
buf.Write(imJson)
buf.WriteString("\n ")
if token == html.EndTagToken {
buf.Write(tokenizer.Raw())
}
updated = true
continue
}
}
}
buf.Write(tokenizer.Raw())
}
fi, erro := f.Stat()
f.Close()
if erro != nil {
return erro
}
err = os.WriteFile(indexHtml, buf.Bytes(), fi.Mode())
} else {
importMap := importmap.ImportMap{}
if !importMap.AddPackages(packages) {
return
}
imJson, _ := importMap.MarshalJSON()
err = os.WriteFile(indexHtml, fmt.Appendf(nil, htmlTemplate, string(imJson)), 0644)
if err == nil {
fmt.Println(term.Dim("Created index.html with importmap script."))
}
}
return
}
41 changes: 0 additions & 41 deletions cli/command_im.go

This file was deleted.

Loading