npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

unplugin-aliyun-oss

v1.1.1

Published

Aliyun OSS plugin powered by unplugin.

Readme

unplugin-aliyun-oss

npm version npm downloads Unit Test Node.js License

Upload generated build assets to Aliyun OSS after bundling. Powered by unplugin, with adapters for Vite, Webpack, Rollup, Rolldown, esbuild, Rspack, and Farm.

Features

  • Runs after the bundler has written build assets.
  • Supports dry runs with test: true, so OSS credentials are not required while checking file discovery and object keys.
  • Converts local output paths into OSS object keys with buildRoot, dist, and optional setOssPath control.
  • Can skip existing objects when overwrite: false is enabled.
  • Can remove uploaded local files and prune empty directories after upload.
  • Can publish version metadata through a user-provided setVersion callback.

Support

The plugin runtime supports Node.js >=20.19.0. This matches the minimum Node version required by the current unplugin and builder adapter toolchain.

| Builder | Import | Notes | | -------- | ------------------------------ | --------------------------------------------------------------------------------------- | | Vite | unplugin-aliyun-oss/vite | Vite ^4 to ^8; output root is inferred from build.outDir. | | Webpack | unplugin-aliyun-oss/webpack | Webpack 4 and 5; output root is inferred from output.path. | | Rollup | unplugin-aliyun-oss/rollup | Rollup ^3 and ^4; output root is inferred from output.dir or output.file. | | Rolldown | unplugin-aliyun-oss/rolldown | Rolldown ^1; uses the Rollup-compatible output options. | | esbuild | unplugin-aliyun-oss/esbuild | esbuild >=0.18; output root is inferred from outdir or outfile. | | Rspack | unplugin-aliyun-oss/rspack | Rspack ^1 and ^2; output root is inferred from output.path. | | Farm | unplugin-aliyun-oss/farm | Uses the unplugin Farm adapter. Set buildRoot explicitly for predictable object keys. |

Installation

npm i -D unplugin-aliyun-oss
pnpm add -D unplugin-aliyun-oss
yarn add -D unplugin-aliyun-oss
bun add -D unplugin-aliyun-oss

Credentials

Keep OSS credentials outside source control and read them from environment variables:

OSS_REGION=oss-cn-hangzhou
OSS_BUCKET=my-bucket
OSS_ACCESS_KEY_ID=your-access-key-id
OSS_ACCESS_KEY_SECRET=your-access-key-secret

region, bucket, accessKeyId, and accessKeySecret are required unless test: true is enabled.

Quick Start

// vite.config.ts
import { defineConfig } from "vite";
import Oss from "unplugin-aliyun-oss/vite";

export default defineConfig({
  plugins: [
    Oss({
      from: "dist/**/*",
      dist: "/static",
      region: process.env.OSS_REGION!,
      accessKeyId: process.env.OSS_ACCESS_KEY_ID!,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET!,
      bucket: process.env.OSS_BUCKET!,
    }),
  ],
});

With the config above, dist/assets/app.js is uploaded to /static/assets/app.js.

Framework Usage

// vite.config.ts
import { defineConfig } from "vite";
import Oss from "unplugin-aliyun-oss/vite";

export default defineConfig({
  plugins: [
    Oss({
      from: "dist/**/*",
      dist: "/static",
      region: process.env.OSS_REGION!,
      accessKeyId: process.env.OSS_ACCESS_KEY_ID!,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET!,
      bucket: process.env.OSS_BUCKET!,
    }),
  ],
});

// webpack.config.js
import path from "node:path";
import Oss from "unplugin-aliyun-oss/webpack";

export default {
  output: {
    path: path.resolve("dist"),
  },
  plugins: [
    Oss({
      from: "dist/**/*",
      dist: "/static",
      region: process.env.OSS_REGION,
      accessKeyId: process.env.OSS_ACCESS_KEY_ID,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
      bucket: process.env.OSS_BUCKET,
      quitWpOnError: true,
    }),
  ],
};

// rollup.config.ts
import Oss from "unplugin-aliyun-oss/rollup";

export default {
  input: "src/index.ts",
  output: {
    dir: "dist",
    format: "esm",
  },
  plugins: [
    Oss({
      from: "dist/**/*",
      dist: "/static",
      region: process.env.OSS_REGION,
      accessKeyId: process.env.OSS_ACCESS_KEY_ID,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
      bucket: process.env.OSS_BUCKET,
    }),
  ],
};

// rolldown.config.ts
import Oss from "unplugin-aliyun-oss/rolldown";

export default {
  input: "src/index.ts",
  output: {
    dir: "dist",
    format: "esm",
  },
  plugins: [
    Oss({
      from: "dist/**/*",
      dist: "/static",
      region: process.env.OSS_REGION,
      accessKeyId: process.env.OSS_ACCESS_KEY_ID,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
      bucket: process.env.OSS_BUCKET,
    }),
  ],
};

// build.ts
import { build } from "esbuild";
import Oss from "unplugin-aliyun-oss/esbuild";

await build({
  entryPoints: ["src/index.ts"],
  bundle: true,
  outdir: "dist",
  plugins: [
    Oss({
      from: "dist/**/*",
      dist: "/static",
      region: process.env.OSS_REGION,
      accessKeyId: process.env.OSS_ACCESS_KEY_ID,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
      bucket: process.env.OSS_BUCKET,
    }),
  ],
});

// rspack.config.js
import path from "node:path";
import Oss from "unplugin-aliyun-oss/rspack";

export default {
  output: {
    path: path.resolve("dist"),
  },
  plugins: [
    Oss({
      from: "dist/**/*",
      dist: "/static",
      region: process.env.OSS_REGION,
      accessKeyId: process.env.OSS_ACCESS_KEY_ID,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
      bucket: process.env.OSS_BUCKET,
      quitWpOnError: true,
    }),
  ],
};

// farm.config.ts
import Oss from "unplugin-aliyun-oss/farm";

export default {
  plugins: [
    Oss({
      from: "dist/**/*",
      buildRoot: "dist",
      dist: "/static",
      region: process.env.OSS_REGION,
      accessKeyId: process.env.OSS_ACCESS_KEY_ID,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
      bucket: process.env.OSS_BUCKET,
    }),
  ],
};

Common Patterns

Dry run

Use test: true to verify matched files and OSS keys without creating an Aliyun OSS client:

Oss({
  from: "dist/**/*",
  dist: "/static",
  test: true,
});

Custom object keys

Use setOssPath when the OSS key should not mirror the build output directory:

import path from "node:path";

Oss({
  from: "dist/**/*",
  dist: "/static",
  region: process.env.OSS_REGION,
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  bucket: process.env.OSS_BUCKET,
  setOssPath(filePath) {
    return `/assets/${path.basename(filePath)}`;
  },
});

Use from to exclude files from the upload set. In the current version, setOssPath should return a concrete string for every matched file.

Skip existing objects

Set overwrite: false to check whether an object already exists before upload. Existing objects are skipped, and upload requests include x-oss-forbid-overwrite.

Oss({
  from: "dist/**/*",
  overwrite: false,
  region: process.env.OSS_REGION,
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  bucket: process.env.OSS_BUCKET,
});

Delete local files after upload

Oss({
  from: "dist/**/*",
  deleteOrigin: true,
  deleteEmptyDir: true,
  region: process.env.OSS_REGION,
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  bucket: process.env.OSS_BUCKET,
});

Publish version metadata

setVersion is called after a non-test upload pass finishes when version is not empty:

Oss({
  from: "dist/**/*",
  version: process.env.APP_VERSION ?? "",
  region: process.env.OSS_REGION,
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  bucket: process.env.OSS_BUCKET,
  async setVersion({ version }) {
    await fetch("https://example.com/assets-version", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ version }),
    });
  },
});

Object Key Rules

  1. from selects local files with glob patterns. Directories are ignored before upload.
  2. If setOssPath is provided, its returned string is used as the per-file object path.
  3. Otherwise, the object path is relative to buildRoot when you provide it.
  4. If buildRoot is not provided, most adapters infer the bundler output root.
  5. dist is prefixed to the object path.

Examples:

| Local file | Config | OSS key | | -------------------- | ----------------------------------------------------------- | ----------------------- | | dist/index.html | from: "dist/**/*", buildRoot: "dist", dist: "/static" | /static/index.html | | dist/assets/app.js | from: "dist/**/*", buildRoot: "dist", dist: "/static" | /static/assets/app.js | | dist/assets/app.js | dist: "/cdn", setOssPath: () => "/app.js" | /cdn/app.js |

Options

interface Options {
  region?: string;
  accessKeyId?: string;
  accessKeySecret?: string;
  bucket?: string;
  from: string | string[];
  test?: boolean;
  verbose?: boolean;
  dist?: string;
  buildRoot?: string;
  deleteOrigin?: boolean;
  deleteEmptyDir?: boolean;
  timeout?: number;
  setOssPath?: (filePath: string) => string | false | null | undefined;
  overwrite?: boolean;
  quitWpOnError?: boolean;
  version?: string;
  setVersion?: (data: { version: string }) => void | Promise<void>;
}

| Option | Required | Default | Description | | ----------------- | ------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | from | Yes | - | Files to upload. Supports one glob or an array of globs, such as dist/**/*. Directories matched by the glob are ignored. | | region | Yes, unless test: true | - | Aliyun OSS region, for example oss-cn-hangzhou. | | accessKeyId | Yes, unless test: true | - | Aliyun access key id. | | accessKeySecret | Yes, unless test: true | - | Aliyun access key secret. | | bucket | Yes, unless test: true | - | Aliyun OSS bucket name. | | test | No | false | Dry run mode. Files are discovered and target paths are printed without creating an OSS client. | | verbose | No | true | Prints grouped logs with source file, OSS key, object status, upload action, result URL, and failures. | | dist | No | "" | OSS object key prefix. | | buildRoot | No | "." | Local root used to make object keys relative. Most adapters infer the bundler output path when buildRoot is not provided. | | deleteOrigin | No | false | Deletes local files after successful upload. | | deleteEmptyDir | No | false | Removes empty parent directories after deleting uploaded files. | | timeout | No | 60000 | OSS request timeout in milliseconds. | | setOssPath | No | - | Overrides the generated OSS object key for each matched file. Return a string for every matched file; use from to filter files out of the upload set. | | overwrite | No | true | Overwrites existing OSS objects by default. Set overwrite: false to skip existing objects and send x-oss-forbid-overwrite. | | quitWpOnError | No | false | Makes Webpack and Rspack builds fail when an upload fails. Other adapters collect the failure and continue the upload pass. | | version | No | "" | Version value passed to setVersion. | | setVersion | No | - | Callback used to publish version metadata after a non-test upload pass finishes and version is not empty. Callback errors are logged. |

Troubleshooting

| Symptom | What to check | | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | No files are uploaded | Check that from points at files that exist after the build has finished. Use test: true to print matched files without OSS writes. | | OSS keys include too much local path | Set buildRoot to the build output directory, for example buildRoot: "dist". | | Farm uploads use unexpected keys | Set buildRoot explicitly because Farm does not provide an inferred output path here. | | Webpack or Rspack succeeds even when upload fails | Set quitWpOnError: true. | | Existing OSS objects should not be replaced | Set overwrite: false. |

Development

This repository uses Node.js 20.19.0 for local development. Use the version declared in .node-version.

pnpm install
pnpm run typecheck
pnpm run build
pnpm run test

Focused checks:

pnpm run test -- tests/uploader.test.ts
pnpm run test -- tests/builders.test.ts

Agent Usage

Copy this prompt into your coding agent when you want it to add Aliyun OSS uploads to an existing project:

Add `unplugin-aliyun-oss` to this project and wire it into the current bundler.

Requirements:

1. Detect the package manager and install `unplugin-aliyun-oss` as a dev
   dependency.
2. Detect the active bundler and import the matching adapter:
   - Vite: `unplugin-aliyun-oss/vite`
   - Webpack: `unplugin-aliyun-oss/webpack`
   - Rollup: `unplugin-aliyun-oss/rollup`
   - Rolldown: `unplugin-aliyun-oss/rolldown`
   - esbuild: `unplugin-aliyun-oss/esbuild`
   - Rspack: `unplugin-aliyun-oss/rspack`
   - Farm: `unplugin-aliyun-oss/farm`
3. Read OSS settings from environment variables. Do not hard-code secrets:
   - `OSS_REGION`
   - `OSS_BUCKET`
   - `OSS_ACCESS_KEY_ID`
   - `OSS_ACCESS_KEY_SECRET`
4. Configure the plugin to upload the production build output. Use the actual
   output directory from the bundler config, usually `dist/**/*`.
5. Set `dist` to the OSS object prefix I want assets published under. If I have
   not specified one, ask before choosing it.
6. For Farm, or whenever the output root cannot be inferred safely, set
   `buildRoot` explicitly to the build output directory.
7. Keep local validation non-destructive. Use `test: true` first unless I
   explicitly provide a real OSS test bucket and ask for live upload
   verification.
8. After editing config, run the project typecheck/build command that already
   exists in `package.json`. Do not invent unrelated tooling.
9. Report the changed files, the selected adapter, the final OSS key mapping for
   one example file, and the verification command output.

Example target config the agent can adapt:

import Oss from "unplugin-aliyun-oss/vite";

Oss({
  from: "dist/**/*",
  dist: "/static",
  region: process.env.OSS_REGION!,
  bucket: process.env.OSS_BUCKET!,
  accessKeyId: process.env.OSS_ACCESS_KEY_ID!,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET!,
});

License

MIT License © 2025-PRESENT Drswith