Angular 6 PWA with Node not working - node.js

I have a Angular 6 app that works and registers the SW when served with
http-server --port 8080 command as you can see here:
But when I serve the files from my Node / Express application that they are meant to be served. The service worker won't register, tried running the app from localhost and also from Heroku but it's the same. Application works otherwise. Any idea what can cause this?

I think this issue is to do with the path that #angular/cli uses when registering the service worker, I have found registering the service worker in main.ts to be more reliable:
platformBrowserDynamic().bootstrapModule(AppModule).then(() => {
if ('serviceWorker' in navigator && environment.production) {
navigator.serviceWorker.register('ngsw-worker.js');
}
}).catch(err => console.log(err));
Or, looking at this recent comment you can manually modify the path in app.modules.ts
-ServiceWorkerModule.register('./ngsw-worker.js', { enabled: environment.production })
+ServiceWorkerModule.register('.ngsw-worker.js', { enabled: environment.production })

I also had a same issue that worked locally but not herokou, and as a result of various searches on the net, I came to this page.
In my case, I finally solved it by adding --prod to the ng build. With --prod, the settings in environment.prod.ts will be reflected, the "serivice worker" in production in angular.json will be true, also "enabled" -> true in ServiceWorkerModule.register in app.module.ts, and service worker is now working. FYI.

Related

Docker Hostnames not resolving in next.js prod but working in dev mode (Error: getaddrinfo ENOTFOUND)

I'm running a next.js react app in a docker container. It's being composed with several other contains: one running Ghost (I'm using the API), one running mysql, and one running NGINX. I've got everything running in development mode.
It works perfectly when run using next dev. But when I run it by doing next build and next start, I start seeing errors like Error: getaddrinfo ENOTFOUND ghost-api when I try to make server-side HTTP requests to my Ghost API container. I'm not entirely sure what the issue is but it seems like there's some issue with how Node is making requests after being built. I've been digging through a lot of Docker/Node questions trying to figure this one out but haven't had any luck.
The entire project can be found here: https://github.com/MichaelWashburnJr/react-cms
The problem may exist in the environment variable that you are using. In both getGhostApi and getGhostApiKey function, you are using the environment variable.
In NextJs you'll have to specify a next.config.js in which you define the variables that you need for
Ex. next.config.js
module.exports = {
serverRuntimeConfig: {
// Will only be available on the server side
mySecret: 'secret',
secondSecret: process.env.SECOND_SECRET, // Pass through env variables
},
publicRuntimeConfig: {
// Will be available on both server and client
staticFolder: '/static',
},
}
You can also refer to the next documentation for the same.
https://nextjs.org/docs/api-reference/next.config.js/runtime-configuration
I'm not able to reproduce the error. How are you starting the frontend container in prod mode?
From the error it appears like you might be trying to start the frontend container or the frontend app as a separate process without starting it as part of the compose project. If that is the case, the name ghost-api won't be resolvable and you would get the Error: getaddrinfo ENOTFOUND ghost-api error.
I've changed the command key of frontend container as follows:
command: [ "yarn", "start-prod" ]
Changed the "start-prod" script in frontend/package.json as follows:
"start-prod": "next build && NODE_ENV='production' next start"
and everything worked as it worked in dev mode. I got some UNKNOWN_CONTENT_API_KEY error in both dev and prod mode but definitely there is no ghost-api name resolution error.
After cloning your repos:
$ grep -R ST_API *
frontend/.env.development:GHOST_API_URL=http://ghost-api:2368
frontend/.env.production:GHOST_API_URL=http://ghost-api:2368
frontend/src/constants/Config.js:export const getGhostApi = () => process.env.GHOST_API_URL || 'http://localhost:8000';
ghost-api is not a domain name: to make it work you need to edit your hosts file or (for a real production environment) to change http://ghost-api:2368 in frontend/.env.production file with the real deploy domain name.
If you are asking why you can't trust on docker compose networking, the answer is: you can, but only in the containers; while the front end will run in the browser of your application client, which is outside the containers.
Hope this helps.
It seems that Docker's hostname resolution does not work during build time. That is why ghost-api is not found.
Instead of referencing the other container by its name (ghost-api), on Mac you can try host.docker.internal. On Linux, using host networking during build worked for me:
nextjs-app:
build:
network: "host"
# ...
network_mode: "host"
This way, you can reference the other container using localhost.

How to intergrate angular and express

I am learning how to build MEAN apps and I was going through this code: https://github.com/linnovate/mean
In this code I notice that here: https://github.com/linnovate/mean/blob/master/src/app/auth/auth.service.ts (line 18 and some other lines as well) there is no base url. e.g
export class IssueService {
// url of the nodejs server
url = 'http://localhost:4000';
constructor(private http: HttpClient) { }
getIssues() {
return this.http.get(`${this.url}/issues`);
}
//More code....
So my questions are:
How is the angular code functioning without the base url or is it defined somewhere else?
How do you configure angular to know the base without defining it ?
Also in this code, when you run it... you can only access it from one url: localhost 4040... so my question is how is this achieved? How is angular and express integrated to work as one? ....(I am asking this because in other tutorials I have seen that angular has a different port number from express. You then use services to communicate between Angular and express)
Thanks in advance.
"start": "concurrently -c \"yellow.bold,green.bold\" -n \"SERVER,BUILD\" \"nodemon server\" \"ng build --watch\""
See this command in package.json. What happening is, he is first build your angular project and watching for any changes and then serve that build project using express server. So there is no need for angular server.
https://github.com/linnovate/mean/blob/master/server/config/express.js
see line 41 he is serving your angular build project
For question 2: How do you configure angular to know the base without defining it ?
The base url is defined in protracter.conf.js (line 15)

NodeJs React Proxy - Backend Api Request

I am currently running a NodeJs with Express Framework and React as my frontend. When I make my request on the development machine the login (passport-google) works flawless. Since I added https to the production server it does not work anymore in google chrome but it is working in safari and IE.
I believe the request is not getting proxied to the express server.
"proxy": {
"/api/*": {
"target": "http://localhost:3001",
"secure": false
}
Proxy settings in react
This is the auth route
router.get(
"/auth/google",
passport.authenticate("google", {
scope: ["profile", "email"]
})
);
router.get(
"/auth/google/callback",
passport.authenticate("google"),
(req, res) => {
res.redirect("/dashboard");
}
);
Thank you
Not sure how it could work in Safari and IE and not in Chrome, but understand that Create-React-App server does not exist in production.
If you are deploying to Heroku, everything changes. Before you deploy to production in Heroku you have to build your React project. When you build your React project, CRA takes all the JavaScript and CSS files and run Webpack and Babel over all those files and save a final build into a build/ folder.
When the user visits your application on Heroku, you are only running the Node/Express API and it sends the user back to the HTML file and the newly built JavaScript file placed in the build/ folder.
npm run build is what you would run before deploying to production.
So when you move into production, you just need to build the application, commit it, deploy to Heroku and you leave it up to the Express server to serve all the different JavaScript files.
So you only need to worry about the proxy for your development environment because CRA does not exist inside production.
You should be using relative routes in your React application.
The entire idea behind the proxy is to re-route requests from localhost:3000/auth/google to localhost:5000 because you are running the two servers in development so the API request has to be proxied, but when deployed you no longer make use of CRA, CRA only exists to use in development to help us create good quality React applications.
Localhost 3000 and 5000 cease to exist when you deploy to production in Heroku at least.

proxy not working for react and node

I'm having issues with the proxy I set up.
This is my root package.json file:
"scripts": {
"client": "cd client && yarn dev-server",
"server": "nodemon server.js",
"dev": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\""
}
My client package.json file:
"scripts": {
"serve": "live-server public/",
"build": "webpack",
"dev-server": "webpack-dev-server"
},
"proxy": "http://localhost:5000/"
I've set up express on my server side to run on port 5000. Whenever I make a request to the server, ie :
callApi = async () => {
const response = await fetch('/api/hello');
const body = await response.json();
// ... more stuff
}
The request always goes to
Can someone point out what i have to do to fix this issue so that the request actually goes to port 5000?
I experienced this issue quite a few times, and I figured it's because of the cache. To solve the issue, do the following
Edit: #mkoe said that he was able to solve this issue simply by deleting the package-lock.json file, and restarting the app, so give that a try first. If that doesn't resolve it, then do the following.
Stop your React app
Delete package-lock.json file and the node_modules directory by doing rm -r package-lock.json node_modules in the app directory.
Then do npm install in the app directory.
Hopefully this fixed your proxy issue.
The reason the react application is still pointing at localhost:8080 is because of cache. To clear it , follow the steps below.
Delete package-lock.json and node_modules in React app
Turn off React Terminal and npm install all dependencies again on React App
Turn back on React App and the proxy should now be working
This problem has been haunting me for a long time; but if you follow the steps above it should get your React application pointing at the server correctly.
This is how I achieved the proxy calls.
Do not rely on the browser's network tab. Put consoles in your server controllers to really check whether the call is being made or not. For me I was able to see logs at the server-side. My node server is running on 5000 and client is running on 3000.
Network tab -
Server logs -
Check if your server is really running on the same path /api/hello through postman or browser. For me it was /api/user/register and I was trying to hit /api/user
Use cors package to disable cross-origin access issues.
Is your client being loaded from http://localhost:8080?
By default the fetch api, when used without an absolute URL, will mirror the host of the client page (that is, the hostname and port). So calling fetch('/api/hello'); from a page running at http://localhost:8080 will cause the fetch api to infer that you want the request to be made to the absolute url of http://localhost:8080/api/hello.
You will need to specify an absolute URL if you want to change the port like that. In your case that would be fetch('http://localhost:5000/api/hello');, although you probably want to dynamically build it since eventually you won't be running on localhost for production.
For me "proxy" = "http://localhost:5000 did not work because I was listening on 0.0.0.0 changing it to "proxy" = "http://0.0.0.0:5000 did work.
Make sure you put it on package.json in client side (react) instead of on package.json in server-side(node).
This solution worked for me, specially if you're using webpack.
Go to your webpack.config.js > devServer > add the below
proxy: {
      '/api': 'http://localhost:3000/',
},
This should work out.
Read more about webpack devSever proxy: https://webpack.js.org/configuration/dev-server/#devserver-proxy
I have tried to solve this problem by using so many solutions but nothing worked for me. After a lot of research, I have found this solution which is given below that solved my proxy issues and helped me to connect my frontend with my node server. Those steps are,
killed all the terminals so that I can stop frontend and backend servers both.
Installed Cors on My Node server.js file.
npm install cors
And added these lines into server.js file
var cors = require('cors')
app.use(cors())
Into package.json file of frontend or client folder, I added this line,
"proxy" : "http://127.0.0.1:my_servers_port_address_"
Now everything working fine.
Yours might not be the case but I was having a problem because my server was running on localhost 5500 while I proxied it to 5000.
I changed my package.json file to change that to 5500 and used this script:
npm config set proxy http://proxy.company.com:8080
npm config set https-proxy http://proxy.company.com:8080
I am pretty sure just changing it on the package.json worked but I just wanted to let you know what I did.
you should set the proxy address to your backend server, not react client address.
you should restart the client after changing package.json
you should use fetch('/api/...') (instead of fetch('http://localhost:8080/api/'))
Make sure you check your .env variables too if you use them. It's because of that if I was looking for a solution on that page.
I tried all the solutions, proposed here, but it didn't work. Then I found out, that I tried to fetch from root directory (i.e. fetch('/')) and it's not correct for some reason. Using fetch('/something') helped me.
Your backend data or files and react build files should be inside the same server folder.
you must give proxy after the name.{"name":"Project Name", "proxy":"http://localhost:5000"}
port should match with your backend's port.
If you are seeing your static react app HTML page being served rather than 404 for paths you want to proxy, see this related question and answer:
https://stackoverflow.com/a/51051360/345648
(This doesn't answer the original question, but searching Google for that question took me here so maybe this will help others like me.)
In my specific case, I had a both Node backend, and an inner folder with a React project. I tried #Harshit's answer, which didn't work, until I had two package.json files in my project, one in the outer folder, and one in my client (React) folder. I needed to set up the proxy in the inner package.json, and I needed to clear the cache in the inner folder.
I was having this issue for hours, and I'm sure some of the things above could be the cause in some other cases. However, in my case, I am using Vite and I had been trying to add my proxy to the package.json file, whereas it should be added to the vite.config.js file. You can click here to read about it in Vite's docs.
In the end, my code looks like this:
export default defineConfig({
server: {
proxy: {
"/api": {
target: "http://localhost:8000",
secure: false,
},
},
},
plugins: [react()],
});
My problem was actually the "localhost" part in the proxy route. My computer does not recognize "localhost", so I swapped it with http://127.0.0.1:<PORT_HERE> instead of http://localhost:<PORT_HERE>.
Something like this:
app.use('/', proxy(
'http://localhost:3000', // replace this with 'http://127.0.0.1:3000'
{ proxyReqPathResolver: (req) => `http://localhost:3000${req.url}` }
));`
For me, I solved this by just stopping both the servers i.e. frontend and backend, and restarting them back again.
Here is an opinion
Don't use proxies, use fetch directly
not working
fetch("/signup", {
method:"post",
headers:{
"Content-Type":"application/json"
},
body:JSON.stringify(
{
name:"",
email:"",
password:"",
}
)
Actually worked after wasting 6hours
fetch("http://localhost:5000/signup", { // https -> http
// fetch("/signup", {
method:"post",
headers:{
"Content-Type":"application/json" },
body:JSON.stringify(
{
name:"",
email:"",
password:"",
}
)
In my case the problem was that the proxy suddenly stopped to work.
after investigating I found that I've moved the setupProxy from the src folder and that cause the problem.
Moving it back to the src folder have solved the problem.
The problematic structure:
The solution:
faced similar issue. my proxy was not connecting restarting the react app fixed my issue
In my case it was because of typo. I wrote "Content-type": "application/json", (with small t) instead of "Content-Type": "application/json",
you should install this package:
npm install http-proxy-middleware --save
refrense: this link
Make sure your end point match with the backend.

how to start angular2 inside nodeJS application

this seemed easy question now blocked my brain, hope to get your help.
I am now using webpack to start angular2 app, it is fine, just run npm start, in realty, it is running this command to boost angular2 project
webpack-dev-server --inline --progress --port 8080
Now everything is fine until I want to start actual development. Our actual development is using nodeJS, I want to use nodeJS to boost the whole angular2 project. I know I can use npm build to build angular project and then using static page inside nodeJS/express to loda that static page. This is ok for deployment or production enviornment. But for development, how can I do?
As above mentioned, I am using webpack-dev-server to boost ng2 project, which is reading a lot webpack.configuration, such as type script loader, sass loader, by default it is port 8080, but in my nodeJs project, it is using "node app" to start, and port is 3000. Obviously, this has caused cross domain issue here.
So is that possible to let nodeJS to boost my local development environment in ng2 so as to avoid the cross domain issue? If I use nodeJS, then where the webpack solution goes?
Hope to hear your suggestion
You can try two solutions. In both you need to have 2 servers: webpack and yours. Both work for any backend.
Enable CORS on your server responses. This might be tricky. Also, it does not really replicate the production behaviour (folder structure, URL paths, etc.)
Proxy all non-webpack output to your server. This is achieved by a couple of lines in a webpack config but it is really good because you still see your non-angular pages, content, static files etc as you would see them in production. What is also good, you can specify your production (stage, develop, whatever) server as a target and simply have no backend running on your machine at all.
This is how-to:
devServer: {
port: 8080,
proxy: { '**': { target: 'http://localhost:3000', secure: false, headers } }
},
This will start angular server on 8080 and redirect any non-webpack generated file to the target.

Resources