Confusion about web-application ports - javascript

I have a project that is already deep in development, and there is a problem with the ports.
The Client is SPA written in backbone, that uses Sails as a server.
Problem is in the fact that Client is running in Express on port 80, while Sails is run on 1337.
I would like to host this backbone application within the Sails, not ouside the sails.
A bit more details:
When I fire the Fiddler, I am seeing requests being made to localhost:1337/get/user.
I need it to reside on port 80 as well.
Backbone is written using standard. I have app.js and main.js with all of the common folders (JS, LIBS, CSS). In other words, I have index.html that has data-main using require.js...
I have not problems running the client in separate node.js... how to run it within Sails.js?
Where do I put my index.html???

Trying to serve index.html as a static file won't work. Instead, try the following:
1. Serve your index.html from Sails
Just serve index.html as a combination of views/layout.ejs and views/home/index.ejs, which are mounted to the root / for default newly created Sails project.
2. Set up a catch-all route
In config/routes.js put something like this:
module.exports.routes = {
'/': {
view: 'home/index'
},
'/:unknownRoute': {
view: 'home/index'
}
}
This way you'll be able, for example, to use simple one-level pushstate routing within your SPA: routes like /products or /news will still give you your index.html (if you are using something more complex though, you may want to play a little bit more with your Sails routes).
3. Serve your API with a prefix
In your config/controllers.js put, for example:
module.exports.controllers = {
...
prefix: '/api',
...
}
This will let you serve your API with a prefix and have both /api/products (JSON API) and /products (your SPA) routes available.
4. Use any port you want
You can change the default port via config/local.js, even to 80 (if you don't have anything else running on 80, of course).
In production though, it would probably be a better idea to just proxy to default Sails' or any other port with Nginx, for example.

Related

hybrid SPA with Next js

The problem I'm trying to solve: there is a public part that requires ssr for seo. But there is also an application where seo is not needed and for it to be spa.
I have no experience with next js. So the question is, is it possible to "embed" a spa application in next js.
I will be happy to get any information
react-router-dom does not work with next js because of the hydration process
I would keep the two apps separate since they have different architectures, and it will be simpler that way. Sounds like your SPA may also be secured, which is why it does not need SEO.
A good technique can be be to build both apps to static content, then achieve public URLs like this:
https://www.example.com
https://www.example.com/public
Both built apps could potentially be deployed to a content delivery network. Another common option is to use a reverse proxy such as NGINX or Kong. This configuration uses NGINX to serve the SPA's static content, then routes requests to the Next.js app to a Docker container:
server {
server_name reverseproxy;
listen ssl 443;
location / {
root /usr/share/nginx/html;
index index.html;
}
location /public {
proxy_pass https://nextjsapp:3000/;
}
}

Nuxt SPA without node server

I head to create Nuxt SPA with routing and mb API in future like that:
Backend server (on express or smth else) listen and on request give entire SPA to client.
Now user can use everything on client side (include routing) with no more else requests to backend (mb API requests only)
It means that server should give some .html file with js and css files as SPA and it will work on client side.
I tried to run some commands like nuxt build and nuxt generate
It looks like they return a same result - js files couldn't be found
And index.html file doesn't work properly
After some researching I found a solution
But now I got this:
It can't open the fourth js file in another js file. Path isn't right!
Every time I tried to run it as a static html file and from localhost (and also with using Live Server)
I think I did a lot of crutches and there should be another built-in function or feature that allows us to do what I want
I wrote a lot - if I made a mistake or you didn't get smth - please, ask! I need any help
To test your locally built application, you need to serve all files within the generated /dist folder. You can setup very easily a local web server using Express/Node.js as you already have Node.js installed when running Nuxt. Create a new folder and install express via npm (run npm install express).
Then, copy everything from /dist into /public and create a file server.js:
const express = require('express');
const app = express();
app.use(express.static(__dirname + '/public'));
app.listen(3000);
Run the web server with node server.js and you can access your generated files on http://localhost:3000.

Issue with routing in react app

I have a web app. Back end with node and front end with React. Setup (simplified) goes like this:
index.js (the server)
client
package.json
The client
Now, the client folder contains a front end web application, its contents are basically same as what you get when you type create-react-app.
Inside client there is a build folder which I created by running npm run build from within the client folder.
Server
Now, the index.js from my main folder acts as the node server, inside it I have a line like:
app.use(express.static(__dirname + "/client/build"));
Using this approach I have merged my node server and a client front end application (located inside client folder). You can see I told the server to serve files from the client/build.
All was working fine, till I encountered this.
If I click a react button in my client app which manually calls my router using say:
this.props.router.push('/listmovies');
it correctly shows the page.
But if I type same page in URL address bar and hit ENTER I get error:
Cannot GET /listmovies
The latter error I am pretty sure comes from node server. Because there is no listener for listmovies in index.js (and there should not be). You see basically I think node is intercepting the call and giving me an error. Whereas in my former case where I called router.push I get a correct page.
I hope I managed to explain my problem. Can someone help how to solve this issue?
You have to make the express application redirect all requests to the main React file so react-router can take over. Something like this below the app.use.
app.get('*', function(req, res) {
res.sendFile(__dirname + '/client/build/index.html')
})
This basically handles all wildcards and points it to the index.html. Mind you if you are also implementing API routes on the express app have them above this wildcard statement because otherwise it will intercept them and treat them as client side react-router routes instead of server-side API routes.

Setting up Express with Angular

I can setup Angular in my web app using ASP/Visual Studio rather easily, but I want to get into the Node world, more specifically Express. I'm not truly understanding a basic route handler for Express, that will support the paradigms that Angular has.
For example, when setting up an Express file, there's a million examples, but almost all of them use Jade for templating, and I'm against Jade's syntax and have no desire to utilize it.
So far, I have this for my Express server (I have commented out some questions regarding my decisions made so far):
var express = require('express'),
path = require('path');
var app = express();
var env = process.env.NODE_ENV || 'development';
// 1) Is this really necessary if I'm going to utilize Angular routing for views?
app.set('views', path.join(__dirname, '/app/views'));
app.use(express.static(__dirname + '/public'));
// 2) I'm assuming this is the desired pattern for utilizing Angular.
// A catch-all handler that serves up an html file, which will then
// hand off the rest of the routing to Angular?
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/index.html'));
});
const PORT = 3000;
app.listen(PORT);
console.log('Listening on port: ' + PORT);
The questions I have are:
Is app.set('views', ...) necessary in an Angular app through Express or is it really intended for a Jade/EJS templating workflow? If it's useful to Angular, what path should I point it to? My Angular views? Or just the static html file that will serve as the container to all angular views?
I'm assuming app.use(express.static(...)) is still needed for ensuring Express can serve up public static resources, like css/javascript.
Is an app.get('*', ...) { res.sendFile('path/to/index.html') } route handler the accepted pattern for serving up one html file, which will contain all necessary Angular usage?
For Angular, is it normal to only have one html file for the entire of your application, and then just use Angular's routing and controllers/views to handle the rest?
Is app.set('views', ...) necessary in an Angular app through Express or is it really intended for a Jade/EJS templating workflow? If it's useful to Angular, what path should I point it to? My Angular views? Or just the static html file that will serve as the container to all angular views?
If you need to render a view on the server side and then send it to the client, you need this. Otherwise (in your case) no. You can just send the file to the user or generate a user-specific output based on the parameters that user has sent to the server. It could be anything, HTML file, json or just simple text.
I'm assuming app.use(express.static(...)) is still needed for ensuring Express can serve up public static resources, like css/javascript.
You are right. If you need to serve the static content as well, the best way is to use express.static, however you can catch the requests and serve the content by yourself.
Is an app.get('*', ...) { res.sendFile('path/to/index.html') } route handler the accepted pattern for serving up one html file, which will contain all necessary Angular usage?
If for each and every other requests that the previous routes didn't catch, you need to send the exact same file, yes it is fine.
Remember if you need to serve other HTML files as templates and they are not in the same directory as you pointed in express.static to, the client could not have access to html files. I'll discuss it in a bit.
However, I believe it is a good practice to define all the routes and not just put a * to catch them all. It is better to define a pattern at least, it would be easier to maintain the code later on.
For Angular, is it normal to only have one html file for the entirety of your application, and then just use Angular's routing and controllers/views to handle the rest?
Depends on your application. In most of the cases yes.
I've done several big angular projects, I only have one route that actually serves the main html file, and one that serves static files (pictures, js, css). I also have a route that points to the templates directory which should be served as static contents. Those are the templates that AngularJS need to work with.
For the communication between your angular app and the server, you'll probably need other routes as well. You could create RESTful API end-points to create a communication layer for the client and the server.
I usually have these two lines in the server code to keep the all the templates in the same folder. It makes it easier to manage and define work flows:
app.use(express.static(path.join(__dirname, 'public')));
app.use('/templates', express.static(path.join(__dirname, 'templates')));
For communication between the server and the client:
app.post('/login', function (req, res) {
// deal with login information ...
res.send({
done: true,
errors: []
});
});
app.post('/search', function (req, res) {
// do the search ...
res.send({
done: true,
results: []
});
});
Remember if you use * at some point in your app, the other routes that you defined after that, will never catch the request.
And
I'm against Jade's syntax and have no desire to utilize it.
Yes, me too! But there are other options as well, I personally prefer ejs. If you are using express-generator you can just pass -e switch and it'll create everything compatible with ejs.
$ express -e
Also, take a look at here.

socket.io.js not loading

I know there are a bunch of questions on this already, but none have answered it for me, and plus mine is slightly different.
I'm starting the socket.io server in node using this:
var io = require('socket.io').listen(8000);
My terminal says everything is ok:
info - socket.io started
Now I am trying to load the .js file in my clientside browser using this url:
http://<hostname>:8000/socket.io/socket.io.js
I dont get a 404, it just hangs forever. I've also used a network utility to ping port 8000, and it seems to be open fine.
I installed node and socket.io just yesterday, so they should be the latest versions. Can anyone shed any light on this? Thanks!
Turns out the reason I could never request the .js file was because my company network blocks all ports except the usual ones (80, 21, etc), so `I would never be able to communicate with port 8000.
Use express.js. Place the socket.io file in public/javascripts folder and add this line to your html
<script src="/javascripts/socket.io.js"></script>
I think this is the best way. When you're writing http://<hostname>:8000/socket.io/socket.io.js
node tries to find a folder named socket.io in your project's public folder. And the file socket.io.js in it.
If you don't want to use express.js you should catch the request and try to load a file if no routes were found for your request (what actually express does) because node doesn't know what to do for requests which don't match any routes in your server.
And I recommend to use the socket.io.min.js file (it's smaller and it's in folder node_modules\socket.io\node_modules\socket.io-client\dist)
You have to start an http/https server to access it via http/https. Simply starting an socket.io server won't do. Do the following:
var http = require('http');
var app = http.createServer(),
io = require('socket.io').listen(app);
app.listen(7000, "0.0.0.0");
Then I can access the file http://localhost:7000/socket.io/socket.io.js
sockets.io uses websocket protocol (ws://). See the wikipedia page.
You need to get at least 3 pieces working together.
Serve some HTML (/index.html will do just fine) so there's a web page. This file should contain the socket.io client <script> tag. For this you need the http server portion of the starter examples. You are missing this and that's why browsing to your server just hangs.
Serve the socket.io client. Socket.io will do this for you automatically when you pass in your http server function to it. You don't need full express as this can be done with just node's http module as per the first example on the socket.io docs.
Some javascript to actually do something with the socket. This can be the content of a <script> tag in index.html or a separate file. If it's a separate file, you need to set up your http server to actually serve it.

Categories