3
votes

I'm building a Django app with a React front end, built using react-create-app. I can't get the favicon to show up in production.

I'm using Django 2.10.0.

When I build the React app, the build output files are put in the assets/static/ folder. This includes image files used as backgrounds via css, and all works fine. These are included in the build because they are referenced in the stylesheets. The favicon is referenced from index.html and therefore isn't picked up by the build process.

However I don't know how to get the server to serve up the favicons. If I put them in the frontend/public folder, the Django server doesn't find them.

If I manually copy them into the static/ folder, they show up but that folder is managed by Webpack and the contents are removed when the app is built.

Copying the favicons into the project root doesn't work. They are in the same folder as index.html, which is served up, but Django server won't serve those co-located image files.

The only documentation I can find deals with either Django or create-react-app; I can't find anything that explains how to tie them together for favicons.

In settings.py:

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'assets/static'),
    os.path.join(BASE_DIR, 'assets'),
]

In index.html:

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

In the browser, this is converted to:

<link rel="shortcut icon" href="/favicon.ico">

which doesn't work - the file is not served up. I'm not sure why this doesn't work given that I've added 'assets' to STATICFILES_DIRS in settings.py and have copied the favicons into the root of 'assets'.

All the working css and image links include the static folder, e.g.:

http://localhost:8000/static/media/private.d7365d01.svg

It seems like there are two problems:

1) how to get the build process to copy the favicon and related files into the assets folder so they can be served up

2) how to get index.html to look in the right place for the favicon

If I could customise PUBLIC_URL to point to static/ that might do it, but that might break other bits of code that reference it?

I am sure I'm missing something simple. I'd be grateful for any help!

Edit: I have now got the favicon to show up in a built version running on my local machine, but it isn't being served by the production server.

Base.py

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'assets/static'),
    os.path.join(BASE_DIR, 'assets'),
]

index.html

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

And favicon.ico is in the 'assets' folder. After building my React app and running the development server locally, the url http://localhost:8000/static/favicon.ico displays my favicon. But after deploying this to the server, the url https://example.com/static/favicon.ico finds nothing. I have checked and the favicon.ico file is present on the server, in the assets folder. Settings.py is the same. I can't figure out why the production server isn't serving up the favicon?

Edit: I've tried adding this to my settings.py, but it still doesn't work:

STATIC_ROOT = os.path.join(BASE_DIR, 'assets')

'assets' is the name of the folder on the server that contains my build files. The favicons are in assets, as is index.html, and the React files in assets/static.

Edit: this is my Passenger config file for Nginx:

server {
    listen 80;
    server_name 178.62.85.245;

    passenger_python /var/www/myappname/venv36/bin/python3.6;

    # Tell Nginx where your app's 'public' directory is
    root /var/www/myappname/myappname/myappname;

    # Turn on Passenger
    passenger_enabled on;


   # Tell Nginx the location of the build output files
    location /static/ {
       autoindex on;
       alias /var/www/myappname/myappname/assets/;
    }
}

Nginx finds the file index.html and all the files that React built. I don't know why it can't find the favicon in the same folder!

Edit: I finally solved this thanks to Sune Kjærgård's help. From reading the Django docs about deployment, I had thought I needed to configure all the static file locations in settings.py. However that seems to be only for the Django development server, even when running with production settings. On the production server I am using Nginx via Passenger to serve the app. It is Nginx that needs to know where all my static files are located. And both 'root' and 'location' need to be set correctly.

Here is my working code. The favicons are served on the production server, and in development on port 3000 when running the frontend separately. I haven't got them served when testing the build locally on port 8000, but I can live with that and maybe find a solution later.

STATIC_ROOT doesn't seem to be required, nor am I running buildstatic.

My favicons are located in frontend/public, the same folder as index.html. The Webpack build process copies them all into the assets folder.

server {
    listen 80;
    server_name 178.62.85.245;

    passenger_python /var/www/myappname/venv36/bin/python3.6;

    # Tell Nginx where your app's 'public' directory is
    root /var/www/myappname/myappname/assets;

    # Turn on Passenger
    passenger_enabled on;


   # Tell Nginx the location of the build output files
    location /static/ {
       autoindex on;
       alias /var/www/myappname/myappname/assets/;
    }
}

In settings.py:

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'assets/static'),
    os.path.join(BASE_DIR, 'assets'),
]

In index.html:

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

In the browser, this is converted to:

<link rel="shortcut icon" href="/favicon.ico">

And I can see the icon in a browser at the address https://example.com/favicon.ico

Happy dance!

1
Sounds like you are trying to use the Django development served in production. Don’t do that! You should use uwsgi with nginx in front of it or similar setup.Sune Kjærgård
I'm using Phusion Passenger under Nginx on the production server, via a wsgi file. What is it in my code that looks wrong to you?Little Brain
Ok, I just misunderstood then because of the local host references in your question. Usually, when you have nginx in front, you should configure that to serve the static files. Can you show us you nginx configuration?Sune Kjærgård
Thank you! All the Django docs talk about using static_files in production so that led me in the wrong direction. I had my Nginx config wrong because I didn't understand how it worked. Setting root /var/www/myappname/myappname/assets; for Nginx has solved the problem. If you post that as an answer, I will accept it.Little Brain
Glad you figured it out. I added an answer :-)Sune Kjærgård

1 Answers

2
votes

In production you usually use nginx or whatever server you have in front of your wsgi server to serve static files.

Specifically for the favicon, you can setup a location in nginx just for that:

location = /favicon.ico {
    alias /var/www/mysite/img/favicon.ico;
}