I'm using Django 4 and wish to integrate a ReactJS application within the Django framework.
I chose to use the exact approach here to start and installed it identically as outlined.
Here's a list of the installed components and versions:
├── @babel/[email protected]
├── @babel/[email protected]
├── @babel/[email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
I do not want to post all of my code here since it is 100% identical to the code in the link above.
Unfortunately, I'm receiving a strange error in the console:
GET http://127.0.0.1:8001/frontend/static/frontend/frontend-dc3188e75be82e0a01e0.js net::ERR_ABORTED 404 (Not Found)
127.0.0.1/:1 Refused to execute script from 'http://127.0.0.1:8001/frontend/static/frontend/frontend-dc3188e75be82e0a01e0.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
This appears to be related to the path, but the referenced JS filename is spelled correctly and exists at the exact referenced path.
The server console also displays a similar error:
Not Found: /frontend/static/frontend/frontend-dc3188e75be82e0a01e0.js
CodePudding user response:
the link you provided is an old tutorial. You should always follow the documentation. Based on docs
You must generate the front-end bundle using webpack-bundle-tracker before using django-webpack-loader. You can compile the assets and generate the bundles by running:
npx webpack --config webpack.config.js --watch
this is webpack config setting related to webpack-bundle-tracker
. It spits out the webpack-stats.json
file and looks like django webpack-loader
reads from this .json file
const path = require('path');
const webpack = require('webpack');
const BundleTracker = require('webpack-bundle-tracker');
module.exports = {
context: __dirname,
entry: './assets/js/index',
output: {
path: path.resolve('./assets/webpack_bundles/'),
filename: "[name]-[hash].js"
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'})
],
}
and then:
WEBPACK_LOADER = {
'DEFAULT': {
'CACHE': not DEBUG,
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
'POLL_INTERVAL': 0.1,
'IGNORE': [r'. \.hot-update.js', r'. \.map'],
}
CodePudding user response:
Thank you for the feedback. This is how I ultimately performed this integration entirely using a combination of online tutorials, the feedback here and the github repo for django-webpack-loader.
Keep in mind this approach below eliminates a lot of the unnecessary steps and ensures the latest versions of the software are used. References are below.
A: Setup the Django App and Dependencies
- Create the frontend app in Django
python manage.py startapp frontend
- Update the list of installed apps within settings.py or base.py:
INSTALLED_APPS = [
'frontend',
...
]
Create the templates folder for the frontend app. In my case, my Templates directory is in the root of the project, so under the folder I added 'frontend': ./templates/frontend
Create the template in the newly created frontend folder: ./templates/frontend/index.html
Add the following into the index.html, which contains Django tags to use later for rendering the bundle:
<!DOCTYPE html>
{% load render_bundle from webpack_loader %}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Site</title>
</head>
<body>
<div id="app"></div>
<p>hello</p>
{% render_bundle 'frontend' %}
</body>
</html>
- Create the view in the app frontend/views.py
from django.shortcuts import render
def index(request):
return render(request, 'frontend/index.html')
- Update the URL pattern within urls.py at the project level: config/urls.py. In this case, the react app is loading from the root of the domain. I recommend using this configuration (outlined in step 7 and 8) or you will receive path errors. This can be changed later.
path('', include('frontend.urls'))
- Update the URL patterns within urls.py at the app level:
path('', views.index)
- At this point, you can test and run the server or continue on. If you test, remember that you have 2 Django tags loading in Step 5 that you will need to comment out.
python manage.py runserver
B: Install React & Babel
- From the root of the project, run the following command to create the package.json file.
npm init -y
- Setup Babel.
npm install --save-dev @babel/core
- Install Babel plugins:
npm install --save-dev @babel/preset-env @babel/preset-react
- Create a .babelrc file in the root of your project and add this into it:
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
C: Install & Configure Webpack
- Install Webpack and the additional packages.
npm install --save-dev webpack webpack-cli webpack-bundle-tracker babel-loader css-loader style-loader clean-webpack-plugin
- Create a webpack.config.js file in the root of the project.
const path = require('path');
const webpack = require('webpack');
const BundleTracker = require('webpack-bundle-tracker');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
context: __dirname,
entry: {
frontend: './frontend/src/index.js',
},
output: {
path: path.resolve('./frontend/static/frontend/'),
filename: '[name]-[hash].js',
publicPath: 'static/frontend/',
},
plugins: [
new CleanWebpackPlugin(),
new BundleTracker({ filename: './webpack-stats.json' })
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
}
- Add the following scripts to your package.json file located in the project root. You should already have scripts in this file; just add the two new lines of code for "dev" and "build".:
{
...,
"scripts": {
...,
"dev": "webpack --config webpack.config.js --watch --mode development",
"build": "webpack --config webpack.config.js --mode production"
}
}
C: Create a basic React APP for testing
In the frontend app folder, create a folder called src.
In the src folder, create an App.js file. Be sure to follow the capitalization. And, add the following to it:
import React from 'react'
const App = () => {
return (
<div>Hello, World!</div>
)
}
export default App
- In the src folder, create an index.js file and add the following to it:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(
<App />,
document.getElementById('app')
)
D: Install Webpack Loader & Configure
- Run the following command:
pip install django-webpack-loader
- Update the list of installed apps within settings.py or base.py:
INSTALLED_APPS = (
...
'webpack_loader',
...
)
- Also, update the Webpack Loader configurations in the settings.py or base.py file:
WEBPACK_LOADER = {
'DEFAULT': {
'CACHE': not DEBUG,
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
'POLL_INTERVAL': 0.1,
'IGNORE': [r'. \.hot-update.js', r'. \.map'],
}
}
If you receive an error related to DEBUG, check the available options in the django-webpack-loader instructions (see below for link).
E: Compile the frontend asset files and test
If you commented out the django tags in step A9, remove the comment before proceeding.
Run the following command:
npx webpack --config webpack.config.js --watch
- Run your server:
python manage.py runserver
- Open your browser and navigate to the root of your site. You should receive a Hello World printout on the screen. If not, and you only receive an empty white screen, the react assets are not loading. Check the server console and/or the browser console for errors.
References: Outdated Tutorial https://dev.to/zachtylr21/how-to-serve-a-react-single-page-app-with-django-1a1l
django-webpack-loader repo https://github.com/django-webpack/django-webpack-loader