3

In react, I created a folder ./public/assets, and put an image in the ./public/assets. Everything works well when I run npm start. After running npm run build in react, I get a ./build folder. I copied files and folders inside the ./build folder to a flask folder. Since the index.html should be put in ./templates in flask, the browser can't get the image in flask ./assets.

The files in flask:

.
├── app.py
├── asset-manifest.json
├── assets
│   └── Montage_of_Toronto_7.jpg
├── favicon.ico
├── manifest.json
├── precache-manifest.28e9dd49c9646209098c5bb088bdb16f.js
├── service-worker.js
├── static
│   ├── css
│   │   ├── main.2cce8147.chunk.css
│   │   └── main.2cce8147.chunk.css.map
│   ├── js
│   │   ├── 2.38e0f74c.chunk.js
│   │   ├── 2.38e0f74c.chunk.js.map
│   │   ├── main.1c5ab122.chunk.js
│   │   ├── main.1c5ab122.chunk.js.map
│   │   ├── runtime~main.a8a9905a.js
│   │   └── runtime~main.a8a9905a.js.map
│   └── media
│       └── logo.5d5d9eef.svg
└── templates
    └── index.html

the folders in react/public:

.
├── assets
│   └── Montage_of_Toronto_7.jpg
├── favicon.ico
├── index.html
└── manifest.json

the files in react/build

.
├── asset-manifest.json
├── assets
│   └── Montage_of_Toronto_7.jpg
├── favicon.ico
├── index.html
├── manifest.json
├── precache-manifest.28e9dd49c9646209098c5bb088bdb16f.js
├── service-worker.js
└── static
    ├── css
    │   ├── main.2cce8147.chunk.css
    │   └── main.2cce8147.chunk.css.map
    ├── js
    │   ├── 2.38e0f74c.chunk.js
    │   ├── 2.38e0f74c.chunk.js.map
    │   ├── main.1c5ab122.chunk.js
    │   ├── main.1c5ab122.chunk.js.map
    │   ├── runtime~main.a8a9905a.js
    │   └── runtime~main.a8a9905a.js.map
    └── media
        └── logo.5d5d9eef.svg

Is there any solution that can configure the public path so that the ./public folder will be put into ./build/static?

I use send_from_directory in flask backend to serve the files in ./assets. But I would like to put files to ./build/static folder when I run npm run build, including the files favicon.ico, manifest.json and so on.

combo combo
  • 85
  • 1
  • 7

2 Answers2

3

If you have a build directory like this inside the flask app:

.
|
|_build
|    |_static
|       |_css
|       |_js
|       |_img
|    |_index.html
|_serve.py

With a serve.py like this:

from flask import Flask, render_template, send_from_directory


app = Flask(__name__, static_folder="build/static", template_folder="build")


@app.route("/")
def home():
    return render_template('index.html')


@app.route("/manifest.json")
def manifest():
    return send_from_directory('./build', 'manifest.json')


@app.route('/favicon.ico')
def favicon():
    return send_from_directory('./build', 'favicon.ico')


app.run(host='0.0.0.0', debug=True)

Reference: https://flask.palletsprojects.com/en/1.1.x/patterns/favicon/

I think it will work.

Full directory tree (tested here locally):

.
├── README.md
├── build
│   ├── asset-manifest.json
│   ├── favicon.ico
│   ├── index.html
│   ├── manifest.json
│   ├── precache-manifest.054774adbe886ee6e3c29227ef1745b5.js
│   ├── service-worker.js
│   └── static
│       ├── css
│       │   ├── main.2cce8147.chunk.css
│       │   └── main.2cce8147.chunk.css.map
│       ├── js
│       │   ├── 2.b41502e9.chunk.js
│       │   ├── 2.b41502e9.chunk.js.map
│       │   ├── main.28647029.chunk.js
│       │   ├── main.28647029.chunk.js.map
│       │   ├── runtime~main.a8a9905a.js
│       │   └── runtime~main.a8a9905a.js.map
│       └── media
│           └── logo.5d5d9eef.svg
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── serve.py
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   └── serviceWorker.js
└── yarn.lock

In this case, I merged the flask and the react app in the same directory. You can put in different directories and then just move the build dir to the root of the flask app. Or do like this suggestion like this.

EDIT (another option to do it):

You can also edit your public directory to look like this:

public/
├── index.html
└── static
    ├── favicon.ico
    └── manifest.json

Note you should also change your index.html to have:

<link rel="manifest" href="%PUBLIC_URL%/static/manifest.json" />
<link rel="shortcut icon" href="%PUBLIC_URL%/static/favicon.ico" />

Then, when you run yarn build you will have the favicon.ico and manifest.json inside the static directory. No need to have the custom routes on flask for this.

caiolopes
  • 561
  • 8
  • 14
  • No, it doesn't work. Did you try `app.run()`? If you load `http://127.0.0.1:5000/` and open the Chrome network panel, can you see manifest.json `404`? – combo combo Jul 29 '19 at 01:13
  • @combo-combo Indeed... I added an workaround but I don't think it is a good solution, but it works – caiolopes Jul 29 '19 at 01:26
  • But I don't think you can put this inside static since it is expected to be on the root. You can read more about this manifest.json file here https://stackoverflow.com/questions/45186993/what-is-public-manifest-json-file-in-create-react-app – caiolopes Jul 29 '19 at 01:31
  • Found another way to do it. Edited the original solution. – caiolopes Jul 29 '19 at 01:43
0

Hope this can help:

  1. react build folder
build
├── asset-manifest.json
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
├── precache-manifest.984ab282787c862e232c323b865ef221.js
├── robots.txt
├── service-worker.js
└── static\
  1. serve public resources using regex
import flask
from werkzeug.routing import BaseConverter

class RegexConverter(BaseConverter):
    def __init__(self, url_map, *items):
        super(RegexConverter, self).__init__(url_map)
        self.regex = items[0]

app = flask.Flask(__name__, template_folder='build', static_folder='build/static')
app.url_map.converters['regex'] = RegexConverter

@app.route("/<regex(r'(.*?)\.(json|txt|png|ico|js)$'):file>", methods=["GET"])
def public(file):
    return flask.send_from_directory('./build', file)
Valley
  • 51
  • 5