Using Vue£ Vite globalProperties in production? - vue.js

I'm trying to serve my assets through Cloudfront (s3) and so:
I have a env variable that contains the cloudfront URL.
I want to use it globally in my app so I did this:
app.config.globalProperties.$IMAGE_URL = import.meta.env.IMAGE_URL;
app.mount("#app");
It works perfectly in local but when I deploy the app. The views are left blank whenever they have this.$IMAGE_URL on it. With no error message. The issues comes from that, not Cloudfront. What am I missing?

Fixed the issue by using provide and inject to use then
// in main.js
app.provide("IMAGE_URL", import.meta.env.IMAGE_URL);
// in components script setup
import {inject} from 'vue'
const IMAGE_URL = inject("IMAGE_URL");
// in <img>
:src="`${IMAGE_URL}/path/to/asset`"
hope it helps !

Related

Next.js serving static files that are not included in the build or source code

I have files that are not stored in a CDN and would like to serve them with Next.js. These files are not intended to be integrated into Next.js and should not be placed in the public folder. More files will be added and I want to avoid using a custom Next.js server to do simple file serving for images that are not available during building. Additionally, this application will only be deployed locally and using a CDN is overkill for this situation.
Currently, I use Express.js and a Next.js custom server to use express.static to serve files, but this ends up slowing down Next.js and adds lots of unnecessary complexity to my stack. I'd rather just use the Next.js CLI to run my app instead of reinventing the wheel.
Is there a simple way I can serve static files within Next.js and outside the public directory?
I posted this question and my own answer here on StackOverflow because I was unable to find a good tutorial on how to do this. Nearly every google search says to use a custom server or to just put your files in the public folder, which is not what I was looking for. Hopefully, others who are looking for the same thing may find it here.
Disclaimer: I do not use Vercel to publish my applications, and I do not know if this answer will be applicable to Next.js on Vercel.
Next.js allows API routes to be customized to support Node.js HTTP handlers, which means express can also be used within Next.js API routes.
Here is some code to utilize express.static on a Next.js API route.
// pages/api/images/[name].js
// Tell Next.js to pass in Node.js HTTP
export const config = {
api: { externalResolver: true }
}
import express from 'express';
const handler = express();
const serveFiles = express.static('./path/to/files');
handler.use(['/api/images', '/images'], serveFiles);
// ^ ^
// Multiple endpoints are passed. The first one is used when visiting /api/images.
// The second one is used when visiting /images using the middleware rewrite I mention below.
// express is just a function that takes (http.IncomingMessage, http.ServerResponse),
// which Next.js supports when externalResolver is enabled.
export default handler;
However to get around visiting this endpoint via /api/images/filename, you can use Next.js's new middleware to rewrite the request!
// pages/images/_middleware.js
import { NextResponse } from 'next/server';
export function middleware(req) {
// Rewrite /images/... to /api/images/...
return NextResponse.rewrite('/api' + req.nextUrl.pathname);
}
With both these in use, visiting /images/photo.png will internally rewrite to /api/images/photo.png and in turn be handled by express.static, allowing you to serve files outside an API route and without using a custom server!
This code can surely be simplified and get rid of the need of initializing a express.js app just to handle a request, but its incredibly simple to integrate express.js into next.js without using a custom server!
I posted this question and my own answer here on StackOverflow because I was unable to find a good tutorial on how to do this. Nearly every google search says to use a custom server or to just put your files in the public folder, which is not what I was looking for. Hopefully, others who are looking for the same thing may find it here.
The public folder can only serve those files that were included at build time.
But we can do some workaround that can serve files that were not included at build time.
Solution starts here
We can create an api endpoint. For example /api/images-endpoint/[...slug].js
import fs from "fs";
import path from "path";
export default function handler(req, res) {
const imagePath = req.query.slug.join("/");
const filePath = path.resolve(".", `images-directory/${imagePath}`);
const imageBuffer = fs.readFileSync(filePath);
res.setHeader("Content-Type", "image/jpg");
return res.send(imageBuffer);
}
By this, our endpoint will read the image from the image directory and send it as a response.
Benifit/Note: This solution works for images that were added after Next project is build i-e npm run build or next build
Drawback: Using this, We can not build optimized images in Next JS Image component i-e next/image

Get Url Vue js (Router)

i am developing an app in vue js with quasar and i would like to get current url in the index.js of Router folder but i do not know how. the problem is we can not access to window and ever $router to get url.
can anybody help me?
If a file loads before route you can still access all the functions with beforeEach
router.beforeEach(function(to,from,next){
console.log(to,from);
)
}
I did not understand your problems correctly. from is the current route location perhaps you can save it in a const variable.

How to access custom static page in VueJS CLI 3 generated app?

I have created a default Vue CLI 3 project (with vue-router) but beside webapp I'd also like to have few static pages (eg. about, faq, terms etc...) that do not require vue framework or any special javascript logic.
So I've added faq.html in /public folder and I tried to access it via https://localhost:8080/faq but I always get index.html page where vue is taking over and loading my app.
How can I have static html pages in public folder not to be handled by vue-router and instead just delivered to the browser?
You should use History mode.
I think you run it on Windows, if you want to access the router from Pullic you must use History mode,
so your router will look like this
/index.html#/faq
if you run it on your server. the router will works fine without history mode
const router = new VueRouter({
mode: 'history',
routes: [...]
})

How to dynamically change axios's baseURL from Vue's web page?

I'm using axios in a Vue project with Spring Boot. I want to test it on both local and cloud (IBM's cloud foundry).
Now I''m using axios like this: in main.js:
var axios = require('axios')
//axios.defaults.baseURL = 'https://demoproject2.au-syd.mybluemix.net/api'
axios.defaults.baseURL = 'https://demoproject1.au-syd.cf.appdomain.cloud/api'
// axios.defaults.baseURL = 'http://localhost:8090/api'
Vue.prototype.$axios = axios
Every time I upload it to the cloud, I have to change axios' baseURL and rebuild it...
Is there a better way to do this? Can I change the url from the Vue page?
I have searched, and there are some similar questions like this: Vue Axios Dynamic URL But it appears not exactly the question as this...
Assuming you've created this app from Vue CLI v3, you can define environment variables and use those for your various builds.
For example, in your code
axios.defaults.baseURL = process.env.VUE_APP_API_BASE
and in your app directory...
.env
VUE_APP_API_BASE=http://localhost:8090/api
.env.production
VUE_APP_API_BASE=https://demoproject1.au-syd.cf.appdomain.cloud/api

Heroku adding 'undefined' to BASE_URL environment variable

attempting to deploy a vuejs, express app to heroku. The app displays, but cannot access the api, because heroku seems to add 'undefined' in the middle of the base_url. Everything works locally as expected.
Here is my heroku config var:
BASE_URL: https://goore-todos.herokuapp.com/
Here is the Vuejs component api request:
fetchTodo () {
let uri = process.env.BASE_URL + '/api/all';
axios.get(uri).then((response) => {
this.todos = response.data;
});
},
As mentioned, this works locally.
the console shows the following error:
VM71:1 GET https://goore-todos.herokuapp.com/undefined/api/all 404 (Not Found)
and the view is empty.
requests to https://goore-todos.herokuapp.com/api/ via Postman work as expected.
In this case it looks like process.env.BASE_URL is undefined. As it is undefined, the url you're trying to access is considered to be relative. That means it uses your current domain and appends the path to it.
If your frontend and backend are running on the same domain there is no reason to try to pass the API url as a variable as you can just use relative URLs.
If you want to access the URL via an environment variable it is a bit trickier with a frontend app. The Vue app is running on the user's browser, not on your server so you can't directly access it.
I had this problem and had to go through and hard code all of my URLs with the heroku URL. I tried resetting the config variables in Heroku which had an extra slash at the end, but in the end hard-coding each API call was the only thing that fixed it.