How to fix NestJS deployment error to the Vercel? - node.js

this is the now.json
{
"version": 2,
"name": "nestjs-now",
"builds": [
{
"src": "dist/main.js",
"use": "#now/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "dist/main.js"
}
]
}
I'm not sure what's the reason and how to fix.
I just followed the vercel tutorial to deploy my nestjs backend project, but don't works.
It inclues GraphQL APIs and Rest APIs together as well as socket.io server.

Why it doesn't work?
Serverless Functions on Vercel (at the moment) do not accept a build step for the code of the function. For that reason, any backend framework that needs a "build step" to generate a server, will not work.
What Vercel is best for?
Frontend deployments and Serverless Functions as helpers. Full-blown APIs should be deployed elsewhere. You can check the following resources:
https://vercel.com/guides
https://vercel.com/import
https://vercel.com/docs/runtimes#official-runtimes
What are my options?
I recommend that you use Heroku or Digital Ocean as alternatives.
Update 2021-11-11
Now you can deploy any framework with SSR, API routes, and Edge Functions (soon) to Vercel. Just make sure you are following the File System API specification.
You can read the introduction section for more information. Remember that Vercel is a platform optimized for frontend deployments.

the problem is that VERCEL looks for the DIST folder as soon as it starts the BUILD process
What you can do is remove the DIST folder from the .gitignore this way it will resolve the 404
after that, whenever you make a new deploy it is necessary to force deploy without cache to compile your dist againe

In your production dashboard you will find this buttom with
vercel function logs
and inside you can find what is breaking your app
but, in my opinion, the first mistake that are crashing is about your VERCEL.JSON file:
When you are building a serveless app in nestjs, you will not renderize by dist/ or output/, you gotta render from your src/, so your vercel.json must be like this:
{
"version": 2,
"builds": [
{
"src": "src/main.ts",
"use": "#vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "src/main.ts",
"methods": ["GET", "POST", "PUT", "PATCH", "DELETE"]
}
]
}
And you must do set it with the documentation help
calling your API like it needs.
This following resolution doesn't works with NESTJS/SWAGGER because it is not sending SwaggerUIBundle to browser as in this image, but a solution to the same issue can be founded here with only swagger in C# (and if is your case, you can try to adapt it to nestjs/swagger)
I oppened this to find some solution

I have successfully deploy nestjs to vercel and I used the following starter project: https://github.com/nestjs/javascript-starter
1)- first, you need to install #babel/cli and #babel/core both at the same time, otherwise npx will install out-of-dated babel 6.x. which will cause issues later when building the project using babel, and thats according to babel own docs
2)- remove #babel/core from package.json
3)- remove #babel/cli if exists from package.json
4)- remove package-lock.json
5)- remove node_modules
6)- run the command npm i
7)- run the command npm i --save-dev #babel/core #babel/cli
8)- build/transpile the project using the command npx babel src --out-dir build
9)- add vercel.json to your project like with following
{
"version": 2,
"builds": [
{
"src": "build/main.js",
"use": "#vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "build/main.js",
"methods": [ "GET", "POST", "PUT", "PATCH", "DELETE" ]
}
]
}
10)- now push this to github, then deploy to vercel

Related

change the path of asset files in jest

So I want to run an e2e test using jest. I'm using nx monorepo architecture, and I have all my assets in a library folder and also nestjs microservices for my backend. I have all my proto files for my microservices in the library, and when I want to load them in my microservices, I do it like this :
protoPath: join(__dirname, 'assets-shared/job.proto'),
and in my workspace.json in my build i change the assets-shared like this:
"targets": {
"build": {
"options": {
"assets": [
{
"input": "libs/backend/shared/src/lib/assets",
"glob": "**/*",
"output": "assets-shared"
}
]
},
all is good, but when I run the test and when it wants to import and give value to it, it doesn't change it, and I have this error which is trying in its folder and not the library folder
ENOENT: no such file or directory, open '/home/dev/Project/apps/backend/api/src/modules/product/assets-shared/job.proto'
I tried the moduleNameMapper to give the libs folder to it manually but no avail.
moduleNameMapper: {
'^.+\\.(proto)$':
'<rootDir>/libs/backend/shared/src/lib/assets/$1',
// '^assets-shared(.*)': '/libs/backend/shared/src/lib/assets/$1',
},
non of these two worked
Have you considered publishing the libraries to a private npm repository or something like artifactory e.g. #my-company/assets
The approach you are trying may work locally, but for a ci/cd pipeline it would be much better to have a versioned artifact in npm or artifactory

Jest moduleNameMapper and NPM package exports

I am developing fullstack NPM packages with multiple entrypoints (namely client, server and sometimes tests), using the exports property of package.json.
I also use a small hack to make TS work with exports until it's officially supported (see this Stack Overflow post, this hackish solution and this ticket).
The package.json ends up looking like this:
{
"name": "#vulcanjs/graphql",
"version": "0.4.7",
"main": "./dist/index.js",
"files": [
"dist/"
],
"exports": {
".": "./dist/index.js",
"./server": "./dist/server/index.js",
"./testing": "./dist/testing.js"
},
"types": "./dist/index.d.ts",
"typesVersions": {
"*": {
"server": [
"./dist/server/index.d.ts"
],
"testing": [
"./dist/testing.d.ts"
]
}
},
"description": "Vulcan graphQL schema generator",
...
You can then import using either #vulcanjs/graphql for shared code, and #vulcanjs/graphql/server for Node.js-only code.
It works perfect in my Next.js app. However, it seems to break Jest moduleNameMapper.
First, I had this:
moduleNameMapper: {
"#vulcanjs/(.*)": [
"<rootDir>/node_modules/#vulcanjs/$1",
],
},
The error is:
Configuration error:
Could not locate module #vulcanjs/graphql/server mapped as:
[
"/code/vulcan-next/node_modules/#vulcanjs/graphql/server",
].
The problem is that it tries to find a package named #vulcanjs/graphql/server: yet "server" is not a different package, it's an entrypoint of #vulcanjs/graphql.
I've also tried this:
moduleNameMapper: {
"#vulcanjs/(.*)/(.*)": [
"<rootDir>/node_modules/#vulcanjs/$1",
],
},
With this config, #vulcanjs/graphql/server is mapped to #vulcanjs/graphql. The problem is that now, server code is not found. I've checked and the problem is that this solution totally removes the /server: so #vulcanjs/graphql/server points to the main entrypoints instead of the server entrypoint.
Finally I did try to remove the moduleNameMapper, but then #vulcanjs/graphql/server package is not found by Jest. Note that I need the mapper for a use case I did not demonstrate here, so getting rid of it is possible but not the best solution.
The bug can be reproduced by installing the framework: https://github.com/VulcanJS/vulcan-next. You can clone, yarn install, unskip the test in src/models/tests/sampleModel.server.test.ts and run yarn run test:unit sampleModel. It will show the error.
Any idea how I could fix this?

Using NodeJS development dependencies in Heroku review-app post-deploy step

I have a (demo) application hosted on Heroku. I've enabled Heroku's "review app" feature to spin up new instances for pull request reviews. These review instances all get a new MongoDB (on mLab) provisioned for them through Heroku's add-on system. This works great.
In my repository, I've defined some seeder scripts to quickly get a test database up and running. Running yarn seed (or npm run seed) will fill the database with test data. This works great during development, and it would be perfect for review apps as well. I want to execute the seeder command in the postdeploy hook of the Heroku review app, which can be done by specifying it under the environment.review section of the app.json file. Like so:
{
"name": "...",
"addons": [
"mongolab:sandbox"
],
"environments": {
"review": {
"addons": [
"mongolab"
],
"scripts": {
"postdeploy": "npm run seed"
}
}
}
}
The problem is, the seeder script relies on some development-only dependencies (faker, ts-node [this is a TypeScript project], and mongo-seeding) to execute. And these dependencies are not available in the postdeploy phase of an Heroku app.
I also don't think that "compiling" the typescript in the regular build step is the best idea. This seeder script is only used in development (and review apps). Besides, I'm not sure that would resolve the issue with missing dependencies like faker.
How would one go about this? Any tricks I'm missing?
Can I maybe skip Heroku's step where it actively deletes development dependencies? But only for review apps? Or even better, can I "exclude" just the couple of dependencies I need, and only for review apps?
The Heroku docs indicate that when the NODE_ENV variable contains anything but "production", the devDependencies will not be removed after the build step.
To make sure this only happens for Heroku review apps, you can set the NODE_ENV variable under the environments.review section of the app.json file. The following config should do the trick:
{
"name": "...",
"addons": [
"mongolab"
],
"environments": {
"review": {
"addons": [
"mongolab:sandbox"
],
"env": {
"NODE_ENV": "development"
},
"scripts": {
"postdeploy": "npm run seed"
}
}
}
}

Generate package.json on nx build / deployment

I've a monorepo using nx with multiple node/nestjs apps. Some of the apps doesn't require all the packages used in the other apps. Because it's a monorepo, I need to install all packages for every apps during the deployment.
Is there a way generate a package.json on build that would contain only the packages needed for the app that I'm building?
I've tryed to use "generate-package-json-webpack-plugin" to generate the package.json, but it only detect half the dependencies.
I've also tried to build a single js file containing all the apps, but it doesn't seem to work and always require tslib.
After I look at the nx source code I found the answer.
Set generatePackageJson to true in workspace.json where <project-name>/targets/build/options.
This will generate you package.json with the necessary dependencies for your app.
Here example:
"node-api": {
"root": "apps/node-api",
"sourceRoot": "apps/node-api/src",
"projectType": "application",
"prefix": "node-api",
"targets": {
"build": {
"executor": "#nrwl/node:build",
"outputs": ["{options.outputPath}"],
"options": {
"showCircularDependencies": false,
"outputPath": "dist/apps/node-api",
"main": "apps/node-api/src/main.ts",
"tsConfig": "apps/node-api/tsconfig.app.json",
"assets": ["apps/node-api/src/assets"],
"generatePackageJson": true <----------------------
},
....
Nx encourages a single-version policy and has a single package.json.
If the issue is that you are installing all the dependencies every time in CI before building then you might need to rely on the functionality provided by your CI system to cache these between runs - a lot of existing CI systems do provide these:
* Gitlab: https://docs.gitlab.com/ee/ci/caching/
* CircleCI: https://circleci.com/docs/2.0/caching/
* Travis: https://docs.travis-ci.com/user/caching/
However this comes with its own set of issues (e.g. parallel jobs where one or more is changing the dependencies).
We can try to explore having a command in Nx: sort of a "affected:dep-install" that will detect which packages to install as part of the affected command. Please create an issue for it here: https://github.com/nrwl/nx/issues

Node app create production build for live web site - static files (no node running on webhost)

I have a question which sounds maybe trivial, but I feel like I life behind the moon.
In those default React Apps, which are initialised by
npm install -g create-react-app
create-react-app my app
I build whatever with this app and in the end of the day, I put in
npm run build
and it builds static files that I can upload via ftp to my existing Webspace with my domain live in the internet. No Haruko, no AWS, no installing node anywhere.
Now my question, how can I do the same with a random node.js ?
I find a gazillion tutorials how to build apps on an server on localhost and even many on how to install node in some webspace.
But how do I generate those 'static files' that I just upload via FTP and dones? Am I the only one who wants to do it that way?
If so, what is wrong with that thinking?
I'm using web-boost static site generator with page-speed optimizations.
You have to explicitly show all the routes you are going to convert from dynamic application into static ones like this:
{
"routes": {
"/": {
"view": "index.twig",
"vars": {
"title": "Home page",
"greeting": "Hello world!"
},
"assets": {
"js/index.min.js": [
"js/index.js"
]
}
},
"/user": {
"view": "user.twig",
"vars": {
"title": "User's page",
"greeting": "Hi John Doe!"
},
"assets": {
"css/user.min.css": [
"styles/bootstrap.min.css",
"styles/user.scss"
]
}
}
}
}
and then run compile command and deploy your static pages into AWS.S3 bucket for example.

Resources