Good idea.
in summary, it turned out to be all due to my lack of understanding rather than it being something to do with Vercel or using Bun as a package manager on Vercel. In hindsight, the solution is very easy and I barely had to do anything. Still, I’ll try to explain what I was thinking incase it helps anyone.
The following settings are the current state of the files with my Vercel deployment working successfully:
First, my project structure:
package.json
{
"name": "options",
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "NODE_ENV=development bunx --bun vite",
"build": "NODE_ENV=production tsc && vite build",
"preview": "NODE_ENV=production vite preview"
},
"devDependencies": {
"typescript": "~5.6.2",
"vite": "^6.0.5"
},
"dependencies": {
"@neondatabase/serverless": "^0.10.4",
"dotenv": "^16.4.7"
}
}
FYI: my project uses the neondatabase/serverless
package but Vercel offers a Neon database integration (which I’ll switch over to in the near future)
vercel.json
{
"version": 2,
"rewrites": [
{
"source": "/api/(.*)",
"destination": "/api/index"
},
{
"source": "/(.*)",
"destination": "/index.html"
}
]
}
tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"isolatedModules": true,
"moduleDetection": "force",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
},
"include": [
"src"
]
}
So, prior to opening up this thread I was getting this error message:
Cannot find module '/var/task/src/server/database.ts' imported from /var/task/api/index.js
I was confused as to why the database.ts
file wasn’t being compiled to database.js
. I assumed (correctly) that it should have been compiled since that’s what package.build script: "build": "tsc && vite build"
, should be doing. However, in my tsconfig.json
at the time I had the following settings:
"allowImportingTsExtensions": true,
"noEmit": true,
so I commented them out and even then I kept getting the same error,
Cannot find module '/var/task/src/server/database.ts' imported from /var/task/api/index.js
and for some reason within the build logs
in the Deployment Details
for my project on Vercel, I was seeing tsc && vite build
highlighted in red, so I assumed it wasn’t running properly and therefore not compiling my .ts
files into .js
files. Also, within the error message I noticed that the api/index.ts
file was being compiled to .js
:
..... /var/task/api/index.js // /api/index.ts was being compiled to index.js
so, based off those assumptions I added the following buildCommand
to vercel.json
file
"buildCommand": "bunx tsc && bunx vite build",
This helped get rid of the tsc && vite build
highlighted in red in the build logs. But, I kept getting the same error:
Cannot find module '/var/task/src/server/database.ts' imported from /var/task/api/index.js
due to my assumptions I couldn’t figure out why the .ts
file wasn’t being compiled to .js
, so after some more reading through the vercel documents I saw that we can use includeFiles
to let Vercel know we want those files included in our Functions. So, I added it to my vercel.json
{
"version": 2,
"buildCommand": "bunx tsc && bunx vite build",
"functions": {
"api/index.ts": {
"includeFiles": "src/server/**"
},
"rewrites": [
...
]
}
}
I still kept getting the same error.
So, I went back into my source files and removed all the .ts
extensions from all the imports. I got the same error but this time without the .ts
, instead it just said database
:
Cannot find module '/var/task/src/server/database' imported from /var/task/api/index.js
at some point, I went back into my source files and added .js
to all the imported lines that I had earlier removed .ts
from and it worked!
I made a few assumptions, such as expecting the files included within includeFiles
in vercel.json to be compiled from .ts
to .js
. I made this assumption because I saw that /api/index.ts
was being compiled to /api/index.js
. I don’t know if that makes sense or if that is the expected behaviour but it didn’t happen in my situation.
I also made the assumption that since tsc
is compiling my ts files into js files, that those imports would automatically also get compiled. I find it strange that I need to import .js
files within .ts
files, it feels like I should be able to import .ts
files and when I run tsc
it should change those imports to their .js
equivalents. I know now (I think) that that isn’t doable because to import .ts
files you need to set "allowImportingTsExtensions": true,
and to set that to true, you need to set "noEmit": true,
. And right there is the issue, setting noEmit:true
results in no javascript files being emitted from compilation.
After knowing what the solution was, I went back and removed lines of code I had added. The code snippets I shared at the start of this post are sufficient for me to deploy to Vercel using Bun as a package manager. Also, the project is using http
module to create a basic server.
Thanks for reading.