{"id":15959173,"url":"https://github.com/nickstenning/s3-npm-publish","last_synced_at":"2025-07-24T19:11:47.881Z","repository":{"id":66096429,"uuid":"83152678","full_name":"nickstenning/s3-npm-publish","owner":"nickstenning","description":"Publish NPM packages to S3 with correct caching headers and sensible update behaviour.","archived":false,"fork":false,"pushed_at":"2017-02-27T12:05:52.000Z","size":24,"stargazers_count":5,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-02T10:43:32.876Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nickstenning.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-25T18:23:43.000Z","updated_at":"2023-09-01T14:58:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"2f31a550-775a-49f1-9ba1-8238c943f281","html_url":"https://github.com/nickstenning/s3-npm-publish","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nickstenning/s3-npm-publish","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickstenning%2Fs3-npm-publish","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickstenning%2Fs3-npm-publish/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickstenning%2Fs3-npm-publish/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickstenning%2Fs3-npm-publish/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nickstenning","download_url":"https://codeload.github.com/nickstenning/s3-npm-publish/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickstenning%2Fs3-npm-publish/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266890394,"owners_count":24001541,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-24T02:00:09.469Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-07T14:40:34.494Z","updated_at":"2025-07-24T19:11:47.860Z","avatar_url":"https://github.com/nickstenning.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"s3-npm-publish\n==============\n\nThis is a tool to publish an [NPM][1] package to an [Amazon S3][2] bucket using\nsensible defaults. It assumes that:\n\n- you are releasing prebuilt assets in your NPM package\n- you wish to expose the entirety of your package in the S3 bucket for each\n  released version\n\nIt will be most useful only if you also:\n\n- define a `main` entrypoint in your package's `package.json`\n- ensure your entrypoint file is capable of loading the remainder of your\n  packages assets as necessary from the bucket HTTP URL (or CDN URL)\n\nTo be explicit, this means that you will probably need your entrypoint script\nto:\n\n1. Know what version of your package it is from.\n2. Know the URL at which your bucket can be accessed over HTTP.\n3. Manage the loading of the rest of your application using 1, 2, and the URL\n   conventions described below.\n\n[1]: https://www.npmjs.com/\n[2]: https://aws.amazon.com/documentation/s3/\n\nWhy?\n----\n\nWhy would you use this? Because:\n\n1. You publish a JavaScript application that you want developers to be able to\n   include on their site using a single tag such as:\n   `\u003cscript src=\"https://cdn.mypackage.com/mypackage\"\u003e\u003c/script\u003e`\n2. You want to take advantage of HTTP/2 request multiplexing to load the various\n   assets that make up your application (i.e. you don't want to have to bundle\n   your entire application into a single file).\n3. You want to be certain that when you release a new version of the package,\n   that release is observed as \"atomic\" by your users. There should be no\n   possibility of a user's browser loading half of the assets from the new\n   version and half from the old version.\n4. You want to make best possible use of CDN and browser caches when delivering\n   your application to users.\n\nThis tool enables a release process that satisfies all of the above by releasing\nthe majority of your package to versioned URLs with caching headers that\nindicate the content is immutable.\n\nEfficient releasing of new versions is made possible by aliasing a package\n\"entrypoint\" script with a short cache TTL. This entrypoint script is\nresponsible for loading the rest of your application.\n\nUsage\n-----\n\n    docker run --rm \\\n      -e AWS_ACCESS_KEY_ID=... \\\n      -e AWS_SECRET_ACCESS_KEY=... \\\n      nickstenning/s3-npm-publish \u003cpkgname\u003e \u003cs3path\u003e\n\nFor example, if you were releasing the `mypkg` package:\n\n    docker run --rm \\\n      -e AWS_ACCESS_KEY_ID=... \\\n      -e AWS_SECRET_ACCESS_KEY=... \\\n      nickstenning/s3-npm-publish mypkg s3://cdn.mypkg.org\n\nSee the \"Example scenario\" below to understand how `s3-npm-publish` lays out\nfiles in your bucket.\n\nTo release a specific version of a package (any NPM version identifier will\nwork):\n\n    docker run --rm \\\n      -e AWS_ACCESS_KEY_ID=... \\\n      -e AWS_SECRET_ACCESS_KEY=... \\\n      nickstenning/s3-npm-publish mypkg@2.0.1 s3://cdn.mypkg.org\n\nTo release to a path other than the bucket root:\n\n    docker run --rm \\\n      -e AWS_ACCESS_KEY_ID=... \\\n      -e AWS_SECRET_ACCESS_KEY=... \\\n      nickstenning/s3-npm-publish mypkg s3://cdn.mypkg.org/static\n\nIf you are running in an environment where the AWS CLI tools will be able to\nobtain credentials without you explicitly providing them (for example on an EC2\ninstance with an appropriate instance role profile) you can omit the `AWS_*`\nenvironment variables:\n\n    docker run --rm nickstenning/s3-npm-publish mypkg s3://cdn.mypkg.org\n\nExample scenario\n----------------\n\nYou have a package, `giraffejs`, which contains a JavaScript application which\nyou intend to release to an S3 bucket, `s3://assets.giraffejs.com`. The package\ncontains the following assets:\n\n    index.js\n    dist/app.js\n    dist/app.css\n\nFirst you would release the `giraffejs` package to NPM as usual, and then you\nwould run `s3-npm-publish` as follows:\n\n    docker run --rm \\\n      -e AWS_ACCESS_KEY_ID=... \\\n      -e AWS_SECRET_ACCESS_KEY=... \\\n      nickstenning/s3-npm-publish giraffejs s3://assets.giraffejs.com\n\nThis automatically detects that the latest version of the `giraffejs` package is\n(for example) `1.2.3` and will upload the contents of the package to:\n\n    s3://assets.giraffejs.com/giraffejs/1.2.3/index.js\n    s3://assets.giraffejs.com/giraffejs/1.2.3/dist/app.js\n    s3://assets.giraffejs.com/giraffejs/1.2.3/dist/app.css\n\nEach of these files will be served with [HTTP `Cache-Control` headers][3] which\nensure that they essentially never expire from any cache:\n\n    Cache-Control: public, max-age=315360000, immutable\n\n[3]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control\n\nIf `package.json` contains a `main` key, the file to which it points will be\nused to set up aliases in the bucket. For example if `package.json` contains\n\n    {\n      ...\n      \"main\": \"./index.js\",\n      ...\n    }\n\nthen `s3-npm-publish` will upload `index.js` to\n\n    s3://assets.giraffejs.com/giraffejs@1.2.3\n    s3://assets.giraffejs.com/giraffejs@1.2\n    s3://assets.giraffejs.com/giraffejs@1\n    s3://assets.giraffejs.com/giraffejs\n\nThe first of these (with the full version number) will be served with similar\n`Cache-Control` headers to the rest of the package. The latter three (which may\nbe updated when a new version is released) are served with a much shorter TTL\nand a request to user agents to revalidate the resource if the cache entry goes\nstale:\n\n    Cache-Control: public, max-age=1800, must-revalidate\n\nThis allow you to easily publish new versions of your package, and clients\npointing to (for example) the `1.2` alias will receive the new entrypoint script\nwhen a new version of the package in the `1.2.X` series is released.\n\nUnsolicited advice\n------------------\n\nIf you are serving a JavaScript application from an S3 bucket, you should\nprobably set up a CloudFront distribution or other CDN to front your bucket.\nThis will improve the perceived loading speed of your package assets, and (if\nyou have substantial traffic) likely reduce your costs.\n\nLicense\n-------\n\nThis project is released under the MIT license, a copy of which is provided in\n`LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnickstenning%2Fs3-npm-publish","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnickstenning%2Fs3-npm-publish","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnickstenning%2Fs3-npm-publish/lists"}