{"id":13531266,"url":"https://github.com/bahmutov/npm-install","last_synced_at":"2025-05-14T11:13:32.888Z","repository":{"id":37826205,"uuid":"221837995","full_name":"bahmutov/npm-install","owner":"bahmutov","description":"GitHub Action for install npm dependencies with caching without any configuration","archived":false,"fork":false,"pushed_at":"2025-04-18T05:26:35.000Z","size":2841,"stargazers_count":666,"open_issues_count":36,"forks_count":74,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-05T19:09:39.344Z","etag":null,"topics":["github-actions","npm-install","yarn"],"latest_commit_sha":null,"homepage":"https://github.com/marketplace/actions/npm-or-yarn-install-with-caching","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bahmutov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null}},"created_at":"2019-11-15T03:38:44.000Z","updated_at":"2025-04-29T05:01:36.000Z","dependencies_parsed_at":"2024-01-11T00:01:50.560Z","dependency_job_id":"f0cebd5e-0504-46ce-88a1-99b4e84c2721","html_url":"https://github.com/bahmutov/npm-install","commit_stats":{"total_commits":195,"total_committers":12,"mean_commits":16.25,"dds":0.6564102564102564,"last_synced_commit":"438a933ce1059e4e2b39e3d2a42c5067070dd444"},"previous_names":[],"tags_count":87,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fnpm-install","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fnpm-install/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fnpm-install/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fnpm-install/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bahmutov","download_url":"https://codeload.github.com/bahmutov/npm-install/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254129530,"owners_count":22019629,"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","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":["github-actions","npm-install","yarn"],"created_at":"2024-08-01T07:01:01.603Z","updated_at":"2025-05-14T11:13:32.863Z","avatar_url":"https://github.com/bahmutov.png","language":"JavaScript","funding_links":[],"categories":["Community Resources","JavaScript","五、按场景分类的实用Action"],"sub_categories":["Utility","1. 依赖管理（提速+合规）"],"readme":"# npm-install [![semantic-release][semantic-image] ][semantic-url] [![renovate-app badge][renovate-badge]][renovate-app]\n\n\u003e GitHub Action for install npm dependencies with caching without any configuration\n\n## CI\n\n\u003c!-- prettier-ignore-start --\u003e\nExample | Status\n--- | ---\n[main](.github/workflows/main.yml) | ![this repo](https://github.com/bahmutov/npm-install/workflows/main/badge.svg?branch=master)\n[basic](.github/workflows/example-basic.yml) | ![basic example](https://github.com/bahmutov/npm-install/workflows/example-basic/badge.svg?branch=master)\n[shrinkwrap](.github/workflows/example-shrinkwrap.yml) | ![shrinkwrap example](https://github.com/bahmutov/npm-install/workflows/example-shrinkwrap/badge.svg?branch=master)\n[Yarn](.github/workflows/example-yarn.yml) | ![yarn example](https://github.com/bahmutov/npm-install/workflows/example-yarn/badge.svg?branch=master)\n[without lock file](.github/workflows/example-without-lock-file.yml) | ![without lockfile example](https://github.com/bahmutov/npm-install/workflows/example-without-lock-file/badge.svg?branch=master)\n[subfolders](.github/workflows/example-subfolders.yml) | ![subfolders example](https://github.com/bahmutov/npm-install/workflows/example-subfolders/badge.svg?branch=master)\n[Node version](.github/workflows/example-node-version.yml) | ![Node version example](https://github.com/bahmutov/npm-install/workflows/example-node-version/badge.svg?branch=master)\n\u003c!-- prettier-ignore-end --\u003e\n\n## Examples\n\n### Basic\n\nThis example should cover 95% of use cases.\n\nIf you use `npm ci` or `yarn --frozen-lockfile` on CI to install NPM dependencies - this Action is for you. Simply use it, and your NPM modules will be installed and the folder `~/.npm` or `~/.cache/yarn` will be cached. Typical use:\n\n```yml\nname: main\non: [push]\njobs:\n  build-and-test:\n    runs-on: ubuntu-latest\n    name: Build and test\n    steps:\n      - uses: actions/checkout@v4\n      - uses: bahmutov/npm-install@v1\n      - run: npm t\n```\n\nSee [bahmutov/npm-install-action-example](https://github.com/bahmutov/npm-install-action-example) ![npm-install-action-example](https://github.com/bahmutov/npm-install-action-example/workflows/main/badge.svg?branch=master).\n\n### Subfolders\n\nIf your repository contains packages in separate folders, install each one separately\n\n```text\nrepo/\n  app1/\n    package-lock.json\n  app2/\n    yarn.json\n```\n\n```yml\nname: main\non: [push]\n\njobs:\n  build-and-test:\n    runs-on: ubuntu-latest\n    name: Build and test\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: bahmutov/npm-install@v1\n        with:\n          working-directory: app1\n      - uses: bahmutov/npm-install@v1\n        with:\n          working-directory: app2\n\n      - name: App1 tests\n        run: npm t\n        working-directory: app1\n      - name: Run app2\n        run: node .\n        working-directory: app2\n```\n\nSee [npm-install-monorepo-example](https://github.com/bahmutov/npm-install-monorepo-example) ![npm-install-monorepo-example](https://github.com/bahmutov/npm-install-monorepo-example/workflows/main/badge.svg?branch=master).\n\nYou can also specify multiple subfolders in a single action; one subfolder per line.\n\n```yml\nname: main\non: [push]\n\njobs:\n  build-and-test:\n    runs-on: ubuntu-latest\n    name: Build and test\n    steps:\n      - uses: actions/checkout@v4\n      - uses: bahmutov/npm-install@v1\n        with:\n          working-directory: |\n            app1\n            app2\n```\n\n### Use lock file\n\nBy default, this action will use a lock file like `package-lock.json`, `npm-shrinkwrap.json` or `yarn.lock`. You can set `useLockFile: false` to use just `package.json` which might be better for [building libraries](https://twitter.com/mikeal/status/1202298796274700288).\n\n```yml\n- uses: bahmutov/npm-install@v1\n  with:\n    useLockFile: false\n```\n\n### Use time-based rolling cache\n\nBy default, yarn and npm dependencies will be cached according to the exact hash of the lockfile (if enabled) or the `package.json`. This will cause cache misses when the dependencies change, which can be slower than re-installing for big projects. To re-use the cache across runs with different lockfiles/dependencies, you can enable the `useRollingCache` option, which will restore the cache from more keys. It will expire the cache once a month to keep it from growing too large, see the Cache Snowballing \u0026 Rolling Cache expiry below.\n\n```yml\n- uses: bahmutov/npm-install@v1\n  with:\n    useRollingCache: true\n```\n\n`useRollingCache` is defaulted to false.\n\n### Production dependencies\n\nYou can install just the production dependencies (without installing dev dependencies) by setting an environment variable `NODE_ENV` variable\n\n```yml\n- uses: bahmutov/npm-install@v1\n  env:\n    NODE_ENV: production\n```\n\n### Custom install command\n\nYou can use your own install command\n\n```yml\n- uses: bahmutov/npm-install@v1\n  with:\n    install-command: yarn --frozen-lockfile --silent\n```\n\nSee [example-install-command.yml](./.github/workflows/example-install-command.yml)\n\n### Add cache prefix\n\nIf you are installing different individual tools, you might want to have different caches. You can insert custom cache prefix strings into the cache keys. For example, let's install two different tools, each cache will be separate.\n\n```yml\n- name: Install tool A\n  uses: bahmutov/npm-install@v1\n  with:\n    # use just package.json checksum\n    useLockFile: false\n    install-command: 'npm install tool-a'\n    cache-key-prefix: tool-a\n\n- name: Install tool B\n  uses: bahmutov/npm-install@v1\n  with:\n    # use just package.json checksum\n    useLockFile: false\n    install-command: 'npm install tool-b'\n    cache-key-prefix: tool-b\n```\n\nThe first cache will have key `npm-tool-a-...` and the second cache will have key `npm-tool-b-...`\n\n### Node version\n\nIf you need to use a specific Node version, use the [actions/setup-node](https://github.com/actions/setup-node) before installing the dependencies.\n\n```yml\n- uses: actions/checkout@v4\n  # pick the Node version to use and install it\n  # https://github.com/actions/setup-node\n  - uses: actions/setup-node@v3\n    with:\n      node-version: 18\n  - uses: bahmutov/npm-install@v1\n```\n\nSee [example-node-version.yml](./.github/workflows/example-node-version.yml)\n\n### External examples\n\n\u003c!-- prettier-ignore-start --\u003e\nName | Description\n--- | ---\n[npm-install-example](https://github.com/bahmutov/npm-install-example) | Shows how to use this action\n\u003c!-- prettier-ignore-end --\u003e\n\n## NPM\n\nIf you are writing your own GitHub Action and would like to use this action as a utility function, import it and run it.\n\n```js\nconst { npmInstallAction } = require('npm-install')\nawait npmInstallAction()\n```\n\n## Debugging\n\nYou can see verbose messages from GitHub Actions by setting the following secrets (from [Debugging Actions Guide](https://github.com/actions/toolkit/blob/master/docs/action-debugging.md#step-debug-logs))\n\n```\nACTIONS_RUNNER_DEBUG: true\nACTIONS_STEP_DEBUG: true\n```\n\n**Tip:** environment variable `ACTIONS_STEP_DEBUG` enables debug messages from this action itself, try it first.\n\n## Testing\n\nUsing Mocha and Sinon.js following the guide [How to set up Mocha with Sinon.js](https://glebbahmutov.com/blog/mocha-and-sinon/). You can find the tests in [test](test) folder. In general:\n\n- all environment inputs are done inside the action, so they can be stubbed and controlled during tests\n- there are separate workflows in [.github/workflows](.github/workflows) that match examples. Each workflow uses this action to install dependencies\n\n## Cache Snowballing \u0026 Rolling Cache expiry\n\nBy default, this action will cache dependencies using an exacty hashs of the lock file (like `package-lock.json`, `npm-shrinkwrap.json` or `yarn.lock`). If you change any dependencies, there will be a cache miss. This is the default cache key strategy to avoid unbounded growth of the cache, as if you don't expire the cache, it will continue being added to. See [this post](https://glebbahmutov.com/blog/do-not-let-npm-cache-snowball/) for more details on this issue.\n\nTo get better cache hit rates without the cache size snowballing, you can turn on this action's `useRollingCache` option, which will allow old caches to be re-used when your dependencies change, at the expense of some snowballing. Instead of letting the cache grow forever, this action resets it every month by including the current month in the cache key.\n\nThe rule of thumb is this: if re-installing your dependencies doesn't take very long, you can avoid superfluous cache restores by keeping `useRollingCache` off. This is the recommended setup for small projects. For big projects where installing the dependencies takes a long time, and cache restores are faster, `useRollingCache` will provide a performance improvement.\n\n## Links\n\n- [Do Not Let NPM Cache Snowball on CI](https://glebbahmutov.com/blog/do-not-let-npm-cache-snowball/) blog post\n- [Trying GitHub Actions](https://glebbahmutov.com/blog/trying-github-actions/) blog post\n- [GitHub Actions in Action](https://slides.com/bahmutov/github-actions-in-action) slides\n\n### Small print\n\nAuthor: Gleb Bahmutov \u0026lt;gleb.bahmutov@gmail.com\u0026gt; \u0026copy; 2019\n\n- [@bahmutov](https://twitter.com/bahmutov)\n- [glebbahmutov.com](https://glebbahmutov.com)\n- [blog](https://glebbahmutov.com/blog)\n\nLicense: MIT - do anything with the code, but don't blame me if it does not work.\n\nSupport: if you find any problems with this module, email / tweet /\n[open issue](https://github.com/bahmutov/npm-install/issues) on Github\n\n## MIT License\n\nCopyright (c) 2019 Gleb Bahmutov \u0026lt;gleb.bahmutov@gmail.com\u0026gt;\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n[semantic-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg\n[semantic-url]: https://github.com/semantic-release/semantic-release\n[renovate-badge]: https://img.shields.io/badge/renovate-app-blue.svg\n[renovate-app]: https://renovateapp.com/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahmutov%2Fnpm-install","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbahmutov%2Fnpm-install","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahmutov%2Fnpm-install/lists"}