I have a single page Vue application that uses hash history for the URLs (i.e. https://www.myapp.com/#/sign-up). I have another website that is using Wagtail as a CMS tool that is attempting to link to my vue spa using an anchor tag but it doesn't appear to be working. The website with the anchor tag was built with a pre-made theme using jQuery.
<a class="btn btn-sm btn-primary transition-3d-hover" href="https://www.myapp.com/#/sign-up">
I expect clicking the link will take me to my sign-up page but nothing happens, I see this on the console log when clicking the link:
Uncaught Error: Syntax error, unrecognized expression: #/sign-up
at Function.oe.error (jquery.min.a2530ed98bf8.js:2)
at oe.tokenize (jquery.min.a2530ed98bf8.js:2)
at oe.select (jquery.min.a2530ed98bf8.js:2)
at Function.oe (jquery.min.a2530ed98bf8.js:2)
at Function.e.find (jquery-migrate.min.05689c22f0c8.js:59)
at w.fn.init.find (jquery.min.a2530ed98bf8.js:2)
at e.fn.init.w.fn.init (jquery.min.a2530ed98bf8.js:2)
at new e.fn.init (jquery-migrate.min.05689c22f0c8.js:43)
at w (jquery.min.a2530ed98bf8.js:2)
at HTMLAnchorElement.<anonymous> (scroll-nav.787831ada42e.js:16)
Navigating to the url https://www.myapp.com/#/sign-up does work as expected, just not through clicking the link. I'm relatively new to front-end development and am lost on what could be causing the problem.
I am not that clear about the question and maybe not the best person to answer, but typically you need to configure your server with a URL Rewrite to be able to work with an SPA application, but if that was the issue you wouldn't be able to open that url directly either but you say that you can. So I am not sure what the issue is. I suggest that you take a look at this link also related to configuring the server.
Don't use hashbang navigation as it's deprecated since 2015. Instead use VueRouter to get rid of your hashbang and configure your server-side app to redirect all routes to /, letting Vue handling the routes.
const router = new VueRouter({
mode: 'history'
})
Thanks to Thomas Edwards line of questioning it lead me to the answer:
The website attempting to link to my SPA indeed had some jQuery code on it for autoscrolling behavior where the function was preventing default behavior for all hashed links.
Related
I am not VueJS programmer, but I work with in a company where we developing a VueJS website.
The website have articles. The URL is something like this:
http://example.com/here_is_news_from_sofia.htm
However if you type:
http://example.com/here_is_news_from_blabla.htm
You should go to 404 page.
I inspected several websites and stackoverflow questions, they explain how you should do catch-all router etc, so finally you get a page with "404 Not Found" text on it.
However, in ALL cases, the HTTP code send to the client is not 404, but 200.
With my team, I elaborated this:
When you go to any article, you get something like this:
<html>
<body>
<div id="app">
<app />
</div>
<script src="/js/client.js"></script>
</body>
</html>
Of course, if you click on a link, this page remains and everything is loaded via JS dynamically.
Then lets suppose article is not found.
VueJS will be able to show "404 Not Found" as text, but because HTTP headers are already send (HTML page is already loaded), it will not be able to send 404 code to the client.
For the same reason, VueJS can not send 301 code redirect to the client.
VueJS can incorrectly change the URL in the browser to "http://example.com/404.htm" - this is NOT a correct solution for search engines, since this is purely client-side (in-browser) "trick".
The other think it can do is to execute fancy redirect, as shown here Vue-router redirect on page not found (404) :
Vue.component("page-not-found", {
template: "",
created: function() {
// Redirect outside the app using plain old javascript
window.location.href = "/404.htm";
}
}
This will make the browser to reload the /404.htm page from the server and if the server (Apache / Nginx) is configured correctly, it will send "correct" 404 code to the client.
However I don't think Google and MSN will recognize that http://example.com/here_is_news_from_blabla.htm is a 404 page.
Am I missing anything?
Is there another way VueJS might handle this situation?
How VueJS websites gets indexed from search engines like Google and MSN?
Off topic bonus question - can VueJS generate visible HTML code that contains the article?
If that's a single page application, you can set up dynamic route matching with parameters with vue-router. And dynamically update your meta tags with javascript. I am using quasar vue framework, which handles all of this SEO feature.
I added slug data to the article saved in the database and use it as a route parameter.
https://quasar.dev/vue-composables/use-meta
https://router.vuejs.org/guide/essentials/dynamic-matching.html
You can use quasar vue framework, develop vue app in SSR mode and deploy it to the server.
https://quasar.dev/quasar-cli-vite/developing-ssr/handling-404-and-500-errors
I just deployed my Vue app to my website using GitHub Pages.
The website is successfully hosted at https://astroorbis.com.
Here's the problem; When you click the "links" button at the top of the page, it successfully nagivates you to https://astroorbis.com/links, but when you try visiting the URL itself (typing in https://astroorbis.com/links) into your browser, it returns a 404.
There are other links that have the same error, such as /discord, /github, etc.
I tried the solution at Vue Router, GitHub Pages, and Custom Domain Not Working With Routed Links, but it failed as well.
What would be the solution for this?
As stated in this section of the HTML5 mode
Here comes a problem, though: Since our app is a single page client side app, without a proper server configuration, the users will get a 404 error if they access https://example.com/user/id directly in their browser. Now that's ugly.
Not to worry: To fix the issue, all you need to do is add a simple catch-all fallback route to your server. If the URL doesn't match any static assets, it should serve the same index.html page that your app lives in. Beautiful, again!
So, the solution would be to use something like that
const routes = [
// will match everything and put it under `$route.params.pathMatch`
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
]
On Netlify, you also need to add the following for it to work
/public/_redirects
/* /index.html 200
So I'm not sure about Github Pages but you should have something similar there, some way of catching all routes and sending them to the index.html of your initial SPA page load.
Otherwise maybe just give a try to Netlify with the _redirects configuration.
Maybe this article could help regarding Github pages.
The hack in your given link seems to be the only viable solution but it's still bad for SEO so yeah, depends if you want any (I guess so).
In that case, you could try Nuxt.js, Gridsome or Vitesse if you want to have some statically generated pages (best approach regarding SEO).
Environment: Nuxt.js (Vue/Vuex/Node framework with SSR).
If user encounters an Internal Server Error, I want to use a custom Vue template, similar to the one I'm already using for 404 errors.
By looking at Nuxt source, it looks like the only way is to add a custom 500 page is to override the default .nuxt/views/error.html with my own custom error page.
I don't want just a static HTML page that the user must click out of to re-enter the app, though. I want it to still load the Nuxt app with some preloaded '500 error' state.
In Nuxt docs I don't see how to accomplish this. Any advice?
Things I have tried already:
Redirecting from error.html (doesn't work because of double redirect)
Iframe (works, but don't want to do it this way)
I want remove hashtag(#) from urls, but also i need to save no-reload mode. Can i do that?
I have: page.com/#/home
I want: page.com/home
I tried mode: 'history', but page reloads with it.
UPD: Is it possible to create SPA app without page reloading and with normal URLs?
When activating the history mode, you need to first configure your server according to the documentation. The reason for that is, that the history mode just changes the URL of the current page. When the user actually reloads the page, he'll get a 404 error, because the requested URL is not actually there. Reconfiguring the server to serve always the main index.html of your SPA resolves this issue.
When using a # in the URL (no history mode), the browser tries to navigate to the element with the ID, which was given after the # (within the same document). This was the original behavior of the fragment identifier. Therefore, if you add a link to your HTML with such a fragment identifier, the browser won't reload the page but actually look for the ID inside the document. The vue-router watches this change and routes you to the correct route. This is the reason it works with hashes. If you just add a regular URL to the HTML, the browser's native behavior is to actually navigate to this page (hard-link). This leads to your experienced reload effect.
The way to handle this, is, to never use regular links to route within a Vue Single-Page-Application. Use the tag <router-link> for routing between one page and another (but only within the SPA). This is the way to go, no matter if the browser allows the navigation with # without reloading or not. Here is the documentation for the recommended routing tag: link
You can also route from one route to another programmatically. Use $router.push() for that. Here is the documentation for that: link
I'm getting started with Durandal JS and so far it's working great.
I have an issue though - ALL my links are being intercepted by Durandal's Router (Sammy JS under the hood). How can I get it to leave my links alone?
If there is a Sammy JS-specific alternative to the hashtag as a href to make the browser think it's a link, that'd be awesome too.
Durandal's router.js is an optional component, so if you don't need it you can remove the script tag that loads sammy.js and remove durandal/plugins/router as dependencies in your AMDs.
If you need to partially protect some links from being handled by router then guardRoute http://durandaljs.com/documentation/Router/ is probably your best bet.
This assumes that you're running Durandal 1.2 and not the latest code from github (work in progress), where router.js just got completely rewritten and has no dependency on sammy.js any longer.
I'm using the following in anchor tags href elements:
href="javascript:void(0);"
and it seems to be working.