Vercel announced a new feature to mitigate errors due to version skew. Their blog post goes into the nature of the problem and the solution, but only mentions Nextjs. This is a problem I have also faced while working with Solidjs using SolidStart.
I suspected (hoped) this might be a platform feature with the direction of Vercel’s Build Output API and not something specific to Nextjs.
Looking into Nextjs
Trying to identify how it was implemented in Nextjs I searched for useDeploymentId in the Nextjs Github Repo. Investigating the git history I found the commits that added this functionality.
Looks like just adding the deployment id via ?dpl= query param or x-deployment-id header to asset requests was sufficient, indicating that this is a platform feature.
Trying it out
Before trying to implement this in SolidStart, I wanted to see if this would work outside of Nextjs.
I made a simple SolidStart app with a dynamic import and deployed it to Vercel.
Lets try out if specifying the header allows us to target specific deployments. I changed the data and deployed the new version, noting the filenames from the network tab.
Note: To get the deployment id I viewed the deployment on the Vercel dashboard.
After deploying v2 trying to fetch the v1 asset returns 404 as expected.
Adding the deployment header x-deployment-id we hit our old deployment and get our data! Now that we know it works outside of Nextjs, we just need to make this automatic for all our assets. Obtaining the deployment id programatically to test this theory would be the start.
Other findings
While undocumented, the Nextjs implementation of adding dpl search param also worked.
When both deployment search param and header is set, search param is used.
Deployment id dpl_ prefix is optional.
Getting the Vercel Deployment Id
Vercel exposes a bunch of System Environment Variables. Nextjs has NEXT_DEPLOYMENT_ID although not listed on the env variables page probably due to its experimental nature it is mentioned in Skew Protection. Unfortunately with SolidStart it was not provided.
Trying to figure out how I could get this I found the Deployment API that I could call with the deployment host exposed through VITE_VERCEL_URL - the current deployment’s host. This is not ideal though since we need to make a network request.
However, upon inspection of the response I noticed that there were additional build env variables that piqued my interest.
Shortened Response
VERCEL_DEPLOYMENT_SKEW_HANDLING was set to 1 . I could not find any info on what it does. I suspect this enables the skew protection route handling.
VERCEL_DEPLOYMENT_ID is the equivalent to Nextjs’s NEXT_DEPLOYMENT_ID, however this variable is not exposed during runtime. Since Vite replaces import.meta.env variables at build time we can use this, but we have to prefix it with VITE_ (Vite docs). We now have our deployment id.
The Solid glue
All we need to do now is add the deloyment id to our asset requests. Being unfamiliar with how js assets are loaded, I looked at the Solid build output. We can see the dynamic imports call an import function and the browser requests the file. Although there are other ways assets are requested I’ll only focus on this.
I settled on a quick and dirty solution of creating a Vite plugin that adds the deployment search param to dynamic imports.
What the plugin does
Map VERCEL_DEPLOYMENT_ID to import.meta.env.VITE_VERCEL_DEPLOYMENT_ID so we no longer need the modified build script to reassign the variabl
When building client bundle add __deploymentImport() to the client entry, entry-client.tsx
Replace dynamic imports to use the dynamic import function instead of the usual import("file.js")
Let’s build and check the output again. We should see dynamic imports use our custom function and its declaration in the client entry. This can also be verified by inspecting the network tab in the browser to see our assets have the dpl search param.
While I was focused on getting this to work with SolidStart, I believe this could work with any framework deployed to Vercel!
Similar solution that requests based off deployment ids could be implemented on other serverless platforms.