Search code examples
reactjsdjangonpmwebpackhybrid

using React JS components in django teamplates though static files (hybrid model) - what's wrong? (newbie JS/React question)


I am new to JS/React/npm/webpack, and fairly new to Django. I am trying to build search experience (i.e. front-end) for my existing Django web application, and I am planning to use elastic/search-ui components for that. I did some research (How to get Django and ReactJS to work together?) and I am following the hybrid model guide (https://www.saaspegasus.com/guides/modern-javascript-for-django-developers/integrating-javascript-pipeline/) where static JS files are used in Django templates.

I got to the point where I could display some text from JS script in Django template, now I am trying to display imported JS component and I got stuck. This is my code:

package.json:

...
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development"
  },
...
  "devDependencies": {
    "@elastic/search-ui": "^1.5.1",
    "babel": "^6.23.0",
    "babel-loader": "^8.1.0",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-scripts": "^4.0.3",
    "webpack": "^5.26.3",
    "webpack-cli": "^4.5.0"
  }

webpack.config.js:

const path = require('path');

module.exports = {
  entry: './ui-react-src/index.js',  // path to our input file
  output: {
    filename: 'index-bundle.js',  // output bundle file name
    path: path.resolve(__dirname, './reviewer/static/ui-react-build'),  // path to our Django static directory
  },
};

django html template I want to load React components to:

{% extends "base_generic.html" %}

{% block content %}

    Test React component

    <hr>

    {% load static %}
    
    <div id ='root'></div>
    <script src="{% static 'ui-react-build/index-bundle.js' %}"> </script>

{% endblock %}

And these are the source JS files I am using for build (with npm run dev):

ui-react-src/App.js:

import {
  SearchBox,
} from "@elastic/react-search-ui";


export default function App() {
    return (
        <div className="App">
            <SearchBox />
        </div>
    );
}

ui-react-src/index.js:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

The last file is the one that seems to be giving me error (when I run npm run dev):

ERROR in ./ui-react-src/index.js 17:16
Module parse failed: Unexpected token (17:16)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| 
| const rootElement = document.getElementById("root");
> ReactDOM.render(<App />, rootElement);

What am I missing / doing wrong here?

SOLUTION:

Adding the following to the webpack.config.hs:

  module: {
    rules: [
      {
        test: /\.(mjs|js|jsx)$/,
        exclude: /node_modules/,
        loader: 'babel-loader',

        options: {
          presets: [
            '@babel/preset-react',
            {
              plugins: [
                '@babel/plugin-syntax-jsx'
              ]
            }
          ]
        },


      }
    ],
  }

and installing with npm the above mentioned @babel libs solved the problem.


Solution

  • I'm fairly confident this is because it can't parse <App /> in your js file (because it is jsx syntax) so your webpack.config.js needs a little tweak.

    Try updating your webpack configuration so that it looks like this.

    const path = require('path');
    
    module.exports = {
      entry: './ui-react-src/index.js',  // path to our input file
      output: {
        filename: 'index-bundle.js',  // output bundle file name
        path: path.resolve(__dirname, './reviewer/static/ui-react-build'),  // path to our Django static directory
      },
      module: {
        rules: [
          {
            include: /\.js$/,
            exclude: /node_modules/,
            use: {
              loader: "babel-loader"
            }
          }
        ]
      }
    };
    

    may need a further tweak depending on the file structure of your project.