How to deploy a NextJs SSR React app on Azure - reactjs

I have been trying to deploy a Server-side rendered react app I built with NextJS on Azure. I set up the Azure pipeline and release successfully but after running it the app doesn't seem to load up when I went to the azure website URL. The build file content is different from a client rendered app. Please share a resource or explanation about deploying SSR React apps (on Azure).
I used this resource to set up the pipeline and I encountered no error but the URL is still not loading the app.

As mentioned by #James in the comment in Doris's answer, using a custom server.js in a Next.js app would make it slower in production because the routes aren't pre-built. Using next build followed by next start would solve this issue. But for you to be able to do that, you should not have a server.js.
And as per Microsoft documentation for deploying Node JS / Next JS application on Azure Linux web app, the recommended way is to use PM2 rather than using npm start (or) node server.js.
So you don't need server.js or web.config. All you need to do is to have a file called ecosystem.config.js with the below content
module.exports = {
apps: [
{
name: "my-nextJs-site",
script: "./node_modules/next/dist/bin/next",
args: "start -p " + (process.env.PORT || 3000),
watch: false,
autorestart: true,
},
],
};
and have the startup command for your Azure app to be this
pm2 --no-daemon start /home/site/wwwroot/ecosystem.config.js
and no change in your package.json scripts
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
Azure Windows App Service
pm2 is not available in Azure Windows Service - it uses IIS Server. Check out the following answer and its linked questions.
Other useful resources:
Deploying a Node.js application on Windows IIS using a reverse proxy
Deploying Nextjs on IIS server without custom server
Deploying Nextjs on Digital Ocean - App Platform

You need two file: server.js and web.config, and modify package.json like below. I've answered a question about deploy nextjs app step by step, you could have a look at this.
package.json modify.
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "node server.js"
server.js (create this file with the code below:)
const { createServer } = require('http')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
createServer((req, res) => {
const parsedUrl = new URL(req.url, 'http://w.w')
const { pathname, query } = parsedUrl
if (pathname === '/a') {
app.render(req, res, '/a', query)
} else if (pathname === '/b') {
app.render(req, res, '/b', query)
} else {
handle(req, res, parsedUrl)
}
}).listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
web.config (create this file with the code below:)
<?xml version="1.0" encoding="utf-8"?>
<!--
This configuration file is required if iisnode is used to run node processes behind
IIS or IIS Express. For more information, visit:
https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
-->
<configuration>
<system.webServer>
<!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
<webSocket enabled="false" />
<handlers>
<!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
<add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- Do not interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<!-- All other URLs are mapped to the node.js site entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
<!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<!-- Make sure error responses are left untouched -->
<httpErrors existingResponse="PassThrough" />
<!--
You can control how Node is hosted within IIS using the following options:
* watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
* node_env: will be propagated to node as NODE_ENV environment variable
* debuggingEnabled - controls whether the built-in debugger is enabled
See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
-->
<!--<iisnode watchedFiles="web.config;*.js"/>-->
</system.webServer>
</configuration>

Related

Adding Web API as Application to Website in IIS, where does Frontend point to?

I have two separate processes running for my website. The frontend is reactjs and the backend is asp.net core 6.
I have a reactjs website running on localhost:9000 on IIS on a server.
I've added the .net web api published files to the above website as an application with it's own application pool.
In the .env REACT_APP_API_URL: I don't know how to point to the API, before i just used localhost:5000, how do I change this to use the application url?
Tried: */api/controllername, localhost/api/controllername, IPADDRESS/api/controllername,
COMPUTERNAME/api/controllername etc.
Here is the Program.cs
using api;
using api.Services;
using Microsoft.AspNetCore.Authentication.Cookies;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseIIS();
builder.Services.Configure<IISServerOptions>(options =>
{
options.AutomaticAuthentication = false;
});
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowOrigin",
options =>
{
options.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.Name = "Project.Cookies";
options.ExpireTimeSpan = TimeSpan.FromHours(12);
options.SlidingExpiration = true;
options.LoginPath = "/User/Login";
options.LogoutPath = "/User/Logout";
options.Cookie.IsEssential = true;
});
builder.Services.AddDbContext<DbDataContext>();
builder.Services.AddScoped<IProjectService, ProjectService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment() || app.Environment.IsProduction())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Here is the web.config for the backend:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\api.dll" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>
</location>
</configuration>
<!--ProjectGuid: -->
And here is the web.config for the reactjs frontend:
<?xml version="1.0"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="React Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I'm in over my head on how to get these talking to each other.
I can run the dotnet from the commandline and have reactjs talk to that localhost on the server (this wont work when connecting to the website from outside the server). But I need these working in IIS.
Any help would be greatly appreciated.
The front end and the backend application should use same port. In your react project, you should use something like const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href'); or process.env.PORT. And your frontend will start with port which you create the main website. You can find it like below.
The main application and virtual application host in same site with different application. And they also should use same port. You can check my test result.
And you can open the frontend application by clicking the Browse *:8031 in the right panel in my picture.
You can access your api application via https://localhost:8031/api/{apiname or controller/action}.
In your case, it should be http://localhost:port/{hidden by red pen}api/controllername.

.NET Core 5 WebApi How to include React app

I have developed .NET5 web api and React app in two different projects.
Now it's time to deploy API and React app to IIS, but on trying to achieve that I realized that they have to be added as same app in IIS.
I wish that routing setup would be:
/ => React App
/api/v1/controller/method => API endpoints
Both of my apps individually has this setup, I just cannot merge them :/
I cannot find examples where dotnet template isn't used. So far I have tried to accomplish that through this code (I have skipped non related configurations code):
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp";
});
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
I have managed to solve it by adding these lines:
in ConfigureServices
if (HostingEnvironment.IsProduction())
{
services.AddSpaStaticFiles(configuration =>
configuration.RootPath ="ClientApp");
}
in Configure
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
if (env.IsProduction())
{
app.UseSpaStaticFiles();
app.UseSpa(spa =>
{
spa.Options.DefaultPage = "/index.html";
});
I have achieved in .NET 6 this by:
1 - Copying the production build of my React app to the Web API wwwroot folder, using a postbuild step in package.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"postbuild": "move build ../YourWebAPIProject/wwwroot",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
2 - Updated the program.cs in the Web API project to contain the following
app.UseRouting();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(config =>
{
config.MapControllers();
config.MapFallbackToController("Index", "Fallback");
});
3 - Add a fallback controller to handle the react routes
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace YourNameSpace
{
[AllowAnonymous]
public class FallbackController : Controller
{
public IActionResult Index()
{
return PhysicalFile(
Path.Combine(
Directory.GetCurrentDirectory(), "wwwroot", "index.html"),
"text/HTML");
}
}
}
This approach allows both WebAPI and React routes to work, served from the WebAPI project.
Hope this is useful to someone

React and express communication with HTTPS enabled

I'm trying to finalize an HTTPS connection for a production server I'm building but am running into issues with HTTPS.
I've tried a few guides on how to set it up individually for both react and node but cannot seem to get the connection completed.
Here's a simplified version of my server.js file for express:
const https = require('https');
const helmet = require('helmet');
const server = express();
server.use(helmet);
https.createServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.cert')
}, server)
.listen(port, () => console.log(`Listening on port ${port}`));
And my frontend build path in my package.json:
"scripts": {
"start": "set HTTPS=true && react-scripts start"
}
But when I go to https://localhost:3000 I get the following from the console and the screen is only white
Failed to load resource: net::ERR_EMPTY_RESPONSE index.js:1437
TypeError: Failed to fetch
Any thoughts on what I'm doing wrong? Thanks in advance for your time and for any help you can provide.

How can I use firebase's firestore/admin sdk with next.js

I am building an application with firebase and next.js
I am fairly new to this set up, completely new to SSR, and the firebase docs are confusing me.
Currently, I am using firebase functions to run next.js, and that works like a charm. But now, I want to use firestore. I see two ways to use it in my project according to the docs (if I get it right). The first one is the 'web' solution which would not be benificial for me, because I believe it is not SSR, while the whole point of my app is being just that.
The other one is the 'node.js' solution, which runs on the firebase functions, this makes a lot more sense to me. The part I can't figure out, is using it with Next.js
In my current set up I am building my next.js application to the functions folder, inside the function folder I can reference the databaseref object I create with the 'node.js' solution, but how can I reference this before building my next application? So when I'm not in the functions folder?
Setup:
- src
- utils
- pages
- index.js
- signin.js
- // etc.
- functions
- next // this is the output folder of my 'src' build
- index.js
- // etc.
inside functions/index.js I could do:
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
let db = admin.firestore();
and use db to read and add to firestore, serverside (right?)
but all my code is in src/ before I build it and I don't think I could use it there. Should I structure my project differently? Or what should I do to be able to use db? Or, of course, another way to have a server side connection with my firestore.
Sorry for the bad answer. It's my first time. I was looking for cookie cuter code and seen that uor question wasn't answered.
I don't know the proper jargon. Yet, you have t run your app wit a custom server. Atleast that's wjhat I do to use firebase-admin. Notice here my answer is bad becase I acyually interfcae wit my client through socket.io. I only use firebase for client code and authentication
In package.json you are adding the script tag to stratfrom the command line
{
"scripts:
"server": "node server.js"
}
that makes it so you can run
$ npm run server
from the command line
~/package.json
{
"name": "app",
"version": "0.1.0",
"private": true,
"scripts": {
"server": "node server.js",
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "9.3.1",
"react": "16.13.1",
"react-dom": "16.13.1"
}
}
In the server.js fil you load up express for a server side rendering, probably can start your own http server with another post. However, as seen below I actullay use socket.io so it has that connection details
the key is right here thogh
he nextHandler() passes the control of the server to the next. So you can probably start an http server and use nextHandler()
app.get('*', (req, res) => {
return nextHandler(req, res)
})
~/server.js
const fs = require('fs');
const express = require('express');
const app = express();
const server = require('http').Server(app)
const firebaseAdmin = require('./services/dwf.firebase.admin.js');
const secureServer = require('https').createServer({
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem')
}, app)
const io = require('socket.io')(secureServer, {secure: true})
const User = require('../../users/user.manager.js');
let user = User(io,firebaseAdmin.auth(),firebaseAdmin.database());
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const nextApp = next({dev})
const nextHandler = nextApp.getRequestHandler()
// socket.io server
io.on('connection', socket => {
console.log(`Main Socket Opened by:\n ${socket.id}`);
socket.on('getDb',function(userId,refs,fn){
console.log("Getting Data")
firebaseAdmin.database().ref(refs).once('value',(snapshot)=>{
console.log(snapshot.val());
fn({body: snapshot.val()})
socket.emit('getDb',snapshot.val());
});
})
socket.on('disconnect', () => {
console.log(`Main Socket Closed by:\n ${socket.id}`);
});
})
nextApp
.prepare()
.then(() => {
app.get('/data/messages', (req, res) => {
res.json(messages)
})
app.get('*', (req, res) => {
return nextHandler(req, res)
})
secureServer.listen(PORT, () => console.log('#> Main Server ready for clients on https://0.0.0.0:PORT'));
})

My react project not working after deploy to firebase hosting

I'm following the instruction of this site and I'm already trying with an empty create-react-app project and It's working fine
But when I'm trying with my existing project after deploy process was done It said
Firebase Hosting Setup Complete
You're seeing this because you've successfully setup Firebase Hosting. Now it's time to go build something extraordinary!
So I'm pretty curious what I missing
here's package.json
{
"name": "iplace",
"version": "0.1.0",
"private": false,
"dependencies": {
"node-sass": "^4.10.0",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-router": "^4.3.1",
"react-router-dom": "^4.3.1",
"react-scripts": "2.1.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
firebase.json
{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
I already execute firebase init (change public-> build) > npm run build > firebase deploy
Here's project structure
And here's index.html file (I'm pretty wonder why index.html still have welcome to firebase wording...)
<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Welcome to Firebase Hosting</title><script defer="defer" src="/__/firebase/5.7.0/firebase-app.js"></script><script defer="defer" src="/__/firebase/5.7.0/firebase-auth.js"></script><script defer="defer" src="/__/firebase/5.7.0/firebase-database.js"></script><script defer="defer" src="/__/firebase/5.7.0/firebase-messaging.js"></script><script defer="defer" src="/__/firebase/5.7.0/firebase-storage.js"></script><script defer="defer" src="/__/firebase/init.js"></script><style media="screen">body{background:#eceff1;color:rgba(0,0,0,.87);font-family:Roboto,Helvetica,Arial,sans-serif;margin:0;padding:0}#message{background:#fff;max-width:360px;margin:100px auto 16px;padding:32px 24px;border-radius:3px}#message h2{color:#ffa100;font-weight:700;font-size:16px;margin:0 0 8px}#message h1{font-size:22px;font-weight:300;color:rgba(0,0,0,.6);margin:0 0 16px}#message p{line-height:140%;margin:16px 0 24px;font-size:14px}#message a{display:block;text-align:center;background:#039be5;text-transform:uppercase;text-decoration:none;color:#fff;padding:16px;border-radius:4px}#message,#message a{box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24)}#load{color:rgba(0,0,0,.4);text-align:center;font-size:13px}#media (max-width:600px){#message,body{margin-top:0;background:#fff;box-shadow:none}body{border-top:16px solid #ffa100}}</style><link href="/static/css/main.6f735e8f.chunk.css" rel="stylesheet"></head><body><div id="message"><h2>Welcome</h2><h1>Firebase Hosting Setup Complete</h1><p>You're seeing this because you've successfully setup Firebase Hosting. Now it's time to go build something extraordinary!</p><a target="_blank" href="https://firebase.google.com/docs/hosting/">Open Hosting Documentation</a></div><p id="load">Firebase SDK Loading…</p><script>document.addEventListener('DOMContentLoaded', function() {
// // πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯
// // The Firebase SDK is initialized and available here!
//
// firebase.auth().onAuthStateChanged(user => { });
// firebase.database().ref('/path/to/ref').on('value', snapshot => { });
// firebase.messaging().requestPermission().then(() => { });
// firebase.storage().ref('/path/to/ref').getDownloadURL().then(() => { });
//
// // πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯
try {
let app = firebase.app();
let features = ['auth', 'database', 'messaging', 'storage'].filter(feature => typeof app[feature] === 'function');
document.getElementById('load').innerHTML = `Firebase SDK loaded with ${features.join(', ')}`;
} catch (e) {
console.error(e);
document.getElementById('load').innerHTML = 'Error loading the Firebase SDK, check the console.';
}
});</script><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={2:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/1.734eb6b0.chunk.js"></script><script src="/static/js/main.14da6ff9.chunk.js"></script></body></html>
First task
You need to replace this code with the following one in index.html of public folder:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web Chat Application created using professional technologies"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Programmer Dost</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
Second Task:
Delete .firebaserc file.
Delete firebase.json file.
Third Task:
Delete β€œ.firebase” folder.
Delete β€œbuild” folder.
Fourth Task:
run the command: firebase init
it will ask:
Which Firebase features do you want to set up for this directory?
choose: Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
then select:
Please select an option: Use an existing project
then select your project name
Fifth Task:
(Type the folder name where you want to initialize the app. It would be build in case of react app.)
What do you want to use as your public directory? build
Sixth Task:
(Select Yes in single page app)
Configure as a single-page app (rewrite all urls to /index.html)? Yes
Seventh Task:
Set up automatic builds and deploys with GitHub? No
Eigth Task:
(Run this Command)
npm run build /yarn build
Last Task:
(Run this command)
firebase deploy
In my case that's How it worked.
You have overwritten you index.html with the default one created by firebase during firebase init.
ToFIX:
delete current index.html
get your original index.html
run firebase init again.
when it ask you to overwrite you "index.html" - say NO.
I had the same problem and it was confusing because it deployed. Turns out I had to make sure to run
npm run build
firebase deploy
then wait a few minutes for the site to show up. This assumes you did not modify the react index.html file
You need to add this line in your index.html file.
<div id="root"></div>
Then it will work, You can add it before try{}.
in firebase.json Instead of
<i>"public": "build" </i>
put
<i>"public": "./build" </i>
and then
npm run build
firebase deploy
You say Β«I'm pretty wonder why index.html still have welcome to firebase wordingΒ». Most probably it is simply because your build process doesn’t overwrite it.
It is difficult to say from the elements and images you have added to your post, but when you do npm run build you either don’t build your react project or you build it in a dist directory that is not at all the public Firebase folder. You should copy the result of your build to the public folder and then re-deploy.

Resources