aturon
aturon

Reputation: 81

How do I get collectstatic to work when running a Django/React App on Heroku?

I have a Django/Wagtail/React App that works in my dev server, but when I try to build it on Heroku, I get a ***FileNotFoundError when it runs collectstatic. I'm using Whitenoise to serve the static files and have Gunicorn installed with its corresponding Procfile. This is the error log I get on Heroku:

-----> Building on the Heroku-20 stack
-----> Using buildpack: heroku/python
-----> Python app detected
-----> Using Python version specified in Pipfile.lock
-----> No change in requirements detected, installing from cache
-----> Using cached install of python-3.9.5
-----> Installing pip 20.2.4, setuptools 47.1.1 and wheel 0.36.2
-----> Installing dependencies with Pipenv 2020.11.15
       Installing dependencies from Pipfile.lock (d71a71)...
-----> Installing SQLite3
-----> $ python manage.py collectstatic --noinput
       BASE_DIR /tmp/build_73214ee4
       BASE_DIR + FRONTENTD:  /tmp/build_73214ee4/frontend/build/static
       Traceback (most recent call last):
         File "/tmp/build_73214ee4/manage.py", line 10, in <module>
           execute_from_command_line(sys.argv)
         File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
           utility.execute()
         File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/__init__.py", line 413, in execute
           self.fetch_command(subcommand).run_from_argv(self.argv)
         File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/base.py", line 354, in run_from_argv
           self.execute(*args, **cmd_options)
         File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/base.py", line 398, in execute
           output = self.handle(*args, **options)
         File "/app/.heroku/python/lib/python3.9/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 187, in handle
           collected = self.collect()
         File "/app/.heroku/python/lib/python3.9/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 105, in collect
           for path, storage in finder.list(self.ignore_patterns):
         File "/app/.heroku/python/lib/python3.9/site-packages/django/contrib/staticfiles/finders.py", line 130, in list
           for path in utils.get_files(storage, ignore_patterns):
         File "/app/.heroku/python/lib/python3.9/site-packages/django/contrib/staticfiles/utils.py", line 23, in get_files
           directories, files = storage.listdir(location)
         File "/app/.heroku/python/lib/python3.9/site-packages/django/core/files/storage.py", line 323, in listdir
           for entry in os.scandir(path):
       **FileNotFoundError: [Errno 2] No such file or directory: '/tmp/build_73214ee4/frontend/build/static'
 !     Error while running '$ python manage.py collectstatic --noinput'.**
       See traceback above for details.
       You may need to update application code to resolve this error.
       Or, you can disable collectstatic for this application:
          $ heroku config:set DISABLE_COLLECTSTATIC=1
       https://devcenter.heroku.com/articles/django-assets
 !     Push rejected, failed to compile Python app.
 !     Push failed

I have a feeling that it may be due to my settings file which is here (I have it split between dev and production, but will collate it here to be more readable):

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'corsheaders.middleware.CorsMiddleware',                        # django-cors-headers: https://pypi.org/project/django-cors-headers/

    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

    'wagtail.contrib.redirects.middleware.RedirectMiddleware',
]

STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]

STATICFILES_DIRS = [
    os.path.join(PROJECT_DIR, 'static'),
    os.path.join(BASE_DIR, 'frontend/build/static'),
]


STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
MEDIA_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN

"""Whitenoise Static Files"""
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'     # See: https://wagtail.io/blog/deploying-wagtail-heroku/
COMPRESS_OFFLINE = True
COMPRESS_CSS_FILTERS = [
    'compressor.filters.css_default.CssAbsoluteFilter',
    'compressor.filters.cssmin.CSSMinFilter',
]
COMPRESS_CSS_HASHING_METHOD = 'content'
django_heroku.settings(locals())

My file structure is laid out like this:

Base_Directory
|__ app1
|__ app2
|__ Frontend (React App)
   |__ build
      |__ static
      |__ (etc..)
   |__ index.html
   |__ src
   |__ (etc..)
|__ Project_Directory
|__ manage.py
|__ Procfile
|__ (etc..)

From the error, it seems like it's not recognizing the static folder under build. I printed out the output from BASE_DIR and it seems it's something strange: "/tmp/build_73214ee4". In the dev environment, the STATICFILES_DIRS list is able to point to the React app's location just fine however.

I've tried creating both a static and a staticfiles folder in the base directory (with a dummy txt file in there so it can be uploaded via git) and it still returns the same error. I've tried moving the frontend folder into the Project_Directory folder and that didn't work either. Has anyone faced this situation before, and if so do you have any tips you can share?

Upvotes: 0

Views: 529

Answers (2)

aturon
aturon

Reputation: 81

Strangely enough, the solution was in my blindspot. When I created my React app, it included a gitignore file that stopped the frontend/build folder from being uploaded to Github. I use the run project from Github feature on Heroku and that's why it gave an error saying the folder could not be found. Needless to say, but that fixed the collectstatic problem for me!

Upvotes: 1

taha maatof
taha maatof

Reputation: 2165

just run this :

heroku config:set DISABLE_COLLECTSTATIC=1

in your terminal and restart

Upvotes: 0

Related Questions