Service Worker not registered in Heroku - Angular PWA - node.js

I am trying to deploy an Angular PWA on Heroku, but I can't seem to figure it out.
The deployed app works great, however no service worker is registered according to LightHouse, therefore it is not a PWA.
Here is the process I am using to deploy :
Run ng build --prod in the angular project
Copy the dist/myapp folder next to my server.js file
Commit and push to heroku.
Before pushing, running npm run start or http-server dist/myapp works just fine locally, a service worker is registered and the app is installable.
Here is my start command in package.json and my post-deploy command in ecosystem.config.js:
"start": "pm2-runtime start ecosystem.config.js --env production"
'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production',
Note: It uses node.js and express to load an Angular project using this method : app.use(express.static(path.join(__dirname, 'dist/myapp')));
Does anyone have an idea as to why it does not register a service worker on Heroku ?

Related

Hangs on build using nestjs, pm2

I want to provide uninterrupted service using nestjs, pm2.
I download the changes via git pull origin master command.
After that, save the new changes through the yarn build command.
At this time, the service stops with an error saying dist/main.js cannot be found.
I tried to move the dist folder that was build outside the operating folder using mv, but it stopped and the service started again after entering the reload command.
Below is my code. How can I operate uninterrupted service?
//ecosystem.config.js
name: 'my_api',
script: 'dist/main.js',
watch: '.',
instances: 2,
exec_mode: 'cluster',
wait_ready: true,
listen_timeout: 20000,
kill_timeout: 5000
//package.json
"prebuild": "rimraf dist",
"start": "yarn build && pm2 start ecosystem.config.js",
You need to remove the dist folder before creating the build of the application. Stop the pm2 service and create a fresh build. After creating a fresh build. Restart the pm2 service. It will be fine.
I removed the watch:'.', the service did not stop during build,
and I was able to run it normally through the command pm2 reload myApp.

Why Does My ReactJS App Run Locally But Not In Azure?

I have a ReactJS app that connects to json-server as a fake API.
I have deployed it to Azure using VSCode and the F1 Free Linux tier.
When I run it locally with npm start everything works.
"scripts": {
"start": "npm-run-all --parallel mock web",
"web": "cross-env PORT=8080 react-scripts start",
"mock": "node index.js"
},
The index.js contains the json-server config etc as it is a bit more than json-server --watch db.json
I am using the package npm-run-all to run json-server and the react app at the same time.
This works fine locally but when I try to deploy it to Azure the container fails to start:
INFO - Starting container for site
INFO - docker run -d -p 7307:8080 --name demo_0_8cd -e WEBSITE_SITE_NAME=demo -e WEBSITE_AUTH_ENABLED=False -e WEBSITE_ROLE_INSTANCE_ID=0 -e WEBSITE_HOSTNAME=demo.azurewebsites.net -e WEBSITE_INSTANCE_ID=8fe4512f9f -e HTTP_LOGGING_ENABLED=1 appsvc/node:12-lts_20200918.1
INFO - Initiating warmup request to container demo_0_8cd for site demo
ERROR - Container demo_0_8cd for site demo has exited, failing site start
ERROR - Container demo_0_8cd didn't respond to HTTP pings on port: 8080, failing site start. See container logs for debugging.
INFO - Stopping site demo because it failed during startup.
I can't see much in the container logs to debug this.
I also can't tell what command Azure is using to start since all it says in the logs is docker run.
Is it calling npm start? (see EDIT - tldr: yes)
Why is it working locally but not in Azure?
Why is it not responding to the ping?
Is it something to do with this being a React app instead of "just" a node app?
EDIT:
The docker container that this tutorial generates has scripts in /opt/startup.
The templated one is /opt/startup/init_container.sh and this contains:
STARTUP_COMMAND_PATH="/opt/startup/startup.sh"
STARTUPCOMMAND=$(cat $STARTUP_COMMAND_PATH)
echo "Running $STARTUPCOMMAND"
$STARTUP_COMMAND_PATH
The /opt/startup/startup.sh contains
# Enter the source directory to make sure the script runs where the user expects
cd "/home/site/wwwroot"
npm start
The start script in the package.json for the demo app has "start": "node ./bin/www"
Which then has:
var http = require('http');
var server = http.createServer(app);
server.listen(port);
So the key thing here is that it does npm start to run which then creates a nodejs server to serve the application on port 8080.
The npm start in my application ends up calling react-scripts start, which uses the WebpackDevServer
Whilst you shouldn't use the dev server for production, does that also mean you can't use it on a server for some reason?
This is just a test/demo to familiarise myself with Azure and not production.
The end result is that npm run is running the WebpackDevServer.
This isn't designed for production so we need to have another way of running on Azure.
Changing the Azure webapp Startup command to npx serve -l 8080 build will run the ReactJS application in Azure.
NB: This answer explains how to run it, but not why.
See this other question for why.

how to connect/run sequelize commands on the server?

set up - node js app with seqeulize. locally I run the sequelize db:migrate command. I am planning to deploy the app to heroku. once deployed, how can i run the same commands? is there a CLI ? can I login into to the mysql instance on heroku to run such commands? can this up as a part of the deployment/build process, the code is in github?
You can use the heroku-postbuild script in your package.json to tell Heroku to run a command during deployment:
"heroku-postbuild": "sequelize db:migrate",

Run Angular + Node.js app in production mode Heroku

So I have an Angular and Node.js app that I'm hosting on Heroku. I want to be able to run this app on localhost for testing but also have it work on Heroku. So I decided to use an environment variable to define the URL of the app for API calls.
So in environment.ts I have
export const environment = {
production: false,
apiURL: 'https://localhost:8080/'
};
And in environment.prod.ts I have:
export const environment = {
production: true,
apiURL: 'myHerokuURL'
};
So when I run on heroku I want the production URL to be used. How can I do this?
To run locally I do, nodemon server.js then ng serve.
However on Heroku I need to do something like ng serve --env=prod but not sure how to do it.
These should help
Option 1
If you are using angular-cli, then
ng build --prod
will do the trick. Then you can copy everything from .dist folder to your server folder
Option 2
you can use http-server to serve your app . To install http-server
npm install http-server -g
and after going to your project folder
http-server ./dist
it will serve all the files in your folder. you can check the terminal what ip-address and port you can use to access the application. Now open up your browser and type
ip-adress:port/index.html
Source: how to deploy angular2 app built using angular-cli
Hope it helps.
In your package.json add
"heroku-postbuild": "ng build --configuration=production"
instead of
"postinstall": "ng build --aot --prod"
This will trigger only one (production) build on heroku. If you leave your current setup you can see in your heroku app logs that you first build everything with --prod but then it just makes normal build.

Can't find entry file when deploying node app to heroku

I'm trying to deploy my first node app to heroku. I have set up a Procfile with the following code
web: node ./app/server.js
but when I deploy to heroku and check the logs I see the error Error: Cannot find module '/app/server.js'.
On local it works fine. I have the following in my package.json nested under scripts
"start": "nodemon ./app/server.js
Nodemon is a utility that will monitor for any changes in your source and automatically restart your server. Perfect for development.
While using nodemon its better to maintain script commands for dev and production as follows:
"scripts": {
"start": "node ./app/server.js",
"dev": "nodemon ./app/server.js"
}
To determine how to start your app, The deployment server( Heroku) first looks for a Procfile. If no Procfile exists for a Node.js app, It will attempt to start a default web process via the start script in your package.json.
If you use nodemon in script, It'll internally try to run node server.js but in your case start file present in app/server.js. To avoid these issues it's better to use two separate script commands for dev and production. So that while running locally you can use npm dev command.

Resources