I set up a very basic Vue.js app essentially using these steps. When I added the router to this project, it asked whether I wanted to use History Mode and I said yes.
Now I am trying to implement the corresponding server configuration changes aka "add[ing] a simple catch-all fallback route to [the] server" but I'm not sure how to do this since I'm using Vercel for my deployments and from my understanding it's managing the server for me.
It seems like I'm able to do some configuration in Vercel, and I'm thinking maybe I need to configure a redirect like in their firebase.json example? If so, would my vercel.json just look like this?
{
"redirects": [
{ "source": "**", "destination": "/index.html" }
]
}
As per Vercel's vercel.json routes upgrade guide, SPA Fallback section, use this on your vercel.json file:
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}
In my case I'm also using Vercel Serverless functions, so I also need rewrites for the /api routes, and here the order is important, it must be done this way:
{
"rewrites": [
{ "source": "/api/(.*)", "destination": "/api" },
{ "source": "/(.*)", "destination": "/index.html" }
]
}
Generally, Vercel automatically detects your configuration and sets it up so that all traffic points at your index.html file. That's kind of their big selling point.
If you want more explicit control, you could use the configuration shown in the Caveat section of the Vue docs you first linked to. Just create a simple component that redirects to the homepage and point * to it.
import NotFound from '../components/NotFound.vue'
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '*', component: NotFound }
]
})
export default {
name: 'NotFound',
template: `<div></div>`,
mounted() {
this.$router.push({ path: '/' })
}
}
You are right, Vercel manages the server for you and you can configure vercel through a vercel.json file. In that vercel.json file you can define rewrite rules as you already assumed. The correct format for this is shown here in the docs of vercel.
Since you want to add a match all rule which directs to the base of your path, adding the following to your vercel.json should work:
{
"rewrites": [{ "source": "/:path*", "destination": "/index.html" }]
}
Explanatory extras:
The :path basically symbolizes a placeholder and the * makes sure it doesn't just match one subpath deep but everything that follows after the initial slash.
For example without the * after /:path you would match domain.xyz/foo but not domain.xyz/foo/bar.
Furthermore since it's a named placeholder you can reuse the matched path for the destination like so "destination": "/index.html/:path".
Which shouldn't be necessary for a frontend application like vue which uses the route inside the browser, but could be helpful for serverless functions.
Related
I am building a project using NextJs and Vercel, but, when the users try to access a new page or route, the Vercel gives them the 404 error.
In other projects, I used Netlify as router and this error was fixed using the netlify.toml config file, but, I am not able to do the same using the vercel.json file.
Can you guys help me to turn this file:
netlify.toml
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Into a vercel.json config file?
I was trying with this settings:
vercel.json
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html"}]
}
But it did not solved my issue.
A workaround is to use a catch all route that immediately redirects to the index page. For example:
// [...404].jsx
export default function Page() {
return null;
}
export function getServerSideProps() {
return {
redirect: {
destination: '/',
permanent: false,
},
};
}
Here's my svelte.config.js and I'm using adapter-static :
const config = {
kit: {
adapter: adapter({
// default options are shown
pages: '../backend/build',
assets: '../backend/build',
fallback: null,
precompress: false,
}),
alias: {},
appDir: '_app',
browser: {
hydrate: true,
router: true,
},
files: {
assets: 'static',
hooks: 'src/hooks',
lib: 'src/lib',
params: 'src/params',
routes: 'src/routes',
serviceWorker: 'src/service-worker',
template: 'src/app.html',
},
floc: false,
methodOverride: {
parameter: '_method',
allowed: [],
},
paths: {
assets: '',
base: '',
},
trailingSlash: 'always',
vite: {
server: {
proxy: {
'/api': 'http://localhost:5555',
},
},
},
},
preprocess: null,};
From the backend (Go lang) I'm serving build directory & index.html file. The homepage works fine but whenever I click on any route, it sends get request to the server instead of redirecting in the app itself.
Here's the go code to serve from backend:
router := gin.Default()
router.StaticFile("/", "./build/index.html")
router.StaticFS("/_app", http.Dir("build/_app"))
I have also tried with the following code:
router.NoRoute(func(c *gin.Context) {
path := c.Request.URL.Path
c.File("./build/index.html")
})
Note: Things work fine when I run npm run preview.
The adapter-static has two distinct modes of operation: SPA and prerendering. When there are several routes, both the npm run dev and npm run preview works as intended, but once built, the static routing falls to the web server, in your case, the Go framework, but the same happens with any other static server (I have tested also Nginx and Apache).
I found a workaround to avoid converting the site to a SPA: Installing a url rewrite mechanism as a middleware in order to add the .html extension that the static server is expecting in the compiled site. In my case, I used Go Fiber github.com/gofiber/rewrite/v2 and it worked as intended (the same behavior as when using npm run dev)
For Nginx static server the solution is the same url rewrite and it could be used as explained here: https://www.codesmite.com/article/clean-url-rewrites-using-nginx
The homepage works fine but whenever I click on any route, it sends get request to the server instead of redirecting in the app itself
SvelteKit users internal router, or $app/navigator for links only if it detects a link to be the same domain as the current page. Likely your web server is misconfigured and there is a mismatch of domain somewhere in
The web browser address bar
Web server configuration
However, the question do not contain these details and is thus unanswerable "why" and how to fix it.
I have some static data which will never change, like the data behind menu items
{
"menuItems": [{
"name": "Shows",
"route": "shows"
}, {
"name": "Podcasts",
"route": "podcasts"
}]
}
i created a json file in /dist folder and in the application route i'm creating a model from the file like
export default Route.extend({
model() {
return $.getJSON('/static/model.json')
}
});
is there a better practice to initialize model with static data?
As already was said in other answer, you are not supposed to edit files in dist/ folder.
You can do the following:
Create a new folder under app/. Let's say app/constants/
In that folder create new file menu.js:
export default {
"menuItems": [{
"name": "Shows",
"route": "shows"
}, {
"name": "Podcasts",
"route": "podcasts"
}]
};
In any other file import it as import menu from 'project-name/constants/menu';. And I don't think you need a model for this, you can just use what you export.
You really shouldn't be editing the dist/ folder - that's where Ember sticks compiled code.
If your static data is only used in a single place, it would be more direct to put it where it's used as a const. In this specific case, that's UI code, and probably belongs in the controller.
The model hook is best for loading data that potentially changes each time you hit that route - probably from a back end.
You can install ember-cli-json-module and then, any JSON files in either app or tests will be converted to ES6 modules that you can import like so:
import myFixture from 'my-app/tests/fixtures/my-fixture';
I would like to add "/app" as my base path for all routes in react routes. So I am trying -
.... more routes
I am unable to make webpack dev server serve pages with URL localhost:8080/app. It gives me a "Cannot get /app" error. If I try localhost:8080/ - it gives me an error that it cannot match a route with "/".
What should be a basic webpack dev server configuration for this scenario?
The Webpack historyApiFallback config option is what you're looking for. Just set that to true and all requests that don't route to an asset will be rewritten to /. You can also pass in an object with custom rewrites:
historyApiFallback: {
rewrites: [
{ from: /^\/$/, to: '/views/landing.html' },
{ from: /^\/subpage/, to: '/views/subpage.html' },
{ from: /./, to: '/views/404.html' }
]
}
(Example taken from the documentation page linked above.)
I'm having difficulties implementing a simple query on a AWS Lambda NodeJS (with Serverless Framework). Running it locally works, but when I upload it to AWS and then try to run it using the API Gateway endpoint, I get this error:
{
"code": "PROTOCOL_INCORRECT_PACKET_SEQUENCE",
"fatal": true
}
I can't find any information on Google, StackOverflow or GitHub about this error, and I can't figure out what I'm doing wrong.
This is what I'm trying.
var mysql = require('mysql');
var connection = mysql.createConnection({
host : '',
user : '',
password : '',
database : ''
});
function getLists (client_id,api_key,callback){
connection.query("SELECT * FROM list WHERE client_id = ?",
[client_id],function(error, results){
connection.end();
callback(error,results);
}
)};
module.exports.run = function(event, context, cb) {
getLists(event.x_mail_list_client_id,'',function(error,results){
if(error){
return cb(null,error);
}
return cb(null,results);
});
};
In general the problem you encounter is the disability of the serverless-optimizer-plugin to handle dynamically loaded NPM modules or globals correctly (e.g. when using the mysql NPM package). So you have to exclude it from optimization.
The solution heavily depends on the serverless version and the Node version you use, so I will list the different solutions below:
Severless v4 + Node v4:
Set the excludes in your s-component.json as follows:
"custom": {
"optimize": {
"exclude": [
"aws-sdk",
"mysql"
],
"includePaths": [
"node_modules/mysql"
]
}
}
Serverless v5 + Node v4:
Components have been obsoleted and removed in this serverless version favoring functions instead. So apply the optimizer configuration directly to your s-function.json configuration files.
Node v5:
The NPM executable included with Node v5 internally does dependency optimization and dependency module flattening. This is not yet really compatible with the current serverless-optimizer-plugin. The solution here is to add the dependencies that are already optimized by NPM as proposed by #Masatsugu Hosoi in his answer above like this
"custom": {
"optimize": {
"exclude": [
"aws-sdk",
"mysql"
],
"includePaths": [
"node_modules/mysql",
"node_modules/bignumber.js",
"node_modules/readable-stream",
"node_modules/isarray",
"node_modules/core-util-is",
"node_modules/inherits",
"node_modules/string_decoder"
]
}
}
edit awsm.json.
"exclude": [
"aws-sdk",
"mysql"
],
"includePaths": [
"node_modules/mysql",
"node_modules/bignumber.js",
"node_modules/readable-stream",
"node_modules/isarray",
"node_modules/core-util-is",
"node_modules/inherits",
"node_modules/string_decoder"
]
https://github.com/felixge/node-mysql/issues/1249
For any coming in the future
what worked for me to add the following in the webpack.config.js file
optimization: {
minimize: false
}
Mysql does not seem to like the minification
I just had this exactly same problem.
The problem is with the browserify and the mysql module. Unfortunately I couldn't find a real solution.
By reading the code the browserify is the only available option as builder.
https://github.com/jaws-framework/JAWS/blob/master/lib/commands/deploy_lambda.js
You can set the 'builder' as false. This will simply zip all your files before sending them to Amazon.
Unfortunately (again) just doing this will not work. For some reason all files are inside a 'node_module' folder to work you must take the files out before upload the package.
Still, all this is manual...
edit: There is already an open issue about this last part:
https://github.com/jaws-framework/JAWS/issues/239