Description
Hello my vite friends! Recently, I created my own scaffolder inspired by create-vite, and while developing it I found a few things that could improve create-vite as well. Primarily, I'm talking about the dependencies @clack/prompts, mri, and cross-spawn. Each one of them either is a CJS package or brings a CJS package along - and since I am the biggest hater of CJS, I cannot stand this. Thankfully, most of these problems can be solved in just a few lines!!!
P.S. Turns out @vercel/detect-agent is also a CJS package... Sadly, I don't have a solution for this one (who ships CJS in 2026?!).
Suggested solution
@clack/prompts has a transitive dependency called sisteransi, which released v2.0.0 several months ago and ported the codebase to ESM with no API changes. Sadly, @clack/prompts still relies on the older version (1.0.5), which is still CJS. I've already opened an issue on their side asking to bump sisteransi to v2, but for now we can simply override the version in pnpm-workspace.yaml:
overrides:
sisteransi: "2.0.0"
This change is also useful because unused code from sisteransi can now be tree-shaken away.
mri
This one is the most hilarious! By default, when the target is set to node, tsdown first searches for the main: entry in package.json and only then the module: entry. mri ships two versions:
- CJS version for the
main: entry
- ESM version for the
module: entry
If we add this to tsdown.config.ts:
{
inputOptions: {
resolve: {
mainFields: ["module", "main"],
},
},
}
we flip the order so tsdown picks the correct (ESM) version of mri.
cross-spawn
This one is harder.
cross-spawn is a very popular package, yet it hasn't received a single commit in the past 2 years - not great. I couldn't find any drop-in replacements... so I decided to build one myself! cross-spawn-esm is a modern ESM + TypeScript port with several advantages over the original: it's ~50% smaller, has zero dependencies, ships types out of the box, and, of course, it's tree-shakable. The migration is very simple - check my Migration guide for more details.
In essence:
Before:
import spawn from 'cross-spawn'
// line 402
const { status, error } = spawn.sync(command, args, options)
// line 624
const { status } = spawn.sync(command, replacedArgs, {
stdio: 'inherit',
})
After:
import { spawnSync } from 'cross-spawn-esm'
// line 402
const { status, error } = spawnSync(command, args, options)
// line 624
const { status } = spawnSync(command, replacedArgs, {
stdio: 'inherit',
})
I guess this is the riskiest option since the package is very new and doesn't have many downloads, but you can take a look and decide whether you want to give it a shot. After all, since you're bundling your dependencies, there's no risk even if it turns out I'm a villain about to publish a virus in the next version lmao :)
After these changes, what do we get?
- Fewer transitive dependencies to worry about
- 4 kB reduction in the bundle
- Almost a fully ESM package (I should talk to the folks at Vercel about @vercel/detect-agent...)
- Since I'm the maintainer of cross-spawn-esm, you can always reach out to me if you hit any bugs or vulnerabilities - I'll patch them
It's not a lot, but it's honest work. If you decide against the @clack/prompts and cross-spawn changes, at least do the mri one so I can sleep well. After all, God's kingdom will arrive when no CJS is left in the wild ❤️
P.S. If needed, I can also open the PRs for these changes. Peace 🕊️
Alternative
No response
Additional context
No response
Validations
Description
Hello my vite friends! Recently, I created my own scaffolder inspired by
create-vite, and while developing it I found a few things that could improvecreate-viteas well. Primarily, I'm talking about the dependencies@clack/prompts,mri, andcross-spawn. Each one of them either is a CJS package or brings a CJS package along - and since I am the biggest hater of CJS, I cannot stand this. Thankfully, most of these problems can be solved in just a few lines!!!P.S. Turns out
@vercel/detect-agentis also a CJS package... Sadly, I don't have a solution for this one (who ships CJS in 2026?!).Suggested solution
@clack/prompts@clack/promptshas a transitive dependency calledsisteransi, which released v2.0.0 several months ago and ported the codebase to ESM with no API changes. Sadly,@clack/promptsstill relies on the older version (1.0.5), which is still CJS. I've already opened an issue on their side asking to bumpsisteransito v2, but for now we can simply override the version in pnpm-workspace.yaml:This change is also useful because unused code from
sisteransican now be tree-shaken away.mriThis one is the most hilarious! By default, when the target is set to
node, tsdown first searches for themain:entry in package.json and only then themodule:entry.mriships two versions:main:entrymodule:entryIf we add this to tsdown.config.ts:
we flip the order so tsdown picks the correct (ESM) version of
mri.cross-spawnThis one is harder.
cross-spawnis a very popular package, yet it hasn't received a single commit in the past 2 years - not great. I couldn't find any drop-in replacements... so I decided to build one myself! cross-spawn-esm is a modern ESM + TypeScript port with several advantages over the original: it's ~50% smaller, has zero dependencies, ships types out of the box, and, of course, it's tree-shakable. The migration is very simple - check my Migration guide for more details.In essence:
Before:
After:
I guess this is the riskiest option since the package is very new and doesn't have many downloads, but you can take a look and decide whether you want to give it a shot. After all, since you're bundling your dependencies, there's no risk even if it turns out I'm a villain about to publish a virus in the next version lmao :)
After these changes, what do we get?
It's not a lot, but it's honest work. If you decide against the
@clack/promptsandcross-spawnchanges, at least do themrione so I can sleep well. After all, God's kingdom will arrive when no CJS is left in the wild ❤️P.S. If needed, I can also open the PRs for these changes. Peace 🕊️
Alternative
No response
Additional context
No response
Validations