How can i deploy a Selenium NodeJS web app to Heroku? - node.js

I have created a Selenium NodeJS web app in Local. It uses chromedriver and my driver must use some chrome extensions. Everything is ok in local.
I want to use it in Heroku but I could not do it. I tried it with build packs but but I could not do it again.
How can i deploy it to Heroku ?
package.json (dependencies):
..
"dependencies": {
"body-parser": "*",
"express": "*",
"firebase": "^4.1.5",
"firebase-admin": "^4.2.1",
"selenium-webdriver": "*",
"chromedriver":"*",
"telebot":"*"
},
..

Note: I am using React, Express, and Selenium with chrome
Step 1: Create a new Heroku app.
Step 2: From your terminal, login to heroku using heroku login
step 3: Once you're logged in, cd to your project directory and set it's remote to your heroku app. heroku git:remote -a YOUR-HEROKU-APP-NAME
step 4: Run all the following commands in your terminal
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-chromedriver
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-google-chrome
heroku config:set CHROME_DRIVER_PATH=/app/.chromedriver/bin/chromedriver
heroku config:set CHROME_BINARY_PATH=/app/.apt/opt/google/chrome/chrome
step 5: Login to heroku from your browser and navigate to your app. Go to settings and under buildpacks, add heroku/nodejs
step 6: This is how my index.js looks like. Note: my express entry point is inside root-dir/server/index.js and my react files are inside root-dir/client/
const express = require('express');
const app = express();
const path = require('path');
// Serve static files from the React app.
app.use(express.static(path.join(__dirname, '..', 'client/build')));
app.get('/api', async (req, res) => {
const webdriver = require('selenium-webdriver');
require('chromedriver');
const chrome = require('selenium-webdriver/chrome');
let options = new chrome.Options();
options.setChromeBinaryPath(process.env.CHROME_BINARY_PATH);
let serviceBuilder = new chrome.ServiceBuilder(process.env.CHROME_DRIVER_PATH);
//Don't forget to add these for heroku
options.addArguments("--headless");
options.addArguments("--disable-gpu");
options.addArguments("--no-sandbox");
let driver = new webdriver.Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.setChromeService(serviceBuilder)
.build();
await driver.get('http://www.google.com');
res.send(await driver.getTitle());
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '..', 'client/build/index.html'));
});
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`listening to port ${port} now...`);
});
step 7 (if you are using React): Now inside your package.json in root-dir/, add this
"scripts": {
...
"heroku-postbuild": "cd client && npm install && npm run build"
}
step 8 (if you are using react): inside your package.json in root-dir/client/ (i.e: package.json for react app), add the following line:
"proxy": "http://localhost:5000/",
step 8: (if you're using react): inside root-dir/client/src/, create a new file called setupProxy.js and paste the following code:
const proxy = require("http-proxy-middleware");
module.exports = function(app) {
app.use(proxy('/api', { target: `http://localhost:${process.env.PORT || 5000}/`}));
};
step 9: Now, you are ready for deployment. Make sure you have the following packages installed: express, selenium-webdriver, and chromedriver
step 10: now push it to heroku
git add .
git commit -m "my app"
git push heroku master

you can do the following steps to deploy your application on heroku
1)make an new repository on git
create an account on github and create an new repository
then on command line check the status of your project file using
git status
if they are red mark then add all the file using
git add .
then commit
git commit -m "first commit"
2)push all the data on that repository
git remote add origin https://github.com/git_account/repository_name.git
git push -u origin master
3) then push from git to heroku
git push heroku

Related

How to run electron on a localhost server in Build as well as in Dev

I'm developing with Next.js + Electron + Typescript.
I'm using the npx create-next-app --example with-electron-typescript command to generate code.
npm run dev (the contents are npm run build-electron && electron . ), it seems that the local server is up and running on localhost8000, but when build, the server is not up internally, and it is running by directly accessing the file.
However, some APIs do not work correctly if there is no domain in the location.origin , so it works in Dev, but does not work in Build.
So, if it is possible, I would like to run the server on localhost in the build version as well as in the Dev version.
Is there anything I can do to make it work?
It's not shown in any of the examples, even though someone requested one:
https://github.com/vercel/next.js/issues/28225
It is possible using a custom server:
https://nextjs.org/docs/advanced-features/custom-server
You can follow these steps to create one:
Clone the Electron Next TypeScript example repo:
https://github.com/vercel/next.js/tree/canary/examples/with-electron-typescript
Update ./electron-src/index.ts with the following code:
import isDev from 'electron-is-dev';
import { createServer } from 'http';
import next from 'next';
import { parse } from 'url';
app.on('ready', async () => {
// Use server-side rendering for both dev and production builds
const nextApp = next({
dev: isDev,
dir: app.getAppPath() + '/renderer'
});
const requestHandler = nextApp.getRequestHandler();
// Build the renderer code and watch the files
await nextApp.prepare();
// Create a new native HTTP server (which supports hot code reloading)
createServer((req: any, res: any) => {
const parsedUrl = parse(req.url, true)
requestHandler(req, res, parsedUrl)
}).listen(3000, () => {
console.log('> Ready on http://localhost:3000')
})
mainWindow.loadURL('http://localhost:3000/')
Update ./package.json Electron build configuration to include the renderer src files:
"build": {
"asar": true,
"files": [
"main",
"renderer"
]
}
In ./package.json move next from devDependencies to dependencies. This means it will be available to run in production builds
Then use helpful scripts to unpack the binary and see the files/folder inside:
npx asar extract ./dist/mac/ElectronTypescriptNext.app/Contents/Resources/app.asar ./dist/unpack
Run the unpacked version to debug:
./node_modules/.bin/electron ./dist/unpack
I have created an Express Server version and NextJS versions to prove it is possible:
https://github.com/kmturley/electron-server/tree/feature/express
https://github.com/kmturley/electron-server/tree/feature/next

What is the best way to get a Vue app to correctly read the env variables that have been set on Heroku?

I have a vue app that is being hosted on Heroku. Now, because heroku doesn't do static apps, I wrote a simple express server to serve this app
//server.js
const express = require('express')
const serveStatic = require('serve-static')
const path = require('path')
app = express()
app.use((req, res, next) => {
if (process.env.NODE_ENV === 'production') {
req.headers['x-forwarded-proto'] !== 'https'
? res.redirect(301, 'https://' + req.hostname + req.originalUrl)
: next()
} else {
next()
}
})
app.use(serveStatic(path.join(__dirname, 'dist')))
const port = process.env.PORT || 80
app.listen(port)
And hooked the build process of the app to Heroku existing workflow through package.json
.
.
.
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"postinstall": "if test \"$NODE_ENV\" = \"production\" ; then yarn run build ; fi",
"start": "node server.js"
},
.
.
.
This whole thing works and technically so do the environment variables. However, I see that some env variables that I set on heroku (in their dashboards) yesterday are still undefined when I access them in vue using process.env.VUE_APP_XXX.
In development I use .env and that works as intended. My idea here is that because there's the express server in the middle things don't work as I would have expected.
Is there any way to make this thing work smoothly or am I better off using a static site hosting a-la Netflify?
Using ENV variables in Vue CLI (or Webpack build app in general) is done using Webpack DefinePlugin which replaces the values like process.env.VUE_APP_XXX in your code at build time
So if you define (or change) your variables directly in Heroku dashboard instead of .env file committed to repo, you need to rebuild you app on Heroku to pick up the changes...
If you are using ENV to configure any secrets (API keys etc), don't !! These values will be included directly in JS bundle of your app and easily accessible to anyone...
You can use heroku cli to set your env variables - documentation
$ heroku config:set DATABASE_URI=database_uri_here
$ heroku config:set SESSION_SECRET=session_secret
... and so on for each variable,
OR
if you have the env variables set in your .env file then you can do this as well
heroku config:set $(cat .env | sed '/^$/d; /#[[:print:]]*$/d')

How to deploy React application to Heroku

I have built a single-page weather app with React and Node.js but can't seem to get it to deploy to Heroku. So far, I have:
Created a new app on Heroku called weather-app-react-node
Logged into Heroku on the CLI
Run the command 'heroku git:remote -a weather-app-react-node' in my terminal
Added a Procfile with 'web: npm start' in it
Ran 'git add .', 'git commit -m "Pushed to heroku"', 'git push heroku master'
My terminal tells me it is deployed and waiting but when I click on the link, I get this error message:
SecurityError: Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.
I've tried to google it but can't seem to find anything relevant to my situation. Anyone know how to fix it?
heroku-site: https://weather-app-react-node.herokuapp.com/github: https://github.com/caseycling/weather-app
To deploy the React app to Heroku, I performed the following steps...
1. In your terminal, enter npm -v and node -v to get your npm and node version. In my case, my npm version is 6.14.1 & my node version is 12.13.0.
2. In package.json, add "main": "server.js", and "engines": { "npm": "6.14.1", "node": "12.13.0" }, under the "private" property. In your scripts property, add "heroku-postbuild": "npm install" and set "start" to "node server.js".
3. In the root directory, create a Procfile with one line of text: web: node server.js.
4. In the root directory, create the server.js file with the below code..
const express = require("express");
// eslint-disable-next-line no-unused-vars
// const bodyParser = require('body-parser');
const path = require("path");
const app = express();
const port = process.env.PORT || 8080;
app.use(express.static(path.join(__dirname, "build")));
// This route serves the React app
app.get('/', (req, res) => res.sendFile(path.resolve(__dirname, "build", "index.html")));
app.listen(port, () => console.log(`Server listening on port ${port}`));
5. Enter npm run build in the terminal to produce the build directory. Next, remove (or comment out) /build from .gitignore file (in root directory).
6. Test if server.js works by entering node server.js (or nodemon server.js) in the terminal. If it works, server.js should serve the React app.
7. Commit everything from step 1-6 to GitHub and Heroku repository. To commit to Heroku repository, in your terminal, enter heroku git:remote -a weather-app-react-node and afterward, enter git push heroku master.
You can try logging in to heroku directly and deploy your github repository's desired branch from there directly.
I used create-react-app-buildpack
npm install -g create-react-app
create-react-app my-app
cd my-app
git init
heroku create -b https://github.com/mars/create-react-app-buildpack.git
or
heroku create -b mars/create-react-app
git add .
git commit -m "I am the newborn app"
git push heroku master
heroku open
Note: In my case, buildpack config from CLI did not work, I still had nodejs-build pack, so I manually changed the build pack to mars/create-react-app in the Heroku project dashboard
The best practice to push React apps to Heroku with a node js backend is to use the Heroku Post Build Script, The post build will take care of all the work under the hood
Follow the steps below
Add This below snippet to your package.json under the scripts
scripts{
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix reactFolderName && npm run build --prefix reactFolderName"
}
And add this snippet to your index.js file
app = express()
app.use(express.static('reactFolderName/build'));
app.get('*', (req, res) => res.sendFile(path.resolve(__dirname, 'reactFolderName', 'build', 'index.html')));
After I set up the all the things above mentioned I'm facing this issue.
When I'm using the URL like http://localhost:8080/ & http://localhost:8080/button
Cannot GET /button
In Console
Failed to load resource: the server responded with a status
of 404 (Not Found)
DevTools failed to load source map: Could not load content
for chrome-
extension://gighmmpiobklfepjocnamgkkbiglidom/browser-
polyfill.js.map: System error: net::ERR_FILE_NOT_FOUND

Final Deployment of React Project

I am new to NodeJS and come from Java world, but in last 3 month I have done quite good development.
I use ExpressJS and ReactJSin my first project, Now during development we use 2 http server 1 for ExpressJS back-end application and another for ReactJS front-end application.
Now is this the way we have to deploy on production or we can combine it as 1 application and deploy on 1 http server listening on port 80.
regards
Deploy a production React app to Heroku
1. Create a React App
npm create-react-app heroku-deploy-test
cd heroku-deploy-test
2. Create an Express JS server to serve your production build
//server.js
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(__dirname));
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
const port = process.env.PORT || 8080;
app.listen(port);
In your package.json file, change the start script to the following: start:
"node server.js"
3. Deploy to Heroku
If you don’t already have a Heroku account, create one here: https://signup.heroku.com/
In your command line, run the following: heroku login
You will need to type in your heroku credentials to the terminal. Once you have successfully entered your heroku credentials, run the following in your terminal to create a new deployed app:
heroku create heroku-deploy-test
(Replace heroku-deploy-test with your own app name.)
Then push your app build to heroku with the following git in your terminal:
git init
git add .
git commit -m "initial commit"
heroku git:remote -a heroku-deploy-test
git push heroku master
These commands install your dependencies, initialize git, and connect your repo to the remote repository hosted by Heroku.
Note: if you already initialized your git before running heroku create [app-name], then you don’t need to run heroku git:remote -a [app-name].
run heroku open and your development app will open in your default browser. If you want a production build, I think you already know what to do. - > Create a production build of your React app. Create a proper .gitignore file so only the relevant files will be deployed.
IMPORTANT: If you already had a .gitignore file, make sure that this line isn't in it /build :)
May I also suggest reading this blog! Have a good one!

How do I make Openshift to use Express 4, instead of its installed Express 3?

I developed my Nodejs Express app locally using Express 4 and it works as expected on my computer. I then git the whole app up to Openshift. When I try to run it Openshift returns"503 Service Unavailable". If I ssh into my base Node cartridge and do "express -V" it returns version 3.2.5. I get the same version 3.2.5 if I go into my app folder at app-root/repo and run "express -V".
So clearly my Express 4 which was included in the git upload in my app's node_modules is not being used. What is the solution to use Express 4 as required by my app?
Ideas are- remove Openshift's version of Express 3, force Openshift to use my Express 4 in my app area, upgrade Openshift's Express 3 to Express 4. I cannot figure out how to do any of those and I have researched this.
Here's how to troubleshoot:
ssh into your cartridge
cd into the app-root/repo directory
run grep version ./node_modules/express/package.json
you should see a version based on your package.json dependency
verify your package.json has a scripts section containing a start command that just runs your app with something like node ./server.js (server.js being whatever file you coded your main app start script in). You don't need the express command line program to launch an express server. It's for setting up new project boilerplate and other ancillary tasks.
To see the version of express running within your app, you can add this code to your server.js (or equivalent) file: console.log(require("express/package").version);
Look at this project to know how to integrate openshift with express4
Its a simple example .
https://github.com/master-atul/openshift-express4
try this
rhc ssh
cd app-root/repo
npm start
also edit the ./bin/www
var port = normalizePort(process.env.OPENSHIFT_NODEJS_PORT || '8080');
var ip = process.env.OPENSHIFT_NODEJS_IP;
if (typeof ip === "undefined") {
// Log errors on OpenShift but continue w/ 127.0.0.1 - this
// allows us to run/test the app locally.
console.warn('No OPENSHIFT_NODEJS_IP var, using 127.0.0.1');
ip = "127.0.0.1";
};
//app.set('ip', port);
app.set('port', port);
var server = http.createServer(app);
server.listen(port, ip);
server.on('error', onError);
server.on('listening', onListening);
you can follow step:
copy all content bin/www and replace all content in file server.js:
Change some content at server.js:
from
`var port = normalizePort(process.env.PORT || '3000');`
to
var port = normalizePort(process.env.OPENSHIFT_NODEJS_PORT || '3000');
Add line:
var ip = process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1';
from
server.listen(port);
to
server.listen(port, ip);
Add more to package.json
from
"scripts": {
"start": "node bin/www"
},
to
"scripts": {
"start": "node server.js"
},
Add line:
"main": "server.js",
Use npm install --save module-name for npm install
create file .gitignore with content:
node_modules
on local run node server.js to start server with address localhost:3000
upload to openshift:
git add .
git commit -m "First update new server version"
git push
Browser: domain-appname.rhcloud.com

Resources