Package: logicore-django-react
logicore-django-reactA little Python module helping to use Django and React on a single port during development and productionServes as a foundation forlogicore-django-react-pagesproject, but can be used without itRunning Django and React on a single port during developmentTODO: MotivationUsage from scratch: starting a Django + React project for developmentTODO: automated script/project templateInstall Django and start the projectmkvirtualenvdjango_react_project1# Or venv etcpython3-mpipinstallDjango
django-admin.pystartprojectdjango_react_project1cddjango_react_project1# Configure database, etc and commitNow you have fresh Django! Check it works:python manage.py runserverand stop the development server.Hint:Don't forget to add minimal.gitignorefile for Python/Django development, such as:*.swp
*.py[cod]
__pycache__
*.sqlite3
/static/**
/media/**Make a React for-development installation (inside a Django folder), calledfrontend.
Then, commit the changes and eject (we need it all):create-react-app frontend
git add --all :/ && git commit -m "added frontend"
cd frontend
yarn eject
git add --all :/ && git commit -m "ejected frontend"Installlogicore_django_reactand make use of it from your Django project:pip install -U logicore_django_react(-Uis required to ensure to get latest version)Add tourls.py:fromlogicore_django_react.urlsimportreact_reload_and_static_urls,react_html_template_urlsurlpatterns=[# ...]# add static/media endpoints here if needed# urlpatterns += static(...)# lastly, combine with logicore_django_react urlsurlpatterns=react_reload_and_static_urls+urlpatterns+react_html_template_urlsWhich will add necessary views for React to work via Django:react_reload_and_static_urls— serves hot-reload hooks and static filesreact_html_template_urls— global (akamatch-all,.*) view, that just serves HTML template that includes ReactThe latter (HTML template) might be overridden by changing
theLOGICORE_DJANGO_REACT_TEMPLATEsetting, which is by default set tologicore_django_react/home.htmlfilename.Please see source of a corresponding template file as an example.Important:In order for template file and template tags to work, addlogicore_django_reacttoINSTALLED_APPS.Also to settings, add:FRONTEND_DEV_MODE=os.environ.get("FRONTEND_DEV_MODE",None)(otherwise you may see an error message).This environment variable is required to
distinguish if Django is running in development or production mode.Either:create your main app in Django (e.g. calledmain)or add non-app templates and static foldersto prepare for React build bundles (templates and static files) to be saved into and remember it for the next step:pythonmanage.pystartappmain# and add to INSTALLED_APPSmkdirmain/templates/# here, "react" folder will automatically be added latermkdirmain/static/# here, "react" folder will automatically be added lateror# add "my_global_templates" to TEMPLATE_DIRSmkdirmy_global_templates/# here, "react" folder will automatically be added later# add "my_global_static" to STATICFILES_DIRSmkdirmy_global_static/# here, "react" folder will automatically be added laterHints:When creating an app, don't forget to add it toINSTALLTED_APPSgitkeep the templates/static folders createdMake modifications tofrontendsub-project:in frontend/config/env.js — replace:WDS_SOCKET_PORT:process.env.WDS_SOCKET_PORT,byWDS_SOCKET_PORT:3000,This will make React project's built-in websocket to the right port — where the React's server
is and not e.g. 8000.Infrontend/scripts/start.jscomment outopenBrowsercommand. Before:openBrowser(urls.localUrlForBrowser);after://openBrowser(urls.localUrlForBrowser);which doesn't open a browser at port3000, 'cause we don't want direct output
of React's dev server (it will be got by Django instead).make the following modifications tofrontend/scripts/build.jsfile
(to make build process also integrate with Django):Add to the beginning:constrimraf=require('rimraf');constmkdirp=require('mkdirp');and also, install that modules (inside yourfrontendfolder):yarn add -D rimraf mkdirpbefore the first.catch(...)statement in the file, prepend the following extra step:.then(function(){constfilename=__dirname+'/../build/asset-manifest.json';constchunks={};JSON.parse(fs.readFileSync(filename)).entrypoints.map(e=>{letext=e.split('.');ext=ext[ext.length-1];if(!chunks[ext])chunks[ext]=[];chunks[ext].push(e.replace('static/','/static/react/'));});constappBase=__dirname+'/../../main/';consttemplates={css:url=>`<link rel="stylesheet" type="text/css" href="${url}" />`,js:url=>`<script type="text/javascript" src="${url}"></script>`,}for(let[k,v]ofObject.entries(templates)){consthtml=chunks[k]?.map(v).join('');constfileDir=`${appBase}templates/react/`;mkdirp.sync(fileDir);fs.writeFileSync(`${fileDir}bundle_${k}.html`,html);}constsrcDir=__dirname+'/../build/static/';constdestDir=appBase+'static/react/';console.log(`will remove dir${destDir}`);rimraf.sync(destDir);fs.copySync(srcDir,destDir,{overwrite:true},function(err){if(err){console.error(err);}else{console.log(chalk.green("copy assets to build: success!"));}});})and check that the path__dirname + '/../../main/(theappBase) points exactly to where your
location for auto-generated (during the build) templates and static files is.
This example is given for storing the files inside the folders of an app calledmain.Finally, infrontend/config/webpack.config.jsreplace two occurrences
ofstatic/media/byreact-static/media/:assetModuleFilename:'static/media/[name].[hash][ext]',toassetModuleFilename:'react-static/media/[name].[hash][ext]',andname:'static/media/[name].[hash].[ext]',toname:'react-static/media/[name].[hash].[ext]',to give specifically included static files, such as included images their own directory
('causestaticmay be already taken by Django).gitignorethe auto-generated folders of yours:main/templates/react/**
main/static/react/**Add files and commit — now you should have ready-to-go setup for
developing and deploying Django + React project on a single port!DevelopmentIn root folder:exportFRONTEND_DEV_MODE=1pythonmanage.pyrunserverInfrontend/folder:yarnstartProductionBuild frontend and collect staticcdfrontend/
yarnbuildcd..
pythonmanage.pycollectstaticDeploy as normal (according to Django docs)