skip to Main Content

npm run build

I build a simple react app; this is what I see in build/ folder

jdoe@AIR  ~/Sites/react/alphabets/build   main ±  tree
.
├── asset-manifest.json
├── favicon.png
├── index.html
└── static
    ├── css
    │   ├── main.f05a5dc1.css
    │   └── main.f05a5dc1.css.map
    └── js
        ├── main.cec1e2e8.js
        ├── main.cec1e2e8.js.LICENSE.txt
        └── main.cec1e2e8.js.map

4 directories, 8 files

Since

I also have a Laravel site that I deployed.

I thought I could drop it in my `public/ and navigate to it like so.

https://www.bunlongheng.com/react/alphabets/

I tried SCP my build/ it to public/react/alphabets/build in my server.

When I go to it, I see no error, no forbidden, but a white screen.

I need a way to deploy react projects as simply as possible since my goal is to deploy more than one… ex.

mysite/react/first-project
mysite/react/second-project
mysite/react/third-project
mysite/react/forth-project

and so on... 

& leave my main site as it…

Any hints for me ? I know I am close.

4

Answers


  1. Your title said as subdomain, but your example URLs are subdirectory/subfolder. So I assume you meant how to build react app as subdirectory.

    the blank page mean the resource is not loaded because the resource path is using root path(/). To change the base path, you just need to add basename to your router :

    <Router basename={'/react/alphabets/build'}>
      <Route path='/' component={Home} />
    </Router>
    

    and also you need to add homepage to package.json. example:

    {
      "name": "react-example",
      "homepage": "/react/alphabets/build",
    

    or another way you need to move/copy public/react/alphabets/build/static to public/static/

    Login or Signup to reply.
  2. If you want a subdomain (ex https://alphabets.bunlongheng.com) you need to edit routing module, all SPA is working fine becouse you are working on the root.

    If you want a route into your domain (ex https://alphabets.bunlongheng.com/react/alphabets) is easier on Lavarel side because you just need to copy build content, but you need to override the default assumption that your app is hosted at the server root at different level: module bundler and client side routing.

    Module Bundler

    I personally use https://vitejs.dev/ in my projects but a very popular bundler is https://create-react-app.dev/.

    The bundler links file referring to the root!!

    Visiting https://www.bunlongheng.com/react/alphabets/ and opening the dev tools we can see on console errors that the webpage is searching for https://www.bunlongheng.com/static/css/main.f05a5dc1.css but the file is on https://www.bunlongheng.com/react/alphabets/static/css/main.f05a5dc1.css

    Please check your bundler documentation to fix this. If you are using CRA this is the docs for absolute and relative reference.

    Client side routing

    If your next project will use a client side routing like react router, you will need to configure a basename on client router docs

    Login or Signup to reply.
  3. Make sure in ur package.json like:

    // package.json 
    {
      "name": "alphabets",
      "homepage": "alphabets",
      ....
    }
    

    Note: Use sed to update homepage automatically.

    • Create a file called .env at your project root (where package.json is located),
      and write in this file:
    REACT_APP_BASENAME=react/alphabets
    

    Note: is better to use cross-env or any other alt (dotenv …) on your build proccess.

    Put empty value for REACT_APP_BASENAME= and remove homepage or put / if you want to run on localhost.

    • Update your BrowserRouter to fix white screen issue, follow:
    import React from "react";
    import { BrowserRouter } from "react-router-dom";
    
    const baseName = process.env.REACT_APP_BASENAME ?? "";
    
    const App: React.FC<> = () => {
      return (
        <>
          <BrowserRouter basename={baseName}>
            ....
          </BrowserRouter>
        </>
      );
    }
    
    export default App;
    
    • Move build files to:
    mv ~/Sites/react/alphabets/build/* ~/Sites/react/alphabets/
    
    Login or Signup to reply.
  4. The HTML standards will enable the static hosting behavior you want, on Laravel or any other provider.

    INDEX.HTML

    First add a base element like this. Set it to / by default, or set it to a value like /spa/ when deployed:

    <!DOCTYPE html>
    <html lang='en'>
        <head>
            <meta charset='utf-8'>
            <meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'>
    
            <base href='/spa/' />
            <title>Demo App</title>
    
            <link rel='stylesheet' href='bootstrap.min.css'>
            <link rel='stylesheet' href='app.css'>
        </head>
        <body>
            <div id='root' class='container'></div>
    
            <script type='module' src='vendor.bundle.js'></script>
            <script type='module' src='app.bundle.js'></script>
        </body>
    </html>
    

    REACT

    React has some nice support for path based routing, as selllami also pointed out above. When the React app starts, you can initialize React routes from the index.html runtime value:

    const props = {
        viewModel: new AppViewModel(),
    };
    
    const baseElement = document.querySelector('base') as HTMLElement;
    const base = baseElement?.getAttribute('href') || '/';
    
    const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
    root.render (
        <ErrorBoundary>
            <BrowserRouter basename={base}>
                <App {...props} />
            </BrowserRouter>
        </ErrorBoundary>
    );
    

    You can then define routes like this, and your code needs no awareness that the full URLs are of the form /spa/products:

    <Routes>
        <Route path='/products/:id' element={<ProductsView {...productsProps} />} />
        <Route path='/*'            element={<HomeView {...homeProps} />} />
    </Routes>
    

    You can then use other React navigation features, such as these, with paths beginning from the subfolder:

    import {useNavigate, useLocation} from 'react-router-dom';
    
    const navigate = useNavigate();
    const currentPath = useLocation().pathname;
    
    navigate("/products");
    
    <Link to="/products">View Products</Link>
    

    DEPLOYMENT

    You just need to edit the index.html as part of a deployment step. This can be automated by some script if required:

    const oldData = fs.readFileSync('index.html', 'utf8');
    var regex = new RegExp("href='/'", 'g');
    const newData = oldData.replace(regex, "href='/spa/'");
    fs.writeFileSync('index.html', newData, 'utf8');
    

    My demo SPA uses the above techniques, and I deploy it by dropping static content into either AWS Cloudfront or Docker based environments. It would also work on Laravel.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search