szymmis / vite-express

⚡ @vitejs integration module for @expressjs
MIT License
641 stars 38 forks source link

production build on Netlify keeps failing #121

Closed kaf-lamed-beyt closed 6 months ago

kaf-lamed-beyt commented 7 months ago

Hi, I'm setting up vite-express for the first time. This is what the script block in my package.json looks like:

  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },

And, here's my server file.

import express from "express";
import ViteExpress from "vite-express";

export const app = express();

ViteExpress.config({
  mode: "production",
});

ViteExpress.listen(app, 5173, () => console.log("Server is listening..."));

In my build logs, I keep getting "tsc: not found". Whenever I go ahead remove tsc from the command in package.json, and I'd get vite: not found.

What could be wrong? For context; here's an excerpt of what the error looks like:

7:51:22 PM: Build command from Netlify app                                
7:51:22 PM: ────────────────────────────────────────────────────────────────
7:51:22 PM: ​
7:51:22 PM: $ pnpm build
7:51:22 PM: > app@0.0.0 build /opt/build/repo
7:51:22 PM: > vite build
7:51:22 PM: sh: 1: vite: not found
7:51:22 PM:  ELIFECYCLE  Command failed.
7:51:22 PM: ​
7:51:22 PM: "build.command" failed                                        
7:51:22 PM: ────────────────────────────────────────────────────────────────
7:51:22 PM: ​
7:51:22 PM:   Error message
7:51:22 PM:   Command failed with exit code 1: pnpm build (https://ntl.fyi/exit-code-1)
7:51:22 PM: ​
7:51:22 PM:   Error location
7:51:22 PM:   In Build command from Netlify app:
7:51:22 PM:   pnpm build
kaf-lamed-beyt commented 7 months ago

I'm not sure. Express/Node.js apps are deployable on netlify.

I checked out Render, and I've been able to deploy a branch from my project without the error. Once I'm certain everything works fine. I'll close this.

szymmis commented 7 months ago

Hi @kaf-lamed-beyt, can you show me your whole package.json? It looks like vite and tsc are dev dependencies and they are not installed when Netlify is running the build command. My guess is that NODE_ENV is set to production and pnpm is installing only production dependencies. Can you check on that?

kaf-lamed-beyt commented 7 months ago

Alright. Gimme a couple of seconds. Let me fetch it.

szymmis commented 7 months ago

Also, I haven't use Netlify myself but from what I can see, it seems that classical Express apps don't work with it, only serverless function style. That might be a problem. Render should work 100% as I have tested it myself because I've had hosted one app there. The only problem with the free tier is that the container is killed if there is no traffic and there is quite a long cold start.

kaf-lamed-beyt commented 7 months ago

Here @szymmis

{
  "name": "twb",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "@chakra-ui/react": "^2.8.2",
    "@emotion/react": "^11.11.3",
    "@emotion/styled": "^11.11.0",
    "@lemonsqueezy/lemonsqueezy.js": "^2.1.0",
    "@react-spring/web": "^9.7.3",
    "@supabase/supabase-js": "^2.39.3",
    "@tanstack/react-query": "^5.20.5",
    "@types/dompurify": "^3.0.5",
    "@types/lodash.debounce": "^4.0.9",
    "@types/node-forge": "^1.3.11",
    "@types/react-helmet": "^6.1.11",
    "@uidotdev/usehooks": "^2.4.1",
    "@use-gesture/react": "^10.3.0",
    "cookies-next": "^4.1.1",
    "dayjs": "^1.11.10",
    "dompurify": "^3.0.8",
    "dotenv": "^16.4.1",
    "formik": "^2.4.5",
    "framer-motion": "^11.0.3",
    "lodash.debounce": "^4.0.8",
    "lucide-react": "^0.320.0",
    "node-forge": "^1.3.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-error-boundary": "^4.0.12",
    "react-helmet": "^6.1.0",
    "react-icons": "^4.12.0",
    "react-router-dom": "^6.21.3",
    "react-select": "^5.8.0",
    "sass": "^1.70.0",
    "yup": "^1.3.3",
    "zustand": "^4.5.0"
  },
  "devDependencies": {
    "@esbuild-plugins/node-globals-polyfill": "^0.2.3",
    "@tanstack/eslint-plugin-query": "^5.20.1",
    "@types/node": "^20.11.16",
    "@types/randomstring": "^1.1.11",
    "@types/react": "^18.2.43",
    "@types/react-dom": "^18.2.17",
    "@types/text-encoding": "^0.0.39",
    "@typescript-eslint/eslint-plugin": "^6.14.0",
    "@typescript-eslint/parser": "^6.14.0",
    "@vitejs/plugin-react": "^4.2.1",
    "drizzle-kit": "^0.20.13",
    "eslint": "^8.55.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.5",
    "typescript": "^5.2.2",
    "vite": "^5.0.8"
  }
}
szymmis commented 7 months ago

Yup, as I have thought, vite is a dev dependency and tsc is not even listed as a dependency from what I can see. It is still pretty weird because it is a build step on Netlify so it doesn't make sense for it to use NODE_ENV=production there. It's pretty hard to assess what is causing that. Let me know how the Render deploy is going then.

kaf-lamed-beyt commented 7 months ago

I moved both typescript and vite deps into "dependencies" and now, It seems to be working. But I have tons of typescript errors in the build process. So the build is still failing.

Now, I have omitted tsc just to ensure that it passes. If it does, I'll let you know.

As for the deployment on render. It deployed successfully, But, most of my HTTP requests are not being triggered at all. Perhaps it s related to some Render config, I'm not sure.

kaf-lamed-beyt commented 7 months ago

Now, I'm getting this.

$ vite build
11:38:43 PM: failed to load config from /opt/build/repo/vite.config.ts
11:38:43 PM: error during build:
11:38:43 PM: Error [ERR_MODULE_NOT_FOUND]: Cannot find package "@vitejs/plugin-react" imported from /opt/build/repo/vite.config.ts.timestamp-1709678323186-51c35c7b14506.mjs
11:38:43 PM:     at new NodeError (node:internal/errors:405:5)
11:38:43 PM:     at packageResolve (node:internal/modules/esm/resolve:916:9)
11:38:43 PM:     at moduleResolve (node:internal/modules/esm/resolve:973:20)
11:38:43 PM:     at defaultResolve (node:internal/modules/esm/resolve:1193:11)
11:38:43 PM:     at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:403:12)
11:38:43 PM:     at ModuleLoader.resolve (node:internal/modules/esm/loader:372:25)
11:38:43 PM:     at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:249:38)
11:38:43 PM:     at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:39)
11:38:43 PM:     at link (node:internal/modules/esm/module_job:75:36)
11:38:43 PM: ​
11:38:43 PM: "build.command" failed    

This is what my package.json looks like now:

{
  "name": "twb",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "@chakra-ui/react": "^2.8.2",
    "@emotion/react": "^11.11.3",
    "@emotion/styled": "^11.11.0",
    "@lemonsqueezy/lemonsqueezy.js": "^2.1.0",
    "@netlify/functions": "^2.4.1",
    "@react-spring/web": "^9.7.3",
    "@supabase/supabase-js": "^2.39.3",
    "@tanstack/react-query": "^5.20.5",
    "@types/dompurify": "^3.0.5",
    "@types/lodash.debounce": "^4.0.9",
    "@types/node-forge": "^1.3.11",
    "@types/react-helmet": "^6.1.11",
    "@uidotdev/usehooks": "^2.4.1",
    "@use-gesture/react": "^10.3.0",
    "axios": "^1.6.7",
    "cookies-next": "^4.1.1",
    "dayjs": "^1.11.10",
    "dompurify": "^3.0.8",
    "dotenv": "^16.4.1",
    "express": "^4.18.3",
    "formik": "^2.4.5",
    "framer-motion": "^11.0.3",
    "lodash.debounce": "^4.0.8",
    "lucide-react": "^0.320.0",
    "node-fetch": "^3.3.2",
    "node-forge": "^1.3.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-error-boundary": "^4.0.12",
    "react-helmet": "^6.1.0",
    "react-icons": "^4.12.0",
    "react-router-dom": "^6.21.3",
    "react-select": "^5.8.0",
    "sass": "^1.70.0",
    "vite-express": "^0.15.0",
    "yup": "^1.3.3",
    "zustand": "^4.5.0",
    "typescript": "^5.2.2",
    "vite": "^5.0.8"
  },
  "devDependencies": {
    "@esbuild-plugins/node-globals-polyfill": "^0.2.3",
    "@tanstack/eslint-plugin-query": "^5.20.1",
    "@types/express": "^4.17.21",
    "@types/node": "^20.11.16",
    "@types/randomstring": "^1.1.11",
    "@types/react": "^18.2.43",
    "@types/react-dom": "^18.2.17",
    "@types/text-encoding": "^0.0.39",
    "@typescript-eslint/eslint-plugin": "^6.14.0",
    "@typescript-eslint/parser": "^6.14.0",
    "@vitejs/plugin-react": "^4.2.1",
    "drizzle-kit": "^0.20.13",
    "eslint": "^8.55.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.5"
  }
}

And here's the content of server.js

import express from "express";
import ViteExpress from "vite-express";

export const app = express();

ViteExpress.config({
  mode: "production",
});

ViteExpress.listen(app, 5173, () => console.log("Server is listening..."));
kaf-lamed-beyt commented 7 months ago

Also, I haven't use Netlify myself but from what I can see, it seems that classical Express apps don't work with it, only serverless function style. That might be a problem. Render should work 100% as I have tested it myself because I've had hosted one app there. The only problem with the free tier is that the container is killed if there is no traffic and there is quite a long cold start.

Yes. You're right about this. I figured it'd be a platform issue.

With the limitation on render I might consider Railway or Fly.io

kaf-lamed-beyt commented 7 months ago

So uhm... @szymmis, the Railway deployment worked fine.

I had to bind Vite express to the custom "0.0.0.0" port. Per the docs on Railway and what the vite-express readme specifies

const server = app.listen(3000, "0.0.0.0", () =>
  console.log("Server is listening...")
);
szymmis commented 7 months ago

Really glad that you found a way to make it work @kaf-lamed-beyt! Thanks for letting me know.

I'll try to find a moment to check what providers allow hosting of vite-express app and update README to reflect that.

kaf-lamed-beyt commented 7 months ago

Ayy!

@szymmis There's still a minor issue though. I'm getting a 503 Error when I try to access a route I've created. Railway keeps throwing a 503 status code with the "Service unavailable error".

I read through their docs and found out it's because I'm not pointing my port to listen on "0.0.0.0". More on that here.

But, I've already done the needful in my server/index.js file:

import express from "express";
import ViteExpress from "vite-express";
import "dotenv/config";

export const app = express();

const retwittInstance = new Rettiwt();

ViteExpress.config({
  mode: "production",
});

const port = process.env.PORT || 3000;

const server = app.listen(port, "0.0.0.0", () => {
  console.log(`Server is listening on ${port}`);
});

ViteExpress.bind(app, server);

app.get("/api/twitter", async (req, res) => {
  const { id } = req.query;
  const response = await retwittInstance.tweet.details(tweetId);

  res.send(response);
});

And the error still persists. Perhaps you could help me with a minor repro. Maybe I'm missing something.

szymmis commented 7 months ago

Hi @kaf-lamed-beyt, it is really hard to tell why are you getting 503 Errors because I was able to setup this app on Railway here without any troubles. Maybe you can try to compare your code with it and see in what way it differs? What I can say right now is I'm just getting port from the env variable like you but there was no need to pass "0.0.0.0" as a host for me. I have not set anything up, just imported the repository and it just worked.

szymmis commented 6 months ago

Hi @kaf-lamed-beyt, I'm closing this issue as there is no activity here. Feel free to ask if you have any further questions.

kaf-lamed-beyt commented 6 months ago

I couldn't figure out why. Eventually I moved to Next.js.

Thanks for your help @szymmis