Svelte Kit Endpoint gives me 404 - api

I made an Svelte Kit its working in my local with no problem but when i build it like this:
import adapter from '#sveltejs/adapter-static';
export default {
kit: {
adapter: adapter({
fallback: 'index.html',
})
}
};
And gives me 3 folders and they are: client, prerendered, server.
I'm uploading this 3 folders in my hosting and move the folder files into root folder. Everythings works with no problem BUT i have an api that sends mail. It's gives me 404? Send mail is working in localhost but not working in hosting. I can't fixed it. In manifest.json:
{
type: 'endpoint',
id: "api/sendMail",
pattern: /^\/api\/sendMail\/?$/,
names: [],
types: [],
load: () => import('./entries/endpoints/api/sendMail/_server.js')
},
The path is correct by the way.
The folders in hosting:
Photo
What can i do?

By specifying a fallback page, this means you're turning SPA mode on, so you can't use server endpoints.
From the adapter-static readme:
You can use adapter-static to create a single-page app or SPA by
specifying a fallback page.
The reason this is working local in dev:
During development, SvelteKit will still attempt to server-side render
your routes. This means accessing things that are only available in
the browser (such as the window object) will result in errors, even
though this would be valid in the output app. To align the behavior of
SvelteKit's dev mode with your SPA, you can add export const ssr =
false to your root +layout.

Related

Catch-all route for production build of Vue Router/Vite-based SPA

I have a Vue3-based SPA using Vue Router and Vite as dev server. The app has three valid URL paths:
/
/first
/second
For production, it will be deployed on Apache under a prefix, i.e. the production URL paths will be:
/prefix
/prefix/first
/prefix/second
What I want to achieve is that clients should be redirected to a valid URL path (e.g. /prefix) of the application even when they initially request an invalid URL path, such as /prefix/invalid.
For this purpose, I've defined the following router.js:
import { createWebHistory, createRouter } from "vue-router";
const routes = [
{
path: "/first",
component: () => import("./components/First.vue")
},
{
path: "/second",
component: () => import("./components/Second.vue")
},
{
path: "/:anything+",
redirect: "/"
},
];
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL), routes});
export default router;
The third route entry defines a catch-all route that will match whenever clients request an invalid URL path. This works fine in development on Vite, i.e. when serving the app via npm run dev -- --base='/prefix/'. Even when the browser initially requests /prefix/invalid, the app's /prefix route is loaded and displayed.
When deploying with npm run build -- --base='/prefix/' for production, however, the catch-all route starts working only after clients have initially requested /prefix or /prefix/index.html and the SPA has been loaded. When they initially request /prefix/invalid or even /prefix/first or /prefix/second, Apache responds with 404 Not Found. This is of course because the whole routing is implemented client-side in JavaScript, so my catch-all route and everything else routing-related will only work once the SPA itself has been loaded and its JavaScript is executing in the browser.
My question is: is there a way to make initial requests for invalid URL paths work in production on Apache like in dev on Vite? I tried adding a file public/.htaccess like this:
ErrorDocument 404 import.meta.env.BASE_URL
But the expression import.meta.env.BASE_URL, which Vite statically replaces with the base config option value in router.js, is not replaced in this file - which is consistent with the documentation of the public directory. Hence this approach doesn't work.
Not sure whether I'm following the right path with .htaccess or whether my business problem has any better -possibly simpler- solution?
The problem can be solved by generating .htaccess dynamically using a simple Vite plugin, which I define inline in vite.config.js for simplicity.
// vite.config.js
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// A private Vite plugin for generating .htaccess dynamically
function generateHtaccess () {
// Resolved Vite configuration, including "base" option
let viteConfig;
return {
name: 'generate-htaccess',
// Rollup Plugin API output generation hook
// See https://rollupjs.org/guide/en/#generatebundle
generateBundle() {
this.emitFile({
type: 'asset',
fileName: '.htaccess',
source: `ErrorDocument 404 ${viteConfig.base}\n`
});
},
// Vite Plugin API specific hook
// See https://vitejs.dev/guide/api-plugin.html#configresolved
configResolved(resolvedConfig) {
viteConfig = resolvedConfig;
},
};
}
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), generateHtaccess()],
});
A non-prefixed production build, such as npx vite build, will hence generate dist/.htaccess with the following content:
ErrorDocument 404 /
while specifying a prefix, e.g. npx vite build --base='/~user/' will generate:
ErrorDocument 404 /~user/
With this .htaccess, clients initially requesting any invalid URL path in production on Apache will be properly redirected to the same catch-all route -the app's root directory- as defined in router.js. This behavior will work consistently for any --base value supplied at build time.

Nuxt static - API call

I'm having trouble dealing with API calls from NUXT static app.
Locally with yarn dev i can get it to work, but when i deploy it (tried with netlify and AWS S3 following this tutorial), i get No 'Access-Control-Allow-Origin' header is present on the requested resource error when calling external API, and the dev tools shows the API call.
But as stated in the official NUXT docs "All calls to APIs will be made and cached in a folder called static inside your generated content so that no calls to your API need to be made on client side navigation.(link)", the API call shouldn't be visible in the dev tools, but i can see it (even in the dev env).
I call the API inside a mixin, just like that:
export const actions = {
async fetchUpcomingGames({ commit }) {
const response = await this.$axios.get('https://api.pandascore.co/matches/upcoming?sort=&page=number=1&size=100&token=MY_TOKEN')
commit('setUpcomingGames', response.data)
}
Build settings on Netlify is like the NUXT docs:
Build command: yarn generate
Publish directory: dist
In nuxt.config i have the settings created by yarn create nuxt-app, wchich is bassicaly:
target: 'static',
modules: [
'#nuxtjs/axios',
],
axios: {
baseURL: '/',
}
It is a simple app with only one layout and one page, not a big deal. What am i missing ?

Why do `/_nuxt/static/... ` page paths appear on Google Analytics? (Nuxt.js + GA4 + vue-gtag)

I'm using Google Analytics (GA4) with a Nuxt.js static site hosted on Netlify. The GA tracking is done with vue-gtag.
It has been working fine for a couple months, but the other day, I noticed an unusually high influx of New User and Session traffic specifically to some of my page paths prefixed with /_nuxt/static/XXXXXXXXXX/... (X denotes some digits). They have "(not set)" Locations, zero Screen Views and zero Average Engagement Times, unlike other legitimate page paths and traffic stats I'm seeing, so I am assuming that they are bots of some sort... but I have no idea where from. Why would particular pages in the static folder get hit like that? And how could they be exposed in the first place?
I'm quite new to all this so I tried researching more about Nuxt static sites, the static folder, and static site generators like Netlify... but I'm not finding anything specifically about these hits showing up on Google Analytics.
I'd appreciate if anyone would be kind enough to explain all this to me!
EDIT - re: kissu's comment on how I've enabled vue-gtag:
I made a Nuxt plugin I've called googleAnalytics.js with the following code:
import Vue from "vue";
import VueGtag from "vue-gtag";
export default ({ app }) => {
// get browser's hostname to check for localhost
let host = window.location.hostname;
// only run the Google Analytics code thru vue-gtag if hostname is not localhost
if (host != "localhost") {
Vue.use(
VueGtag,
{
config: { id: "G-XXXXXXXXXX" },
appName: "SomeName",
pageTrackerScreenviewEnabled: true
},
// pass application router to vue-gtag so that it associates tracking information with the specific page in view
// code from: https://www.carlcassar.com/articles/add-google-analytics-to-a-nuxt-js-app/
app.router
);
}
};
And then in my nuxt.config.js I set it to client-only:
plugins: [
{
src: "./plugins/googleAnalytics.js",
mode: "client"
},
That's all I've done with respect to the GA tracking. Are there are any other config options I should be using?
I'm on Nuxt v2.15.3 and vue-gtag v1.14.0.

Axios GET request resulting in CORS error

I'm working on a VueJS app, and I want to use the Yahoo! Shopping API (documentation: https://developer.yahoo.co.jp/webapi/shopping/shopping/v1/itemsearch.html) to fetch products using their barcode. However, I keep getting a CORS error and I'm not sure why, or what I can do to make it work. My code is as follows:
data() {
return {
appId: 'dj00aiZpPUQ4RTBUUTVSNUs3TyZzPWNvbnN1bWVyc2VjcmV0Jng9NTI-',
apiUrl: 'https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch'
}
}
...
axios.get(this.apiUrl, {
params: {
appid: this.appId,
jan: 4589707054951
}
})
.then((response) => {
console.log(response);
})
.catch((error) => {
alert(error)
})
The specific error I get is this:
Access to XMLHttpRequest at
'https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch?appid=dj00aiZpPUQ4RTBUUTVSNUs3TyZzPWNvbnN1bWVyc2VjcmV0Jng9NTI-&jan=4589707054951'
from origin 'https://0.0.0.0:8080' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
What can I do to make this work? So far the only way it works is using the CORS Chrome extension, but that's naturally just for testing.
Thanks a lot.
The server/api owner needs to send this in his response header:
Or if you have a server settings panel or something, make sure to add the domain from where you are making the request.
Access-Control-Allow-Origin: 'your-domain-here'.
Please read more at: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
I got the same error. I solved it in the following manner.
This error occurs because we are tryign to access the data hosted on a different server. CORS issue is a browser issue where a certain browser does allow you to access the contents hosted on a different or a virtual server. If you observe the app that you are running on is on the local-host (https://0.0.0.0:8080) and trying to access the data hosted on https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch. You can solve this problem simply by adding in a few lines of code in your vue application.
Step 1:
Create a new file called vue.config.js in your root directory of the vue application, that is beside your package.json file. Add the following code in your vue.config.js file:
module.exports = {
devServer:{
proxy: "https://shopping.yahooapis.jp"
}
}
Note: https://shopping.yahooapis.jp would be your base url.
Step 2:
Now, go back to your code in data(). Replace the domain name/base url of the apiUrl with https://0.0.0.0:8080. that is now your apiUrl would be https://0.0.0.0:8080/ShoppingWebService/V1/json/itemSearch.
data() {
return {
appId: 'dj00aiZpPUQ4RTBUUTVSNUs3TyZzPWNvbnN1bWVyc2VjcmV0Jng9NTI-',
apiUrl: 'https://0.0.0.0:8080/ShoppingWebService/V1/json/itemSearch'
}
}
Step 3:
Restart your application. Eg, npm run serve.
I found another solution which worked without creating a proxy server or a mock server. You can disable the security settings for accessing cross origin apis on your web browser.
You can disable the CHROME security settings for accessing apis out of the origin by typing the below command on the terminal:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir="/tmp/chrome_dev_session" --disable-web-security
After running the above command on your terminal, a new chrome window with security settings disabled will open up. Now, run your program (npm run serve / npm run dev) again and this time you will not get any CORS error and would be able to GET request using axios.
Hope this helps!

PWA doesn't load when router is in history mode (Vue CLI 3 based project)

I have a Vue CLI 3 based app which I would like to function as a PWA.
I need it to work in history mode, because the hash intervenes in redirects that I'm doing as part of an OAuth based authentication process.
When the routing is in hash mode, the manages to load fine as PWA. Once I change the mode to 'history', the PWA I installed won't load anymore - I'm getting a white screen instead. I checked the browser version and it still works fine (I configured the fallback in my NGINX server to index.html).
At first I used the default settings provided with vue CLI project and the PWA plugin. After doing some research, I added the following to my vue.config.js:
pwa: {
workboxOptions: {
skipWaiting: true,
navigateFallback: 'index.html'
}
}
and I saw that the following was indeed added to service-worker.js:
workbox.skipWaiting();
...
workbox.routing.registerNavigationRoute("index.html");
but it still didn't help. Even though the app registers successfully on my mobile device's homescreen, it just won't run unless I change the routing back to hash mode.
Does anyone have a clue what I might be missing?
Thanks
I have the same problem, i solved it by adding this in the end of my router.js
{
path: '*', // or '/index.html'
beforeEnter: (to, from, next) => {
next('/')
}
}
Try /index.html instead of index.html.