How should I configure create-react-app to serve app from subdirectory?

前端 未结 6 1082
死守一世寂寞
死守一世寂寞 2020-12-08 02:59

I have classic web application rendered on server. I want to create admin panel as single page application in React. I want to server admin panel from https://smyapp.example

相关标签:
6条回答
  • 2020-12-08 03:17

    You should add entry in package.json for this.

    Add a key "homepage": "your-subfolder/" in your package.json All static files will be loaded from "your-subfolder"

    If there is no subfolder and you need to load from same folder you need to add the path as "./" or remove the entire line which has "homepage": "xxxxxxxxxx"

    "homepage": "./"

    From the official docs

    By default, Create React App produces a build assuming your app is hosted at the server root. To override this, specify the homepage in your package.json, for example:

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

    Note: If you are using react-router@^4, you can root <Link>s using the basename prop on any <Router>.

    From here and also check the official CRA docs

    0 讨论(0)
  • 2020-12-08 03:26

    In addition to your requirements, I am adding mine:

    • It should be done by CD, through an env variable.
    • If I need to rename the subdirectory, I should only have to change the env variable.
    • It should work with react-router.
    • It should work with scss (sass) and html.
    • Everything should work normally in dev mode (npm start).

    I also had to implement it in Angular2+ project not long ago, I found it harder to implement in React then in Angular2+ where you are good to go with ng build --base-href /<project_name>/. source


    Short version

    1. Before building, set PUBLIC_URL env variable to the value of your subdirectory, let use /subdir for example. You can also put this variable into your .env.production (in case you do not have that file you can check the doc)
    2. In public/index.html add the base element bellow, this is for static files like images.
    <base href="%PUBLIC_URL%/">
    
    1. Also in public/index.html, if you have custom link element, make sure theyre are prefixed with %PUBLIC_URL% (like manifest.json and favicon.ico href).
    2. If you use BrowserRouter, you can add basename prop:
    <BrowserRouter basename={process.env.PUBLIC_URL} />
    
    1. If you use Router instead, because you need access to history.push method, to programmatically change page, do the following:
    // history.tsx
    import {createBrowserHistory} from 'history';
    
    export default createBrowserHistory({ basename: process.env.PUBLIC_URL });
    
    <!-- Where your router is, for me, App.tsx -->
    <Router history={history}>
      ...
    </Router>
    
    1. Use relative links inside your elements
    <!-- "./assets/quotes.png" is also ok, but "/assets/quotes.png" is not -->
    <img src="assets/quotes.png" alt="" />
    
    1. Move your background-image links from scss to jsx/tsx files (note that you may not need to do that if you use css files):
    /*remove that*/
    background-image: url('/assets/background-form.jpg');
    
    <section style={{backgroundImage: `url('assets/background-form.jpg')`}}>
    ...
    

    You should be done.


    Additional informations

    I preferred to use PUBLIC_URL instead of homepage in package.json because I want to use env variable set on gitlab to set the subdir. Relevant resources about the subject:

    • https://create-react-app.dev/docs/deployment/#building-for-relative-paths
    • https://create-react-app.dev/docs/advanced-configuration/
    • https://github.com/facebook/create-react-app/issues/998

    PUBLIC_URL override homepage, and PUBLIC_URL also take the domain name, if you provide one. If you set only homepage, PUBLIC_URL will be set to the value of homepage.


    If you do not want to use a base element in your index.html (I would not know why), you will need to append process.env.PUBLIC_URL to every link yourself. Note that if you have react-router with a base element, but have not set basename prop, you will get a warning.


    Sass won't compile with an incorrect relative path. It also won't compile with correct relative path to your ../public/assets folder, because of ModuleScopePlugin restrictions, you can avoid the restriction by moving your image inside the src folder, I haven't tried that.


    There seem to be no way of testing relative path in development mode (npm start). see comment


    Finnaly, theses stackoverflow link have related issues:

    • Can I set a base route in react-router
    • Setting base href using Environment variables
    0 讨论(0)
  • 2020-12-08 03:27

    put in package.json something like this:

    "homepage" : "http://localhost:3000/subfolder",

    and work fine on any public or local server. Of course, subfolder must be your folder.

    0 讨论(0)
  • 2020-12-08 03:32

    For create-react-app v2 and react-router v4, I used the following combo to serve a production (staging, uat, etc) app under "/app":

    package.json:

    "homepage": "/app"
    

    Then in the app entry point:

     <BrowserRouter basename={process.env.PUBLIC_URL}>
      {/* other components */}
     </BrowserRouter>
    

    And everything "just works" across both local-dev and deployed environments. HTH!

    0 讨论(0)
  • 2020-12-08 03:35

    You can specify the public path in your webpack configuration along with use of react route basepath.

    Link to Public Path: https://webpack.js.org/guides/public-path/

    Note that public path will be both leading and trailing slashes / to be valid.

    0 讨论(0)
  • 2020-12-08 03:38

    Maybe you could use react-router and its relative basename parameter which allows you to serve your app from a subdirectory.

    basename is the base URL for all locations. If your app is served from a sub-directory on your server, you’ll want to set this to the sub-directory. A properly formatted basename should have a leading slash, but no trailing slash.

    For instance:

    <BrowserRouter basename="/calendar"/>
    

    So <Link to="/today"/> will render <a href="/calendar/today">

    See: https://reacttraining.com/react-router/web/api/BrowserRouter/basename-string

    0 讨论(0)
提交回复
热议问题