Deploy sveltekit app on vercel using node adapter - express

I'm trying to deploy my app on vercel using node adapter. I know that i should use the vercel adapter but i made some changes to make sveltekit work with socket.io. I followed this guide: https://joyofcode.xyz/using-websockets-with-sveltekit.
The Node adapter creates the index.js and handler.js files in your build folder when you run npm run build — creating a custom server works by importing the handler from build/handler.js and using your custom server instead of index.js. Then I created a index.js file at the root of the project with the following content:
import http from 'http';
import express from 'express';
import injectSocketIO from './src/lib/websockets/socketIoHandler.js';
import { handler } from './build/handler.js'
const app = express();
const server = http.createServer(app);
// // Inject SocketIO
injectSocketIO(server);
// // SvelteKit handlers
app.use(handler);
server.listen(3000, () =\> {
console.log('Running on http://localhost:3000');
});
i tryied in some ways to make the deploy but I can't make it work...
How could I deploy the app on vercel? Thanks!
enter image description here
using this vercel.json file:
{
"version": 2,
"builds": [
{
"src": "./index.js",
"use": "#vercel/node"
}
],
"routes": [
{
"src": "/web/(.*)",
"dest": "/"
}
]
}
enter image description here

To put this simply, the adapter-vercel exists, because Vercel mainly works on the front-end aspect and is serverless. socket.io will not work on Vercel mainly because Vercel will freeze your app (including your socket) after it detects an inactivity in the application.
So TLDR; you can't use socket.io on Vercel. You can see more on that here:
https://vercel.com/guides/do-vercel-serverless-functions-support-websocket-connections

Related

Vue + Express +GCloud routing breaks in App Service

I have a Vue3 + Express + Okta app. It works perfectly fine on local, but once I deploy it to Google Cloud's App Service I can only load the main page. Any navigation gives me 404.
I assume I am doing something dumb, but I've tried all I can think about to no avail. Help please?
Here's my router (I removed extra routes):
import { createRouter, createWebHistory } from "vue-router";
import AppHeader from "./layout/AppHeader";
import AppFooter from "./layout/AppFooter";
import Home from "./views/Home.vue";
import ListEpisodes from "./views/ListEpisodes.vue";
import { LoginCallback, navigationGuard } from '#okta/okta-vue';
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/",
name: "home",
components: {
default: Home,
footer: AppFooter,
header: AppHeader
}
},
{
path: "/episodes",
name: "episodes",
components: {
header: AppHeader,
default: ListEpisodes,
footer: AppFooter
}
},
{
path: '/login/callback',
component: LoginCallback
}
]
})
router.beforeEach(navigationGuard);
export default router;
To deploy to GCP, I run npm run build for the frontend, then copy dist/ to my express app's static folder, then "gcloud app deploy".
The routing worked fine in GCP before I moved from vue2 to vue3 to integrate with okta. The extra stuff was history: createWebHistory() and router.beforeEach(navigationGuard);
Any ideas what can that be?
createWebHistory() was originally createWebHistory(process.env.BASE_URL). I thought maybe there's an issue there, so I tried creating .env file with BASE_URL=https://my_domain.
Then I removed the parameter - no difference on local, still didn't work on GCP.
Tried removing nocache from the express app as well, as that was another thing I changed before redeploying from working (vue2 many changes ago) version.
UPD: here's my app.yaml
runtime: nodejs16
service: default
instance_class: F2
Ok, I still don't know what is happening, but I found another way to do this: deploying api and frontend separately and then setting up the dispatch rules to connect Vue app to the backend.
I have used this guide with a few changes: https://medium.com/#rgoyard/how-to-deploy-a-single-page-application-and-its-backend-to-google-app-engine-353ff93bd38c
in vue.config.js for the Vue app remove/comment out the proxy redirecting to your api:
devServer: {
// proxy: {
// '^/api': {
// target: 'http://localhost:3000',
// changeOrigin: true
// },
// }
}
create frontend.yaml in the frontend dir, don't set any handlers:
runtime: nodejs18
service: default
Deploy frontend: gcloud app deploy frontend.yaml
Create api.yaml in the api dir:
runtime: nodejs18
service: api
Deploy api: gcloud app deploy api.yaml
Create dispatch.yaml in the root dir (or anywhere, really):
dispatch:
- url: '*/api/*'
service: api
Deploy dispatch rules: gcloud app deploy dispatch.yaml

Use express.js as middleware for nuxtjs?

I've been following this tutorial that explains how to have an express app in your nuxtjs app, but when I make a postman request to the route defined in the express app, it returns 404 error. Is this tutorial outdated?
Here's my nuxt.config.js:
import { resolve } from 'path'
export default {
ssr: true,
target: 'server',
modules: [
'#nuxtjs/axios'
],
serverMiddleware: [
{ path: '/api', handler: '~/api/index.js' },
],
}
I made an api folder with an api folder with a index.js file in it where you can find a normal express app, I configured my nuxt.config.js file but it seems like the express.js is not running when I run the nuxtjs app. What should I do?

Why nuxt.config.js build.babel is ignored on app start, but work on app update?

My nuxt.config.js file has the following section
build: {
babel: {
presets (_, [_1, _2]) {
return [['#babel/preset-env', {}]]
},
plugins: [
['#babel/plugin-transform-runtime',
{
regenerator: true
}]
]
}
}
If I start my app (yarn dev), this section is ignored, and I've got regeneratorRuntime is not defined error instead of backend answer when I call my REST API (server middleware). But if after that (while server is up and running) I perform some changes in nuxt.config.js (i.e. set regenerator to false and then again to true), app is beeing regenerated and my REST API starts working fine.
yarn generate fails with ERROR ServerMiddleware Error: regeneratorRuntime is not defined
How to make it working always?

How to load multiple apps with vue devServer configuration

Hi i have a app called Home which has installable plugins which i can install at any point of time which runs in iframe
<Home /home/user/mainprojects/index.html> <-- Home app
<Bed iframe /home/user/plugins/bed/index.html> <-- plugins app
<Bed /iframe>
</Home>
with this nginx setup i'm able to load the plugin app(Bed) with after build(which is heavy time consuming)
here is nginx setup for that
location / {
alias /home/user/mainprojects/dist/;
index index.html;
}
location /Bed {
alias /home/user/plugins/bed/dist/;
index index.html index.htm;
}
Question: i don't want to build main app Home app i want to run it through serve, but second app i,e plugin i will always build which will be available as bundle. with above nginx setup after building both(i,e npm run build, bundle) it will work fine. i want to avoid main app build.
here is how my vue.config.js will look like
module.exports = {
devServer:{
proxy:{
'^/appReplacer':{
target: 'http://100.148.1.9:9003/',
changeOrigin:true,
logLevel:'debug',
pathRewrite: {'^/appReplacer':'/'}
}
}
}
}
Still looking for a solution..
Please help me thanks in advance !!
Assuming you are using Vue CLI v4 which is based on Webpack 4
Webpack DevServer is based on Express framework and allows to setup custom Express middleware using devServer.before option
This way you can configure any path to serve virtually anything you want. For example use the static middleware to serve some static files (dist of your plugin in this case)
Note that following code depends heavily on version of Vue CLI in use. Current release version of Vue CLI 4.5.15 is using "webpack-dev-server": "^3.11.0" which uses "express": "^4.17.1"
// vue.config.js
// express should be installed as it is used by webpack-dev-server
const express = require('express');
module.exports = {
//...
devServer: {
before: function(app, server, compiler) {
app.use('/url/to/plugin', express.static('dist/location/of/your/plugin'));
}
}
};

Nuxt static generated page and axios post

I have a Nuxt project. Everything is OK when I generate a static page.
However, I need to send a POST request to the other server.
I tried to use both a proxy in nuxt.config.js and just direct query, but after deploy to the ngnix eventually, nothing works.
Please help.
UPDATE. Steps to reproduce.
Create Nuxt App including axios and proxy
Configure your proxy for other webservice:
proxy: {
'/api': {
target: 'http://example.com:9000',
pathRewrite: {
'^/api': '/',
},
},
changeOrigin: true,
},
call this service somewhere in the code:
const result = await this.$axios.post('/api/email/subscribe', {email: email})
run "yarn dev" and test the service. It works locally properly.
run 'nuxt generate' and deploy the static code hosting service, for example, hosting.com
run your page which calls the above-mentioned service.
As a result, instead of making POST call to the hosting.com/api/email/subscribe, it calls localhost:3000/api/email/subscribe.
Be sure to install the nuxt versions of axios and proxy in your project #nuxt/axios and #nuxtjs/proxy
after that in your nuxt.config.js add axios as module plus this options for axios and proxy:
modules: [
// Doc: https://axios.nuxtjs.org/usage
'#nuxtjs/axios',
//more modules if you need
],
/*
** Axios module configuration
*/
axios: {
proxy: true,
// See https://github.com/nuxt-community/axios-module#options
},
proxy: {
'/api/': {
target: process.env.AXIOS_SERVER, // I use .env files for the variables
pathRewrite: { '^/api/': '' }, //this should be your bug
},
},
now you can use axios in any part of the code like this
const result = await this.$axios.post('/api/email/subscribe', {email: email})
it will internally resolve to AXIOS_SERVER/email/subscribe without cause cors issues.
EXTRA: test enviroments in local using multiples .env files
you can configure .env for dev and .env.prod for production, after that in local you can use yarn build && yarn start for test your app with your production enviroment. You only need add this at the top of your nuxt.config.js file
const fs = require('fs')
const path = require('path')
if (process.env.NODE_ENV === 'production' && fs.existsSync('.env.prod')) {
require('dotenv').config({ path: path.join(__dirname, `.env.prod`) })
} else {
require('dotenv').config()
}
By definition on the Nuxt docs page what nuxt generate does is: Build the application and generate every route as a HTML file (used for static hosting).
Therefore, using proxy is out of question here. Take note that you path is not even being rewritten.
And probably the result you're looking for is not hosting.com/api/email/subscribe (wit /api), but hosting.com/email/subscribe.
Nevertheless, if you use nginx then I don't think you should use Nuxt's proxy option. Nginx is built just for that so point your API calls there and in nginx config file just declare where it should point further.