13

I have a react app that works perfectly fine locally, when I deploy it to Azure, I have a few 404 errors, on the index.html

All of them with the tag %PUBLIC_URL%

According to the documentation, they will be replaced in the build process, but not sure how this is done, so that when deployed, the correct urls are put in place

<!doctype html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta name="theme-color" content="#000000">
    <!--
          manifest.json provides metadata used when your web app is added to the
          homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/favicon.png">
    <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700" rel="stylesheet" async>
    <link async rel="stylesheet" href="%PUBLIC_URL%/css/ionicons.min.css">
    <link rel="stylesheet" href="https://unpkg.com/react-instantsearch-theme-algolia@4.0.0/style.min.css">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css"
         integrity="sha512-M2wvCLH6DSRazYeZRIm1JnYyh22purTM+FDB5CsyxtQJYeKq83arPe5wgbNmcFXGqiSH2XR8dT/fJISVA1r/zQ=="
         crossorigin="" async/>
    <!--
          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>Isomorphic</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>
Garry
  • 49
  • 6
Luis Valencia
  • 32,619
  • 93
  • 286
  • 506
  • `%PUBLIC_URL%` will be replaced with an actual value in the build, like you said. Are you sure you are deploying the `index.html` file from the `build` directory and not the `public` directory? – Tholle Nov 09 '18 at 12:07
  • I have CI/CD, when something is commited to vsts git repo, then the build and deploy is fired, let me send you some screenshots – Luis Valencia Nov 09 '18 at 12:09
  • not sure, if this screenshot helps. https://www.screencast.com/t/y279smspa – Luis Valencia Nov 09 '18 at 12:10
  • then the deployment pipeline is really easy: https://www.screencast.com/t/033U0cZHm – Luis Valencia Nov 09 '18 at 12:12

2 Answers2

12

HOW TO REPLACE %PUBLIC_URL%

By default, Create React App produces a build assuming your app is hosted at the server root. example.com If your website isn't served from this root, (maybe you want to serve from example.com/relativepath, you can override this by specifying the homepage in your package.json

"homepage": "http://example.com/relativepath",

This will let Create React App correctly infer the root path to use in the generated HTML file.

In your case, however, I think you get a 404 error because the Azure is trying to find an index.html (or some other index.* named). To fix this, Azure needs to know how to pass the intended route to the one and only index.html placed at the site's root. Create a new file named web.config inside /site/wwwroot folder with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<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>

This will tell Azure to rewrite all urls as if they are pointing to our root file and our SPA application can handle the links correctly.

References:

I hope this may help you

Tatsu
  • 1,743
  • 16
  • 15
9

This looks like the index file taken from public instead of build.

Like the documentation says, %PUBLIC_URL% is replaced when you build the project.

Assuming you used create-react-app, make sure that you're running npm run build and hosting the files from the build directory.

Smarticles101
  • 1,822
  • 1
  • 14
  • 28
  • the big questions, is it replaced by what? is there a parameter file somewhere where I have to put this public url? – Luis Valencia Nov 13 '18 at 22:43
  • 1
    there is a `homepage` property you can set inside of `package.json` that specifies where the react app is hosted. If this property isn't set, the build command assumes that the app is hosted at root. If it is set and it contains a path after the domain, the build command replaces `%PUBLIC_URL%` with the path. ex: if I set `"homepage": "http://example.com/reactapp/"` then `%PUBLIC_URL%` is replaced with `/reactapp` but if `"homepage": "http://example.com/"` `%PUBLIC_URL%` is just replaced with an empty string. – Smarticles101 Nov 13 '18 at 22:57
  • I checked the deployed the files. and in index.html %PUBLIC_URL% is replaced with empty, so it should be fine, if you check the screenshots above for my build pipeline, I am copying the build directory – Luis Valencia Nov 13 '18 at 23:16
  • @LuisValencia where are you running `npm run build`? Does the CI use a script or is it just a gui? – Smarticles101 Nov 13 '18 at 23:18
  • I'm not too familiar with azure, have you tried using the "Azure App Service Deploy" task? You should be able to update the package or folder value on that to `$(System.DefaultWorkingDirectory)/build`. – Smarticles101 Nov 13 '18 at 23:35
  • 2
    I felt very silly when I found this answer, but you saved me from a major headache, so thank you! – Nick Coad Jun 25 '19 at 05:45