Bundling dependencies is a pain (duh)
I just published our first open source action that deploys an application to Docker Swarm. This action relies on some fairly old npm packages, and thus mixes ES modules and CJS dependencies (*shudders*).
Now my initial assumption that actions would somehow surely install the module dependencies before running it was obviously wrong, if unexpected; however I still find it very strange that my options boil down to:
- checking in my 375MB
node_modules/folder that consists of 98% development dependencies, which will be downloaded on every action run, or - use
@vercel/nccand hope it works, because if it doesn't, there's no configuration options and you're SOL
While the second option seemed obvious, it quickly broke down due to some tier-4 dependency using __dirname in a module context, which means either I'll implement a full Docker API client myself, or replace the build tooling. Bummer.
So finally I built this exciting Rube-Goldberg-esque contraption that uses unbuild to create a CJS "bundle" (in quotes, because it won't bundle the CJS dependencies) and chains ncc to actually bundle that into a self-contained package. It's awkward, but it works, and I'm over my time budget for something so trivial already. Not to mention I'd rather cut my arm off than spending any more time in module intestines.
Having recovered from the shell shock of that, I wanted to complain about it here. Creating an action that uses dependencies shouldn't be so awful in 2025. Either provide a runtime that will auto-install prod-dependencies from the package.json, build some cached Docker image for node actions that will install them during the build phase, have a release action that prunes the modules before re-committing them, or offer a first-party GitHub actions bundler that wraps things up properly. The use case of building a self-contained node.js application is fairly obscure and mostly limited to GH Actions, so having at least a bit better tooling here would be nice.
:wave: @Radiergummi! Thank you for the detailed issue! It sounds like we've both run into a number of the same headaches...
First off, I have opened a request to the GitHub documentation to remove the suggestion that developers commit the entire node_modules directory to their action repository. I agree that this is not an ideal practice to publish GitHub Actions.
Second, my experience so far has been that @vercel/ncc works great for CommonJS actions, but not so much those written in ES module syntax. Have you tried using rollup instead? This repo has been updated to use that for bundling action code and dependencies, and has worked pretty well so far. It also has a fair number of configuration options to make use of. I haven't gone too far down the ESM/CommonJS bundling rabbit-hole, but for the actions I have authored, there hasn't been any major issues.
You can potentially disregard the above, since it appears
unbuildusesrollupunder the hood.
Unfortunately I don't have a 100% effective answer yet. I'm still holding off until Immutable Actions is GA (currently in public preview). Once that is available, this should resolve many of the challenges JavaScript/TypeScript actions developers are experiencing since the action can be built and published as an OCI image with all dependencies included. I will also keep an eye out so that I can update this repository to use them going forward!
Second, my experience so far has been that @vercel/ncc works great for CommonJS actions, but not so much those written in ES module syntax.
FWIW I've been using @vercel/ncc and it handles ESM => CJS with TypeScript in all of my GitHub Actions workflows with ease.
OCI is getting scheduled/prioritized and as of the time of writing, it's slated for Q4 2025. For the next 6+ months or until that lands, I think bundling node_modules into a dist'd GHA is the way to go.
Additionally, once node22 lands as a runtime, all CJS/ESM interop will no longer be an issue. Not sure when exactly that's slated to occur.
Unfortunately I don't have a 100% effective answer yet. I'm still holding off until Immutable Actions is GA (currently in public preview). Once that is available, this should resolve many of the challenges JavaScript/TypeScript actions developers are experiencing since the action can be built and published as an OCI image with all dependencies included. I will also keep an eye out so that I can update this repository to use them going forward!