1

I'm writing a django rest framework API (backend) with a react SPA frontend. For the production environment, the front end is served up via nginx at http://example.com/ and the backend is proxied to gunicorn and served from the same domain with a different path - http://example.com/api/

This is all working fine in production, there are no CORS issues as the frontend and backend are both served up under the same domain via nginx.

For local development, I want to be able to replicate a similar setup using ./manage.py runserver and have django serve up the frontend from project/frontend/dist (built by npm build seperately).

Has anyone got any urlpattern wizardry that will allow this to happen and also let the react-router play nicely? I just can't figure it out and it's starting to drive me nuts...

The project structure is something like this if it helps in any explanations.

Project
|
 ── backend
│   ├── apps
│   ├── config
|   |    ├── settings.py
|   |    ├── settings_local.py
|   |    ├── urls.py
│   ├── manage.py
│   ├── requirements.txt
│   └── venv
├── frontend
│   ├── dist (contains the npm build webpack)
│   ├── node_modules
│   ├── package.json
│   ├── package-lock.json
│   ├── scripts
│   ├── src
│   ├── webpack.config.js

Edit #1

Thanks to another post I was able to get partially the way there by adding this to my urls.py

if settings.DEBUG:
    from django.views.generic import RedirectView
    from django.contrib.staticfiles.views import serve

    bundle_path = os.path.abspath(os.path.join(root_dir, 'frontend', 'dist'))

    settings.STATICFILES_DIRS += (bundle_path,)

    urlpatterns += [url(r'^$', serve, kwargs={'path': 'index.html'})]
    urlpatterns += [url(r'^(?!/?static/)(?!/?media/)(?P<path>.*\..*)$',
        RedirectView.as_view(url='/static/%(path)s', permanent=False))]

The only issue I have here is that if I go directly to one of the JS router links, then django tries to interpret it and can't find the route.

What I need now is a catch-all that will redirect to '/' but also keep any extra URL path information on the url

vasdee
  • 153
  • 7

2 Answers2

2

Finally got this to work with all the routing.

Added the webpack dist folder to settings.STATICFILES_DIRS Added the webpack frontend path to settings.TEMPLATES

Added 3 new urlpatterns to urls.py ( based on a conditional, settings.DEBUG)

urlpatterns += [
        url(r'^(?!/?static/)(?!/?media/)(?P<path>.*\..*)$',
        RedirectView.as_view(url='/static/%(path)s', permanent=False)),
        url(r'^$', TemplateView.as_view(template_name='dist/index.html'), name='frontend'),
        url(r'^(?P<path>.*)/$', TemplateView.as_view(template_name='dist/index.html'), name='frontend'),
]

The first redirects any of the asssets for the bundle to be served using django's static files.

The second pattern serves the root path / as a template from the webpack dist folder

The final piece handles all the leftover JS routing paths to go back to the initial root view.

vasdee
  • 153
  • 7
0

You can use nginx reverse proxy to serve them. No need config Django's url. See example here: http://www.codingpedia.org/ama/how-to-configure-nginx-in-production-to-serve-angular-app-and-reverse-proxy-nodejs

Cherry
  • 71
  • 1
  • 1
  • 5
  • This is what I am trying to avoid. Seems a little heavy for this scenario to use nginx locally (or docker). – vasdee Oct 25 '17 at 00:31