How to set up Express proxy DevServer on a Vue3 Vite App - vue.js

I was following a tutorial on a Full-Stack MEVN app with different folders for the client and server, and when it came time to join both, I notice my from-end is trying to make requests to the server it is running on instead of the express server.
This is my vite.config.js file as followed by the tutorial
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
const path = require('path')
// https://vitejs.dev/config/
export default defineConfig({
alias: {
'#': path.resolve(__dirname, './src'),
},
plugins: [vue()],
devServer: {
proxy: "http://localhost:5001"
}
})
But when I try to use the GET method (that works fine on its own) I get a 404 error on my DevTools because I guess it is trying to perform tasks on the same server instead of my already developed express server.

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

Is it possible to configure Vite to build for use inside Android app (CORS error)

Scenario
I'm using Vue2 with Vue CLI as the bundling tool, now I want to migrate Vue CLI to Vite to enhance the development experience, and the migration process is somewhat successful (thanks to this guide).
Problem
Due to a specific reason, I need to keep the production build accessible statically, without any local server required (the web app should run simply by opening up the index.html file on my machine). And with this, I encounter the problem due to the fact that Vite bundles my code in ESM format that has to be served through some server to resolve CORS policy (error screenshot below). And hence the question: Is it possible to configure Vite to build in plain JS rather than ESM?
Any help is appreciated. Thank you.
Attachments
My vite.config.js as below if it helps:
import path from "path";
import { defineConfig } from "vite";
import { createVuePlugin } from "vite-plugin-vue2";
export default defineConfig({
base: "",
css: {
preprocessorOptions: {
scss: {
additionalData: `
#use "sass:math";
#import "#/scss/utils.scss";`,
},
},
},
plugins: [createVuePlugin()],
resolve: {
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"]
alias: {
"#": path.resolve(__dirname, "./src"),
},
},
});

How to fix the asset file path in my Vue (Vite) application build?

I recently completed a small project in Vue, but when I uploaded it to my server, I am just seeing a blank screen. From my research, I discovered it was likely an issue relating to the asset path as I had it in a sub-directory (https://digitalspaces.dev/portfolio/wil/). After some time trying to fix it by editing the vite.config.js file, I gave up and decided to host it in a subdomain (https://wil.digitalspaces.dev/) instead, where it is now.
The problem is, the index.html now thinks the assets files are at https://digitalspaces.dev/portfolio/wil/assets/, which is true I suppose, but they don't seem to be working from there (nor should they be). Frustratingly, when the build is in https://digitalspaces.dev/assets/, the assets directory is https://digitalspaces.dev/assets/, so it's broken no matter where I have it.
I based my project on the Vue.js quick start guide using vite.
My complete repo is on GitHub, and this is the vite.config.js file:
import { fileURLToPath, URL } from 'url'
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import vueJsx from '#vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
Thanks to anyone who is able to help.
The subdirectory on your site is /portfolio/wii/, so you should configure the base URL to match:
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
⋮
base: '/portfolio/wii/'
})

Web3js fails to import in Vue3 composition api project

I've created a brand new project with npm init vite bar -- --template vue. I've done an npm install web3 and I can see my package-lock.json includes this package. My node_modules directory also includes the web3 modules.
So then I added this line to main.js:
import { createApp } from 'vue'
import App from './App.vue'
import Web3 from 'web3' <-- This line
createApp(App).mount('#app')
And I get the following error:
I don't understand what is going on here. I'm fairly new to using npm so I'm not super sure what to Google. The errors are coming from node_modules/web3/lib/index.js, node_modules/web3-core/lib/index.js, node_modules/web3-core-requestmanager/lib/index.js, and finally node_modules/util/util.js. I suspect it has to do with one of these:
I'm using Vue 3
I'm using Vue 3 Composition API
I'm using Vue 3 Composition API SFC <script setup> tag (but I imported it in main.js so I don't think it is this one)
web3js is in Typescript and my Vue3 project is not configured for Typescript
But as I am fairly new to JavaScript and Vue and Web3 I am not sure how to focus my Googling on this error. My background is Python, Go, Terraform. Basically the back end of the back end. Front end JavaScript is new to me.
How do I go about resolving this issue?
Option 1: Polyfill Node globals/modules
Polyfilling the Node globals and modules enables the web3 import to run in the browser:
Install the ESBuild plugins that polyfill Node globals/modules:
npm i -D #esbuild-plugins/node-globals-polyfill
npm i -D #esbuild-plugins/node-modules-polyfill
Configure optimizeDeps.esbuildOptions to use these ESBuild plugins.
Configure define to replace global with globalThis (the browser equivalent).
import { defineConfig } from 'vite'
import GlobalsPolyfills from '#esbuild-plugins/node-globals-polyfill'
import NodeModulesPolyfills from '#esbuild-plugins/node-modules-polyfill'
export default defineConfig({
⋮
optimizeDeps: {
esbuildOptions: {
2️⃣
plugins: [
NodeModulesPolyfills(),
GlobalsPolyfills({
process: true,
buffer: true,
}),
],
3️⃣
define: {
global: 'globalThis',
},
},
},
})
demo 1
Note: The polyfills add considerable size to the build output.
Option 2: Use pre-bundled script
web3 distributes a bundled script at web3/dist/web3.min.js, which can run in the browser without any configuration (listed as "pure js"). You could configure a resolve.alias to pull in that file:
import { defineConfig } from 'vite'
export default defineConfig({
⋮
resolve: {
alias: {
web3: 'web3/dist/web3.min.js',
},
// or
alias: [
{
find: 'web3',
replacement: 'web3/dist/web3.min.js',
},
],
},
})
demo 2
Note: This option produces 469.4 KiB smaller output than Option 1.
You can avoid the Uncaught ReferenceError: process is not defined error by adding this in your vite config
export default defineConfig({
// ...
define: {
'process.env': process.env
}
})
I found the best solution.
The problem is because you lose window.process variable, and process exists only on node, not the browser.
So you should inject it to browser when the app loads.
Add this line to your app:
window.process = {
...window.process,
};

How to use dotenv in SvelteKit project?

I'm trying to use dotenv.config() in a SvelteKit project.
I can run npm run build successfully. But when I try to start the server (using node build), it throws Error: Dynamic require of "fs" is not supported.
I tried to comment out the dotenv part in src/routes/test.js and build again, and this time the server started without any errors. (I created the project with npm init svelte#next without typescript, and except for the codes here, nothing else is changed)
How should I use dotenv here to load environment variables at runtime?
svelte.config.js
import node from '#sveltejs/adapter-node';
const config = {
kit: {
adapter: node(),
target: '#svelte'
}
};
export default config;
/src/routes/test.js
import dotenv from 'dotenv';
dotenv.config();
export function get() {
return {
body: {
test: process.env.TEST
}
}
}
.env
TEST=123
No need to explicitly load dotenv.
Vite uses dotenv
https://vitejs.dev/guide/env-and-mode.html#env-files
You can access your variable via import.meta.env.VITE_MY_VAR
Important is that your env variables must be prefixed with VITE_ in order to get them exposed. And if you are already running npm run dev, quit it and start again.
That worked for me.
Since a few weeks SvelteKit has a built-in way to handle environment variables:
https://kit.svelte.dev/docs/modules#$env-dynamic-private
I solved the problem with env-cmd (https://www.npmjs.com/package/env-cmd) by adding env-cmd to the beginning of svelte-kit dev, svelte-kit preview and node build.
Also, use process.env['TEST'] instead of process.env.TEST since process.env.TEST is replaced with ({}) by vite. (https://github.com/vitejs/vite/issues/3176)
This is what I did:
vite has a special config option for server port.
// import adapter from '#sveltejs/adapter-static';
import adapter from '#sveltejs/adapter-node';
import preprocess from 'svelte-preprocess';
import path from 'path';
import dotenv from 'dotenv-flow';
dotenv.config();
/** #type {import('#sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess(),
kit: {
// hydrate the <div id="svelte"> element in src/app.html
// target: '#svelte',
/*
adapter: adapter({
// default options are shown
pages: 'build',
assets: 'build',
fallback: 'index.html'
}),
*/
adapter: adapter({
out: './build',
precompress: true
}),
vite: {
resolve: {
alias: {
$components: path.resolve('./src/components'),
$stores: path.resolve('./src/stores'),
$api: path.resolve('./src/api')
}
},
build: {
minify: true
},
server: {
port: process.env.PORT || 3000
}
}
}
};
export default config;
I have .env for defaults (dev etc) and .env.local that is ignored in .gitignore for production (keys, etc).
When .env.local is present it uses that port.
edit: this does not work with node-adapter in production. I think we need to declare PORT some other way. it only works with npm run dev