From a16f8e61c6d43ab8a5ff4817b8de3e509fcc9d16 Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 08:01:46 +0800 Subject: [PATCH 01/11] Update dockerfile --- Dockerfile | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5ce7f1a6..e88844f5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,26 @@ -# --- build the server from source code +# --- build server from source code FROM golang:1.23-alpine AS builder -ENV ESM_SH_REPO https://github.com/esm-dev/esm.sh -ENV ESM_SH_VERSION main +ARG SERVER_VERSION="v136" RUN apk update && apk add --no-cache git -RUN git clone --branch $ESM_SH_VERSION --depth 1 $ESM_SH_REPO /tmp/esm.sh +RUN git clone --branch $SERVER_VERSION --depth 1 https://github.com/esm-dev/esm.sh /tmp/esm.sh WORKDIR /tmp/esm.sh -RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o esmd main.go +RUN go build -ldflags="-s -w -X 'github.com/esm-dev/esm.sh/server.VERSION=${SERVER_VERSION}'" -o esmd main.go # --- -FROM alpine:latest AS server +FROM alpine:latest -# install tini & git (use to fetch repo tags from Github) -RUN apk update && apk add --no-cache tini git +# install git (use to fetch repo tags from Github) +RUN apk update && apk add --no-cache git + +# add user and working directory +RUN addgroup -g 1000 esm && adduser -u 1000 -G esm -D esm && mkdir /esmd && chown -R esm:esm /esmd + +# copy esmd & deno build +COPY --from=builder /tmp/esm.sh/esmd /bin/esmd +COPY --from=denoland/deno:bin-2.1.4 --chown=esm:esm /deno /esmd/bin/deno # deno desn't provider musl build yet, the hack below makes the gnu build working in alpine # see https://github.com/denoland/deno_docker/blob/main/alpine.dockerfile @@ -23,21 +29,13 @@ COPY --from=gcr.io/distroless/cc --chown=root:root --chmod=755 /lib/ld-linux-* / RUN mkdir /lib64 && ln -s /usr/local/lib/ld-linux-* /lib64/ ENV LD_LIBRARY_PATH="/usr/local/lib" -# don't run as root -RUN addgroup -g 1000 esm && adduser -u 1000 -G esm -D esm -RUN mkdir /esmd && chown -R esm:esm /esmd - -COPY --from=builder /tmp/esm.sh/esmd /bin/esmd -COPY --from=denoland/deno:bin-2.1.4 --chown=esm:esm /deno /esmd/bin/deno - +# server configuration ENV ESM_SERVER_PORT="8080" ENV ESM_SERVER_WORKDIR="/esmd" -# use tini -# see https://github.com/krallin/tini -ENTRYPOINT ["/sbin/tini", "--"] - +# switch to non-root user USER esm -WORKDIR /esmd + EXPOSE 8080 +WORKDIR /esmd CMD ["esmd"] From b4415c511c1f5750c6f20070a4cd44d68e5fa620 Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 08:02:02 +0800 Subject: [PATCH 02/11] Update deploy-ci script --- scripts/deploy-ci.sh | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/scripts/deploy-ci.sh b/scripts/deploy-ci.sh index 51311701..d028a552 100755 --- a/scripts/deploy-ci.sh +++ b/scripts/deploy-ci.sh @@ -1,32 +1,32 @@ #!/bin/bash mkdir -p ~/.ssh -ssh-keyscan $DEPLOY_HOST_NAME >> ~/.ssh/known_hosts echo "${DEPLOY_SSH_PRIVATE_KEY}" >> ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 -echo "Host next.esm.sh" >> ~/.ssh/config +ssh-keyscan $DEPLOY_HOST_NAME >> ~/.ssh/known_hosts +echo "Host d.esm.sh" >> ~/.ssh/config echo " HostName ${DEPLOY_HOST_NAME}" >> ~/.ssh/config echo " Port ${DEPLOY_HOST_PORT}" >> ~/.ssh/config echo " User ${DEPLOY_SSH_USER}" >> ~/.ssh/config echo " IdentityFile ~/.ssh/id_ed25519" >> ~/.ssh/config echo " IdentitiesOnly yes" >> ~/.ssh/config -echo "--- building..." -go build -ldflags="-s -w -X 'github.com/esm-dev/esm.sh/server.VERSION=${VERSION}'" -o esmd $(dirname $0)/../main.go +echo "--- building server..." +go build -ldflags="-s -w -X 'github.com/esm-dev/esm.sh/server.VERSION=${SERVER_VERSION}'" -o esmd $(dirname $0)/../main.go if [ "$?" != "0" ]; then exit 1 fi - -echo "--- uploading..." du -h esmd + +echo "--- uploading server build..." tar -czf esmd.tar.gz esmd -scp esmd.tar.gz next.esm.sh:/tmp/esmd.tar.gz +scp esmd.tar.gz d.esm.sh:/tmp/esmd.tar.gz if [ "$?" != "0" ]; then exit 1 fi -echo "--- installing..." -ssh next.esm.sh << EOF +echo "--- installing server..." +ssh d.esm.sh << EOF gv=\$(git version) if [ "\$?" != "0" ]; then apt update @@ -43,7 +43,7 @@ ssh next.esm.sh << EOF echo "StartLimitIntervalSec=0" >> \$servicefile echo "[Service]" >> \$servicefile echo "Type=simple" >> \$servicefile - echo "ExecStart=/usr/local/bin/esmd" >> \$servicefile + echo "ExecStart=/usr/local/bin/esmd --config=/etc/esmd/config.json" >> \$servicefile echo "USER=\${USER}" >> \$servicefile echo "Restart=always" >> \$servicefile echo "RestartSec=5" >> \$servicefile @@ -57,8 +57,18 @@ ssh next.esm.sh << EOF echo "Stopped esmd.service." fi - mv -f ~/.esmd /tmp/.esmd - nohup rm -rf /tmp/.esmd & + mkdir -p /etc/esmd + rm -f /etc/esmd/config.json + if [ "$SERVER_CONFIG" != "" ]; then + echo "${SERVER_CONFIG}" >> /etc/esmd/config.json + else + echo "{}" >> /etc/esmd/config.json + fi + + if [ "$RESET_ON_DEPLOY" == "yes" ]; then + mv -f ~/.esmd /tmp/.esmd + nohup rm -rf /tmp/.esmd & + fi cd /tmp tar -xzf esmd.tar.gz From 87b6b29deff10ea952a0305fede5ce925db002f7 Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 08:02:20 +0800 Subject: [PATCH 03/11] Add release action yml --- .github/workflows/deploy.yml | 3 +- .github/workflows/docker-push.yml | 40 -------------- .github/workflows/release.yml | 89 +++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 41 deletions(-) delete mode 100644 .github/workflows/docker-push.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0af68ef1..e081f04a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -28,4 +28,5 @@ jobs: DEPLOY_HOST_PORT: ${{ secrets.DEPLOY_HOST_PORT }} DEPLOY_SSH_USER: ${{ secrets.DEPLOY_SSH_USER }} DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} - VERSION: ${{ github.sha }} + SERVER_VERSION: ${{ github.sha }} + RESET_ON_DEPLOY: yes diff --git a/.github/workflows/docker-push.yml b/.github/workflows/docker-push.yml deleted file mode 100644 index 02caf9c9..00000000 --- a/.github/workflows/docker-push.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Docker Push - -on: - push: - tags: - - v* - -jobs: - push: - name: Push docker image to ghcr.io - runs-on: ubuntu-latest - permissions: - packages: write - contents: read - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to GHCR - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v6 - with: - context: . - push: true - platforms: linux/amd64,linux/arm64 - tags: ghcr.io/esm-dev/esm.sh:latest,ghcr.io/esm-dev/esm.sh:v136 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..66cf12d5 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,89 @@ +name: Release + +on: + push: + tags: + - v* + +jobs: + deploy: + name: Deploy server to esm.sh nodes + runs-on: ubuntu-latest + environment: ${{ matrix.environment }} + + strategy: + matrix: + environment: [production-node-1] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: 1.23.x + + - name: Run Deploy Script + run: ./scripts/deploy-ci.sh + env: + GOOS: ${{ secrets.DEPLOY_HOST_OS }} + GOARCH: ${{ secrets.DEPLOY_HOST_ARCH }} + DEPLOY_HOST_NAME: ${{ secrets.DEPLOY_HOST_NAME }} + DEPLOY_HOST_PORT: ${{ secrets.DEPLOY_HOST_PORT }} + DEPLOY_SSH_USER: ${{ secrets.DEPLOY_SSH_USER }} + DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} + SERVER_CONFIG: ${{ github.SERVER_CONFIG }} + SERVER_VERSION: ${{ github.ref_name }} + + push_docker_image: + name: Push docker image to ghcr.io + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GHCR + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + tags: ghcr.io/esm-dev/esm.sh:latest,ghcr.io/esm-dev/esm.sh:${{ github.ref_name }} + build-args: | + SERVER_VERSION=${{ github.ref_name }} + + publish: + name: Publish + runs-on: ubuntu-latest + needs: [deploy, push_docker_image] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Extract Release Note + run: echo "console.log(require('fs').readFileSync('CHANGELOG.md','utf8').split('## ')[1].slice('${{ github.ref_name }}'.length).trim())" | node > release-note.txt + + - name: Publish Release + uses: softprops/action-gh-release@v2 + with: + body_path: release-note.txt From 88f76d7f7438b7eaef9a1fb42bb05edbd357470c Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 08:02:54 +0800 Subject: [PATCH 04/11] Update hosting.md --- HOSTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HOSTING.md b/HOSTING.md index 6e6d3faf..8e104802 100644 --- a/HOSTING.md +++ b/HOSTING.md @@ -98,6 +98,6 @@ You can also create your own Dockerfile based on `ghcr.io/esm-dev/esm.sh`: ```dockerfile FROM ghcr.io/esm-dev/esm.sh:latest -ADD ./config.json /etc/esmd/config.json +ADD --chown=esm:esm ./config.json /etc/esmd/config.json CMD ["esmd", "--config", "/etc/esmd/config.json"] ``` From b07e58e53d4522aa4454c375d26692cebee3a2e5 Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 10:00:10 +0800 Subject: [PATCH 05/11] Add v136 changes --- CHANGELOG.md | 123 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aedc7ebd..4926eb67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,126 @@ # Changelog -## Unreleased +## v136 + +* Add two builtin registries: + * [jsr](https://jsr.io) - The open-source package registry for modern JavaScript and TypeScript, created by the Deno team. ([32cd2bd](https://github.com/esm-dev/esm.sh/commit/32cd2bd931f33118cbc96ee89583f20718c58fbf)) + ```js + // example + import { encodeBase64 } from "https://esm.sh/jsr/@std/encoding@1.0.0/base64"; + import { Hono } from "https://esm.sh/jsr/@hono/hono@4"; + ``` + * [pkg.pr.new](https://pkg.pr.new) - Continuous (Preview) Releases for your libraries, created by [StackBlitz Labs](https://github.com/stackblitz-labs) ([#904](https://github.com/esm-dev/esm.sh/issues/904), [#913](https://github.com/esm-dev/esm.sh/issues/913)) + ```js + // Examples + import { Bench } from "https://esm.sh/pr/tinylibs/tinybench/tinybench@a832a55"; + import { Bench } from "https://esm.sh/pr/tinybench@a832a55"; // --compact + ``` + +* Respect sematic versioning for dependency resolving ([#875](https://github.com/esm-dev/esm.sh/issues/875)) + + Prior to v136, dependency resolution used fixed versions, which could lead to duplication issues when a package was updated. Now, we adhere to semantic versioning for dependencies. + + ```js + // before + "react-dom@19.0.0" import "/react@18.3.1/es2022/react.mjs"; + // after + "react-dom@19.0.0" import "/react@^18.3.1?target=es2022"; + ``` + +* Add built-in npm package manager ([#948](https://github.com/esm-dev/esm.sh/issues/948)) + + Implement a built-in npm package manager in Go to replace pnpm. This change reduces the CI test time from 12:15 to 4:30 (**~2.7x faster**) and eliminates the need for `nodejs` and `pnpm` dependencies. + +* Splitting modules by analyzing dependency tree when building ([#959](https://github.com/esm-dev/esm.sh/issues/959)) + + To improve build performance and reduce network requests, esm.sh bundles sub-modules of a package by default. However, this can lead to duplicate code in the build. In v136, the server will split the modules by analyzing the dependency tree during the build process if the package's `exports` field is defined. + +* Use [unenv](https://github.com/unjs/unenv) as the node runtime compatibility layer ([#914](https://github.com/esm-dev/esm.sh/issues/914)) + + The `unenv` project is created [@pi0](https://github.com/pi0), which also used by cloudflare workers: [blog](https://blog.cloudflare.com/more-npm-packages-on-cloudflare-workers-combining-polyfills-and-native-code/) + + ```js + // example + import { readFile } from "https://esm.sh/unenv/fs"; + import { createServer } from "https://esm.sh/unenv/http"; + ``` + +* Add npm-replacements that follows [e18e](https://e18e.dev)'s [module-replacements](https://github.com/es-tooling/module-replacements). ([#914](https://github.com/esm-dev/esm.sh/issues/914)) + + ```js + // example + import "object-assign"; // replaced with "Object.assign" + ``` + +* Remove the build version prefix of esm.sh in the module path + + The build version prefix of esm.sh was introduced to avoid potential breaking changes caused by updates to the esm.sh server. However, it can lead to duplication issues when updating the server. In v136, we have removed the build version prefix from the module path, and the `?pin` query will be ignored. Paths with the build version prefix will continue to work as before, but the new default will be paths without the build version prefix. + + ```js + // before + "react@19.0.0" -> "https://esm.sh/v135/react@19.0.0/es2022/react.mjs"; + // after + "react@19.0.0" -> "https://esm.sh/react@19.0.0/es2022/react.mjs"; + ``` + +* Deprecate the `build` API + ```js + import { build } from "https://esm.sh/build"; + build() // throws Error: The build API has been deprecated. + ``` + +* Deprecate the Deno CLI script + + Deno now includes its own built-in package manager, which can be used to manage `jsr:` nad `npm:` imports in your deno applications. So we decided to deprecate the Deno CLI script. + + ```bash + # use + deno add npm:pract jsr:@std/encoding + Add npm:preact@10.25.4 + Add jsr:@std/encoding@1.0.6 + + # do not use + deno run -A -r https://esm.sh init + error: The deno CLI has been deprecated. + ``` + +* Add `npmScopedRegistries` config + + The `npmScopedRegistries` configuration enables you to define the registry, token, user, and password for scoped npm packages. This allows you to import scoped packages using URLs like `https://your-esm-server.com/@scope_name/pkg@version`. + + ```json + { + "npmScopedRegistries": { + "@scope_name": { + "registry": "https://your-registry.com/", + "token": "xxxxxx", + "user": "", + "password": "" + } + } + } + ``` + +* Experimental Features: + * Build `.vue` and `.svelte` files on the fly ([#906](https://github.com/esm-dev/esm.sh/issues/906)) + ```js + import "https://esm.sh/gh/phosphor-icons/vue@v2.2.0/src/icons/PhAirplay.vue?deps=vue@3.5.8" + ``` + * https://esm.sh/x - ts/jsx/vue/svelte just works™️ in browser. ([#886](https://github.com/esm-dev/esm.sh/issues/886)) + +* Other Changes: + * Upgrade esbuild to **0.24.2** + * Use native [cjs-module-lexer@v1.0.7](https://github.com/esm-dev/cjs-module-lexer/releases/tag/v1.0.7) + * Use target `es2022` for browsers by default ([#903](https://github.com/esm-dev/esm.sh/issues/903)) + * Replace `window` with `globalThis` to make Deno 2 happy ([#964](https://github.com/esm-dev/esm.sh/issues/964)) + * Use `.mjs` extenstion for sub-module build (#917) + * dts-transformer: support `.d` extension + * config: Add `corsAllowOrigins` config + * config: Add `customLandingPage` config (#928) + * config: Add `npmQueryCacheTTL` config (#921) + * config: Add npmQueryCacheTTL config (#921) + * config: Support **S3-compatible** storage (#886) -- Use semver versioning for depdency resolving -- Introduce `esm.sh/run` v2 ## v135 From d9f1a7aa81e95145bd7b4b7b7ce3e97049e0236a Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 10:13:14 +0800 Subject: [PATCH 06/11] Update v136 change note --- CHANGELOG.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4926eb67..020d2d54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,21 +35,22 @@ To improve build performance and reduce network requests, esm.sh bundles sub-modules of a package by default. However, this can lead to duplicate code in the build. In v136, the server will split the modules by analyzing the dependency tree during the build process if the package's `exports` field is defined. -* Use [unenv](https://github.com/unjs/unenv) as the node runtime compatibility layer ([#914](https://github.com/esm-dev/esm.sh/issues/914)) +* Use [@pi0](https://github.com/pi0)'s [unenv](https://github.com/unjs/unenv) as the node runtime compatibility layer ([#914](https://github.com/esm-dev/esm.sh/issues/914)) - The `unenv` project is created [@pi0](https://github.com/pi0), which also used by cloudflare workers: [blog](https://blog.cloudflare.com/more-npm-packages-on-cloudflare-workers-combining-polyfills-and-native-code/) + unenv provides a collection of Node.js and Web polyfills and mocking utilities with configurable presets for converting JavaScript code and libraries to be platform and runtime agnostic, working in any environment including Browsers, Workers, Node.js, Cloudflare Workers, Deno. unenv is also used by CloudFlare Workers: [blog](https://blog.cloudflare.com/more-npm-packages-on-cloudflare-workers-combining-polyfills-and-native-code/). + + You can also access these `unenv` node runtime modules directly via `/node/[node-builtin-module-name].mjs` path, for example: ```js - // example - import { readFile } from "https://esm.sh/unenv/fs"; - import { createServer } from "https://esm.sh/unenv/http"; + import * from "https://esm.sh/node/fs.mjs"; ``` -* Add npm-replacements that follows [e18e](https://e18e.dev)'s [module-replacements](https://github.com/es-tooling/module-replacements). ([#914](https://github.com/esm-dev/esm.sh/issues/914)) +* Add [npm-replacements](./server/npm_replacements/src/) that follows [e18e](https://e18e.dev)'s [module-replacements](https://github.com/es-tooling/module-replacements). ([#914](https://github.com/esm-dev/esm.sh/issues/914)) + + The `npm-replacements` package replaces certain polyfill packages on NPM with native modern APIs during the build process. For example, the `object-assign` package is replaced with `Object.assign`: ```js - // example - import "object-assign"; // replaced with "Object.assign" + import assign from "object-assign"; // replaced with "const assign = Object.assign" ``` * Remove the build version prefix of esm.sh in the module path From 23d58549d9fb0300339f87270d107140d2b6e98b Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 10:49:15 +0800 Subject: [PATCH 07/11] Update release action yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 66cf12d5..d70850cc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,7 +33,7 @@ jobs: DEPLOY_HOST_PORT: ${{ secrets.DEPLOY_HOST_PORT }} DEPLOY_SSH_USER: ${{ secrets.DEPLOY_SSH_USER }} DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} - SERVER_CONFIG: ${{ github.SERVER_CONFIG }} + SERVER_CONFIG: ${{ secrets.SERVER_CONFIG }} SERVER_VERSION: ${{ github.ref_name }} push_docker_image: From be86776ffe9dd2a243fe934f7a778274e9b5f928 Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 10:49:20 +0800 Subject: [PATCH 08/11] format --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 020d2d54..2c5462e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,7 @@ * Use [@pi0](https://github.com/pi0)'s [unenv](https://github.com/unjs/unenv) as the node runtime compatibility layer ([#914](https://github.com/esm-dev/esm.sh/issues/914)) - unenv provides a collection of Node.js and Web polyfills and mocking utilities with configurable presets for converting JavaScript code and libraries to be platform and runtime agnostic, working in any environment including Browsers, Workers, Node.js, Cloudflare Workers, Deno. unenv is also used by CloudFlare Workers: [blog](https://blog.cloudflare.com/more-npm-packages-on-cloudflare-workers-combining-polyfills-and-native-code/). + unenv provides a collection of Node.js and Web polyfills and mocking utilities with configurable presets for converting JavaScript code and libraries to be platform and runtime agnostic, working in any environment including Browsers, Workers, Node.js, Cloudflare Workers, Deno. unenv is also used by CloudFlare Workers: [blog](https://blog.cloudflare.com/more-npm-packages-on-cloudflare-workers-combining-polyfills-and-native-code/). You can also access these `unenv` node runtime modules directly via `/node/[node-builtin-module-name].mjs` path, for example: From 20c156d4283462e4d63be6fbb5430ad9e127ca60 Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 19:01:14 +0800 Subject: [PATCH 09/11] Update deploy action yml --- .github/workflows/deploy.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e081f04a..8a1313dd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,7 +8,7 @@ jobs: deploy: name: Deploy main branch to next.esm.sh runs-on: ubuntu-latest - environment: next + environment: next.esm.sh steps: - name: Checkout diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d70850cc..b420e86a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - environment: [production-node-1] + environment: [d1.esm.sh] steps: - name: Checkout From 6c1d7880cc252a531d432ec1f641cfbac6bdd97d Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 23:40:40 +0800 Subject: [PATCH 10/11] Fix unocss build cache --- cli/serve.go | 104 ++++++++++++++++++++++++++++----------------------- cli/utils.go | 2 +- 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/cli/serve.go b/cli/serve.go index 09851de1..21d49632 100644 --- a/cli/serve.go +++ b/cli/serve.go @@ -14,6 +14,7 @@ import ( "net/url" "os" "path/filepath" + "sort" "strings" "sync" "time" @@ -273,40 +274,44 @@ func (d *DevServer) ServeHtml(w http.ResponseWriter, r *http.Request, pathname s w.Write([]byte(">")) continue } - // replace `` - // with `` - if (strings.HasPrefix(srcAttr, "http://") || strings.HasPrefix(srcAttr, "https://")) && strings.HasSuffix(srcAttr, "/x") && mainAttr != "" { - w.Write([]byte("` + // with `` + if mainAttr != "" && (strings.HasPrefix(srcAttr, "https://") || strings.HasPrefix(srcAttr, "http://")) { + if srcUrl, parseErr := url.Parse(srcAttr); parseErr == nil && srcUrl.Path == "/x" { + w.Write([]byte("")) + continue } - w.Write([]byte(">")) - continue } // replace `` // with `` - if (strings.HasPrefix(srcAttr, "http://") || strings.HasPrefix(srcAttr, "https://")) && strings.HasSuffix(srcAttr, "/uno") { - unocss = "/@uno.css?ctx=" + btoaUrl(pathname) - w.Write([]byte(fmt.Sprintf(``, unocss))) - tok := tokenizer.Next() - if tok == html.TextToken { - tokenizer.Next() - } - if tok == html.ErrorToken { - break + if strings.HasPrefix(srcAttr, "http://") || strings.HasPrefix(srcAttr, "https://") { + if srcUrl, parseErr := url.Parse(srcAttr); parseErr == nil && srcUrl.Path == "/uno" { + unocss = "/@uno.css?ctx=" + btoaUrl(pathname) + w.Write([]byte(fmt.Sprintf(``, unocss))) + tok := tokenizer.Next() + if tok == html.TextToken { + tokenizer.Next() + } + if tok == html.ErrorToken { + break + } + continue } - continue } case "style": // strip `` @@ -551,7 +556,7 @@ func (d *DevServer) ServeUnoCSS(w http.ResponseWriter, r *http.Request) { defer imHtmlFile.Close() configCSS := "" configFilename := "" - content := []string{} + contents := [][]byte{} jsEntries := map[string]struct{}{} importMap := common.ImportMap{} tokenizer := html.NewTokenizer(imHtmlFile) @@ -604,20 +609,20 @@ func (d *DevServer) ServeUnoCSS(w http.ResponseWriter, r *http.Request) { } else if srcAttr == "" { // inline script content tokenizer.Next() - content = append(content, string(tokenizer.Text())) + contents = append(contents, tokenizer.Text()) } else { if mainAttr != "" && isHttpSepcifier(srcAttr) { - if !isHttpSepcifier(mainAttr) && endsWith(mainAttr, supportedModuleExts...) { + if !isHttpSepcifier(mainAttr) && endsWith(mainAttr, moduleExts...) { jsEntries[mainAttr] = struct{}{} } - } else if !isHttpSepcifier(srcAttr) && endsWith(srcAttr, supportedModuleExts...) { + } else if !isHttpSepcifier(srcAttr) && endsWith(srcAttr, moduleExts...) { jsEntries[srcAttr] = struct{}{} } } case "link", "meta", "title", "base", "head", "noscript", "slot", "template", "option": // ignore default: - content = append(content, string(tokenizer.Raw())) + contents = append(contents, tokenizer.Raw()) } } } @@ -636,21 +641,28 @@ func (d *DevServer) ServeUnoCSS(w http.ResponseWriter, r *http.Request) { configCSS = string(data) } } - contentFiles := map[string]struct{}{} + tree := map[string][]byte{} for entry := range jsEntries { - tree, err := d.analyzeDependencyTree(filepath.Join(filepath.Dir(imHtmlFilename), entry), importMap) + t, err := d.analyzeDependencyTree(filepath.Join(filepath.Dir(imHtmlFilename), entry), importMap) if err == nil { - for filename, code := range tree { - if _, ok := contentFiles[filename]; !ok { - contentFiles[filename] = struct{}{} - content = append(content, string(code)) - } + for filename, code := range t { + tree[filename] = code } } } sha := xxhash.New() sha.Write([]byte(configCSS)) - for _, s := range content { + keys := make([]string, 0, len(tree)) + for k := range tree { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + code := tree[k] + contents = append(contents, code) + sha.Write(code) + } + for _, s := range contents { sha.Write([]byte(s)) } etag := fmt.Sprintf("w\"%x\"", sha.Sum(nil)) @@ -687,7 +699,7 @@ func (d *DevServer) ServeUnoCSS(w http.ResponseWriter, r *http.Request) { "css": configCSS, } } - _, css, err := loader.Load("unocss", []any{config, strings.Join(content, "\n")}) + _, css, err := loader.Load("unocss", []any{config, string(bytes.Join(contents, []byte{'\n'}))}) if err != nil { fmt.Println(err) http.Error(w, "Internal Server Error", 500) @@ -782,24 +794,24 @@ func (d *DevServer) analyzeDependencyTree(entry string, importMap common.ImportM Format: esbuild.FormatESModule, Platform: esbuild.PlatformBrowser, JSX: esbuild.JSXPreserve, - Bundle: true, MinifyWhitespace: true, - Outdir: "/esbuild", + Bundle: true, Write: false, + Outdir: "/esbuild", Plugins: []esbuild.Plugin{ { Name: "loader", Setup: func(build esbuild.PluginBuild) { build.OnResolve(esbuild.OnResolveOptions{Filter: ".*"}, func(args esbuild.OnResolveArgs) (esbuild.OnResolveResult, error) { - path, resolved := importMap.Resolve(args.Path) + path, _ := importMap.Resolve(args.Path) if isHttpSepcifier(path) || (!isRelPathSpecifier(path) && !isAbsPathSpecifier(path)) { return esbuild.OnResolveResult{Path: path, External: true}, nil } - if resolved { - if endsWith(path, supportedModuleExts...) { - return esbuild.OnResolveResult{Path: filepath.Join(d.rootDir, path), Namespace: "module", PluginData: path}, nil + if endsWith(path, moduleExts...) { + if isRelPathSpecifier(path) { + path = filepath.Join(filepath.Dir(args.Importer), path) } - return esbuild.OnResolveResult{Path: filepath.Join(d.rootDir, path)}, nil + return esbuild.OnResolveResult{Path: path, Namespace: "module", PluginData: path}, nil } return esbuild.OnResolveResult{}, nil }) diff --git a/cli/utils.go b/cli/utils.go index be8d1087..23716994 100644 --- a/cli/utils.go +++ b/cli/utils.go @@ -10,7 +10,7 @@ import ( ) var ( - supportedModuleExts = []string{".js", ".mjs", ".jsx", ".ts", ".mts", ".tsx", ".svelte", ".vue"} + moduleExts = []string{".js", ".mjs", ".jsx", ".ts", ".mts", ".tsx", ".svelte", ".vue"} ) // termRaw implements the github.com/ije/gox/term.Raw interface. From 1961055d30d4a28a56365615bf463b7631865d53 Mon Sep 17 00:00:00 2001 From: Je Xia Date: Mon, 30 Dec 2024 23:41:02 +0800 Subject: [PATCH 11/11] Update demo apps --- cli/cmd/demo/react/index.html | 6 +++--- cli/cmd/demo/svelte/index.html | 2 +- cli/cmd/demo/with-markdown/react/index.html | 4 ++-- cli/cmd/demo/with-markdown/svelte/index.html | 2 +- cli/cmd/demo/with-unocss/react/index.html | 4 ++-- cli/cmd/demo/with-unocss/svelte/index.html | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cli/cmd/demo/react/index.html b/cli/cmd/demo/react/index.html index 6095204f..b31ee87a 100644 --- a/cli/cmd/demo/react/index.html +++ b/cli/cmd/demo/react/index.html @@ -9,14 +9,14 @@
- + diff --git a/cli/cmd/demo/svelte/index.html b/cli/cmd/demo/svelte/index.html index 368155ab..c7316217 100644 --- a/cli/cmd/demo/svelte/index.html +++ b/cli/cmd/demo/svelte/index.html @@ -9,7 +9,7 @@ diff --git a/cli/cmd/demo/with-markdown/react/index.html b/cli/cmd/demo/with-markdown/react/index.html index 3b8add2d..1ca6f3be 100644 --- a/cli/cmd/demo/with-markdown/react/index.html +++ b/cli/cmd/demo/with-markdown/react/index.html @@ -9,8 +9,8 @@ diff --git a/cli/cmd/demo/with-markdown/svelte/index.html b/cli/cmd/demo/with-markdown/svelte/index.html index 368155ab..c7316217 100644 --- a/cli/cmd/demo/with-markdown/svelte/index.html +++ b/cli/cmd/demo/with-markdown/svelte/index.html @@ -9,7 +9,7 @@ diff --git a/cli/cmd/demo/with-unocss/react/index.html b/cli/cmd/demo/with-unocss/react/index.html index 4bd20f30..71e2f04f 100644 --- a/cli/cmd/demo/with-unocss/react/index.html +++ b/cli/cmd/demo/with-unocss/react/index.html @@ -9,8 +9,8 @@ diff --git a/cli/cmd/demo/with-unocss/svelte/index.html b/cli/cmd/demo/with-unocss/svelte/index.html index 6bd1d2e4..8d594634 100644 --- a/cli/cmd/demo/with-unocss/svelte/index.html +++ b/cli/cmd/demo/with-unocss/svelte/index.html @@ -9,7 +9,7 @@