ref –
- https://css-tricks.com/deploying-a-client-side-rendered-create-react-app-to-microsoft-azure/
- https://stackoverflow.com/questions/57618453/process-for-react-app-deployment-to-azure-web
- download demo
First we search for “App Services”. Then click on the plus button to create one.
Since I”m on free trial, that is the account I belong to. We give it a name for the group that this app belongs to. Stack should be Node. Region should be East Asia.
Use default on the rest of the options. Review your changes and click create.
Once it finishes creating, you’ll come back to the dashboard with your newly created Web Service. Click on it and you’ll see the web service’s stats. Notice the URL. Click on it to see your default page. This page is actually serviced from your server’s site/wwwroot/hostingstart.html. You can verify this by clicking on the SSH icon on your left, a window pops up and you’re in your server. cd into site/wwwroot and you’ll be able to see it.
Creating React App locally
We create the app and name it azure-react-demo:
npx create-react-app azure-react-demo
We go into the directory and install react-router-dom for routing features:
cd azure-react-demo
npm i react-router-dom
In your directory, you should now see node_modules, public, src ..etc.
Then create pages folder in src.
src/App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import React, { Component } from "react"; import "./App.css"; import Home from "./pages/Home"; import Page1 from "./pages/Page1"; import Page2 from "./pages/Page2"; import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; class App extends Component { render() { return ( <Router> <Switch> <Route exact path="/" component={Home} /> <Route path="/page1" component={Page1} /> <Route path="/page2" component={Page2} /> </Switch> </Router> ); } } export default App; |
src/pages/Home.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import React from "react"; import { Link } from "react-router-dom"; const Home = () => { return ( <div className="flags"> <div className="page page1"> <div className="flagTop" /> <div className="flagCenter"> <h1 className="country">Argentina (PAGE 1)</h1> <Link to="/page1">Click to go to Page 1</Link> </div> <div className="flagBottom" /> </div> <div className="page page2"> <div className="flagTop" /> <div className="flagCenter"> <h1 className="country">Nigeria (PAGE 2)</h1> <Link to="/page2">Click to go to Page 2</Link> </div> <div className="flagBottom" /> </div> </div> ); }; export default Home; |
src/pages/Page1.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// Page1.js import React from "react"; import { Link } from "react-router-dom"; const Page1 = () => { return ( <div className="page page1"> <div className="flagTop" /> <div className="flagCenter"> <h1 className="country">Argentina (PAGE 1)</h1> <div className="otherLinks"> <Link to="/page2">Nigeria</Link> <Link to="/">Home</Link> </div> </div> <div className="flagBottom" /> </div> ); }; export default Page1; |
src/pages/Page2.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import React from "react"; import { Link } from "react-router-dom"; const Page2 = () => { return ( <div className="page page2"> <div className="flagTop" /> <div className="flagCenter"> <h1 className="country">Nigeria (PAGE 2)</h1> <div className="otherLinks"> <Link to="/page1">Argentina</Link> <Link to="/">Home</Link> </div> </div> <div className="flagBottom" /> </div> ); }; export default Page2; |
src/App.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
/* App.css */ html { box-sizing: border-box; } body { margin: 0; } .page { display: grid; grid-template-rows: repeat(3, 1fr); height: 100vh; } .page1 .flagTop, .page1 .flagBottom { background-color: blue; } .page2 .flagTop, .page2 .flagBottom { background-color: green; } .flagCenter { display: flex; align-items: center; flex-direction: column; justify-content: center; text-align: center; } .page a { border: 2px solid currentColor; font-weight: bold; margin: 0 30px; padding: 5px; text-decoration: none; text-transform: uppercase; } .flags { display: flex; width: 100%; } .flags > .page { flex: 1; } |
run npm start and you should see a simple app with pages. We are going to deploy it to Azure.
Deploy to Azure
First go to Deployment Credentials
set up credentials for a user.
Now go to the deployment center and set it up for our local project.
After the third step, Azure generates a local git repo for you. And it gives you a remote link to point your react app to.
something like this: https://YourAppName.scm.azurewebsites.net/YourAppName.git
Create the build folder
Now in our root directory, npm run build
Once the build folder generates, we CD into it:
1 2 3 4 5 |
git init git add . git commit -m "Initial Commit" git remote add azure <git clone url> git push azure master |
Make sure you use the git url like this: https://YourAppName.scm.azurewebsites.net/YourAppName.git
And then put in your username and password when it prompts you.
Startup command
If you are using Windows, you’re ready to go. Because we are using Node, we need to do something that would allow Azure to point to our static website.
Configuration > General Settings > Startup Command:
pm2 serve /home/site/wwwroot –no-daemon –spa
If you use react-router (which we are using) and wants to make any direct access on custom routes be handled by index.html you need to add –spa option on the same command.
then go to your site and it should work. When you click around, all the links should work. In addition, entering URLs in the browser will work also.
IF you do not put in the Startup command, the site will always display the default page. It will not even run your app.
If you put the startup command WITHOUT the –spa, the site will work, but you can’t access other pages through the URL. Every URL page must be accessed through the front page.
Thus, pm2 serve /home/site/wwwroot –no-daemon –spa solves both problems.