I'm new in react world.
So I want to make an website with express + react. My question is, I have to make 2 servers 1 to my cliente-side(react) and another to my server-side(express)?? or I can create just 1 server with both, like express + ejs, blade?
(Sorry for my english)
Thanks,
You could use only one server if you wanted to. Setup your express server to return your react bundle on one url, all your api requests on other dedicated urls (same goes for static content such as images), and fall back to returning your index.html on all other urls.
You can use one server by setting up react to use a proxy.
Read this awesome article. Link
Related
I am currently working on a Sessions Server for a company project.
My problem is, I cant find any help to accomplish, that I can do javascript HTTP calls from a javascript server running with http.createServer() and server.listen(8080, ...) to my Angular Server, which is hosted with ng serve running on localhost:4200.
What I want, respectively need,is something like mentioned below in pseudocode:
In my Angular TypeScript file I need something like:
private listdata = new Array<string>();
ngOnInit(){}
constructor(private http: HttpClient){
this.http.listen(method: "POST", address: "http://localhost:4200/data", callback: => (data){
this.listdata = data;}
)
}
So that my Angular Application (Server) can receive REST calls from another Server.
In my JavaScript file I want to do smth. like:
http.post("localhost:4200/data", data, httpOptions);
So in the end, my javascript server running on localhost:8080 sends data to my angular server running on localhost:4200.
I tried to read me through several sources, containing HttpInterceptors etc. but couldnt find a simple solution for Noobs like me.
Is there an easy way, so that my automatically builded and hosted Angular Server can define routes it listens to and process the data directly for frontend use?
Thanks in advance :)
I think you have to read documentation again
In my opinion or am using like that when calling rest.
2.1 Rest function have to write in httpService.service.ts
2.2 Rest I used to HttpInterceptor to login OAUTH it will check auth guards,
then token expired you check easy way.
3. last question: You asking like roles something, you want to show components different users? yes you can manage routing,
https://www.thirdrocktechkno.com/blog/how-to-integrate-interceptor-in-angular-9/
So I have made a React app that uses Axios to fetch api's. During development, I would have an api call to 127.0.0.1. However, my ReactApp resided on localhost:3000. Therefore, it development, I can't just use:
axios.get('/api/'),
In dev I would need to use:
axios.get('127.0.0.1/api/'),
Anybody have any good ideas on how to resolve this conflict so I can see some data in dev? Kinda tough to design an UI without any data to populate it. Kinda like buying a shirt without trying it on first (which, I never try anything on, so this is a horrible analogy.)
Use it as in the first example. Because it is relative, it will resolve fine for different hosts:
axios.get('/api')
Will automatically resolve to:
// if called by https://example.com/index.js for example
"https://example.com/api"
// if called by localhost/index.js
"https(s)://localhost/api"
In your second example, if you prepend the host and port, you will get duplication!
For example, I just tried your first example on my localhost:3000 and the result is
GET http://localhost:3000/api 404 (Not Found)
Which makes sense because I don't have a /api. But did you notice it appended /api correctly after my host and port?
Now your second example:
GET http://localhost:3000/127.0.0.1/api 404 (Not Found)
It duplicates the host and port. In your case it would be 127.0.0.1:3000/127.0.0.1/api
Just use the first example and it will resolve fine for different hosts (and ports) because it's relative! Did you try it out?
I try to build a multi-tenant SPA using Aurelia where the tenant is given as:
http://myapp.example.org/tenant1
http://myapp.example.org/tenant2
http://myapp.example.org/tenant3
How can I return the same index.html for all of these urls (while being able to extract the tenant in the SPA code for Oauth2 login)?
I have made similar AngularJs solutions but then I used a "trick" by implementing a Asp.net web api that accepted a {tenant} route. Is there a simple "all Javascript" Aurelia way of doing this?
The only way to "redirect" all those pages to index without changing the URL is by doing it in the server, with a URL rewrite. The thing you did in ASP.NET MVC was exactly that.
If you want to do that only with javascript, you'll need to redirect all those pages to index and pass the tenant as a parameter. For example:
location.href = location.host + "/?tenant=" + location.search;
The problem here is: by doing that, you'll really need all those tenant pages phisically, what I suppose it's not what you want.
There is another try: you can also make a default 404 page and then make that redirect from there, but you'll throw an 404 error to the client, what I don't think it's good at all.
So, if you're using IIS or any other server, you should just do a rewrite and everything is gonna be ok.
If you're using NodeJS or .NET you can see how to do it directly from the Aurelia's documentation.
http://aurelia.io/docs.html#configuring-push-state
I currently have a set-up based on the meanjs stack boilerplate where I can have users logged in this state of being 'logged-in' stays as I navigate the URLs of the site. This is due to holding the user object in a Service which becomes globally available.
However this only works if I navigate from my base root, i.e. from '/' and by navigation only within my app.
If I manually enter a URL such as '/page1' it loses the global user object, however if I go to my root homepage and navigate to '/page1' via the site. Then it's fine, it sees the global user object in the Service object.
So I guess this happens due to the full page refresh which loses the global value where is navigating via the site does not do a refresh so you keep all your variables.
Some things to note:
I have enabled HTML5Mode, using prefix of '!'.
I use UI-Router
I use a tag with '/'
I have a re-write rule on express that after loading all my routes, I have one last route that takes all '/*' to and sends back the root index.html file, as that is where the angularjs stuff is.
I'm just wondering what people generally do here? Do they revert the standard cookies and local storage solutions? I'm fairly new to angular so I am guessing there are libraries out there for this.
I just would like to know what the recommended way to deal with this or what the majority do, just so I am aligned in the right way and angular way I suppose.
Update:
If I manually navigate to another URL on my site via the address bar, I lose my user state, however if I manually go back to my root via the address bar, my user state is seen again, so it is not simply about loosing state on window refresh. So it seems it is related to code running on root URL.
I have an express re-write that manually entered URLs (due to HTML5 Location Mode) should return the index.html first as it contains the AngularJs files and then the UI-Route takes over and routes it properly.
So I would have expected that any code on the root would have executed anyway, so it should be similar to navigating via the site or typing in the address bar. I must be missing something about Angular that has this effect.
Update 2
Right so more investigation lead me to this:
<script type="text/javascript">
var user = {{ user | json | safe }};
</script>
Which is a server side code for index.html, I guess this is not run when refreshing the page to a new page via a manual URL.
Using the hash bang mode, it works, which is because with hash bang mode, even I type a URL in the browser, it does not cause a refresh, where as using HTML5 Mode, it does refresh. So right now the solution I can think of is using sessionStorage.
Unless there better alternatives?
Update 3:
It seems the best way to handle this when using HTML5Mode is that you just have to have a re-write on the express server and few other things.
I think you have it right, but you may want to look at all the routes that your app may need and just consider some basic structure (api, user, session, partials etc). It just seems like one of those issues where it's as complicated as you want to let it become.
As far as the best practice you can follow the angular-fullstack-generator or the meanio project.
What you are doing looks closest to the mean.io mostly because they also use the ui-router, although they seem to have kept the hashbang and it looks like of more of an SEO friendly with some independant SPA page(s) capability.
You can probably install it and find the code before I explained it here so -
npm install -g meanio
mean init name
cd [name] && npm install
The angular-fullstack looks like this which is a good example of a more typical routing:
// Server API Routes
app.route('/api/awesomeThings')
.get(api.awesomeThings);
app.route('/api/users')
.post(users.create)
.put(users.changePassword);
app.route('/api/users/me')
.get(users.me);
app.route('/api/users/:id')
.get(users.show);
app.route('/api/session')
.post(session.login)
.delete(session.logout);
// All undefined api routes should return a 404
app.route('/api/*')
.get(function(req, res) {
res.send(404);
});
// All other routes to use Angular routing in app/scripts/app.js
app.route('/partials/*')
.get(index.partials);
app.route('/*')
.get( middleware.setUserCookie, index.index);
The partials are then found with some regex for simplicity and delivered without rendering like:
var path = require('path');
exports.partials = function(req, res) {
var stripped = req.url.split('.')[0];
var requestedView = path.join('./', stripped);
res.render(requestedView, function(err, html) {
if(err) {
console.log("Error rendering partial '" + requestedView + "'\n", err);
res.status(404);
res.send(404);
} else {
res.send(html);
}
});
};
And the index is rendered:
exports.index = function(req, res) {
res.render('index');
};
In the end I did have quite a bit of trouble but managed to get it to work by doing few things that can be broken down in to steps, which apply to those who are using HTML5Mode.
1) After enabling HTML5Mode in Angular, set a re-write on your server so that it sends back your index.html that contains the Angular src js files. Note, this re-write should be at the end after your static files and normal server routes (e.g. after your REST API routes).
2) Make sure that angular routes are not the same as your server routes. So if you have a front-end state /user/account, then do not have a server route /user/account otherwise it will not get called, change your server-side route to something like /api/v1/server/route.
3) For all anchor tags in your front-end that are meant to trigger a direct call to the server without having to go through Angular state/route, make sure you add a 'target=_self'.
I want to allow an authenticated client in Express to access to other web applications that are running on the server, but on different ports.
For example, I have express running on http://myDomain and I have another application running on say port 9000. I want to be able to reach the other app through http://myDomain/proxy/9000.
I had a little bit of success using node-http-proxy, for example:
function(req, res) {
var stripped = req.url.split('/proxy')[1];
var path = stripped.split('/');
var port = path.shift();
var url = path.join('/');
req.url = url;
proxy.web(req, res, {
target: 'http://127.0.0.1:' + port
});
}
However, the big problem is that when the web app makes GET requests, such as for /js/lib.js, it resolves to http://myDomain/js/lib.js, which is problematic because express is not aware of those assets. The correct request would be to http://myDomain/proxy/9000/js/lib.js. How do I route all these additional requests?
What you need to do is to replace URLs in the initial page with the new URL pattern. What is happening is that the initial page that your reverse proxy returns has a reference to:
/js/lib.js or http://myDomain/js/lib.js
so when the browser makes a second request it has the wrong pattern for your reverse proxy.
Based on the incoming request you know what the pattern should look like. In your example it's http://myDomain/proxy/9000. You then fetch the appropriate page from the other server running on http://127.0.0.1:9000/. You do a string replace on any resources in that file. You'll need to experiment with the pattern but you might look for 'script src="/' or 'href="/' and you might find regex helps with the pattern if, for example, the src attribute isn't the first listed in a script tag.
For example you might find 'scr="/' and then you replace it with 'src="/proxy/9000/' that way when the browser asks for that local resource it will come through with the port that you're looking for. This is going to need experimentation and it's a great algorithm to write unit testing around to get perfect.
Once you've done the replacement you just stream that page to the client. res.send() will do this for you.
Something else that you might find useful is that ExpressJS gives you a way to pull out the port number with a little less hassle than you're doing. Take a look at this example:
app.get('/proxy/:port', function(req, res){
console.log('port is ' + req.params.port);
});
I don't think http://myDomain/proxy/9000 is the correct way to do it. Web pages are going to assume the site's domain to be just myDomain and not myDomain/proxy/9000, because that is what the standard says.
Your use case would be better served by using subdomains like 9000.proxy.myDomain.