Architecting a Drupal and React Project: A Step-by-Step Guide
Hey everyone in this article I will explain the best project configuration for Drupal as your backend and React as your frontend framework, we are going to see how we will keep react project folder inside drupal folder structure and much more.
Folder structure -
.
└── Drupal/
└── themes/
└── custom/
└── [your-theme]/
└── REACT
Yeah its simple just keep your react folder inside the theme you are going to use.
Attaching the REACT build to your HTML page -
Here is the complex part when you make a build from react using the command -
npm run build
You will always get a hashed file name like this main.34567890abcdef.js, there is no problem in using this as your build js, but you will have to update this name inside your [your-theme].libraries.yml everytime you build your project and thats a problem.
custom:
version: 1.x
js:
react/build/main.34567890abcdef.js: {minified: true }
css:
theme:
react/build/main.34567890abcdef.css: {minified: true}
dependencies:
- core/jquery
- core/drupalSettings
So to overcome this problem we need to find a way to keep the file name constant all the times so your developement process is seamless.
I tried searching for this solution but I couldn't find any with using react out of the box, maybe I didn't searched enough but here is a work around -
Recommended by LinkedIn
Custom build process using webpack -
I dont know what is the industry standard for this thing but I will call it "CUSTOM BUILD PROCESS"
So for this all we have to do is write this webpack config file which is going to -
And other than these two things we have url-loader, file-loader, sass-loader and css extractor plugin, you can read more about webpack from youtube.
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const minicss = require("mini-css-extract-plugin");
module.exports = ({ mode } = { mode: "production" }) => {
console.log(`mode is: ${mode}`);
return {
mode,
entry: "./src/index.js",
output: {
publicPath: "/",
path: path.resolve(__dirname, "build"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.jpe?g|png|svg$/,
exclude: /node_modules/,
use: ["url-loader", "file-loader"],
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.css$/i, // Matches all CSS files
use: [
minicss.loader,
"css-loader",
"sass-loader",
'postcss-loader'
],
},
],
},
plugins: [
new minicss(),
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
],
};
};
Now as you can see we are asking the compilation process to keep the name of built javascript as bundle.js all the time which solves our problem.
After this you have to write few commands inside your package.json file which will use webpack to build the project for you.
{
"name": "poc",
"version": "0.1.0",
"private": true,
"dependencies": {
"@headlessui/react": "^1.7.18",
"@heroicons/react": "^2.1.1",
"@paypal/react-paypal-js": "^8.3.0",
"@tailwindcss/forms": "^0.5.7",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.6.8",
"flowbite-react": "^0.7.3",
"postcss-loader": "^8.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-google-recaptcha": "^3.1.0",
"react-lazyload": "^3.2.1",
"react-phone-number-input": "^3.3.9",
"react-router-dom": "^6.22.3",
"react-scripts": "5.0.1",
"sass": "^1.77.3",
"sass-loader": "^14.2.1",
"swiper": "^11.1.8",
"tailwindcss": "^3.4.1",
"web-vitals": "^2.1.4",
"webpack": "^5.91.0"
},
"scripts": {
"webpack": "webpack",
"watch_live": "webpack --watch --env mode=development",
"webpack-dev-server": "webpack-dev-server",
"dev": "npm run webpack-dev-server -- --env mode=development",
"prod": "webpack --watch --env mode=production",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/plugin-transform-class-properties": "^7.24.6",
"babel-loader": "^9.1.3",
"css-loader": "^7.1.2",
"file-loader": "^6.2.0",
"mini-css-extract-plugin": "^2.9.0",
"url-loader": "^4.1.1",
"webpack-cli": "^5.1.4"
}
}
This script will make a development build and to use it just write npm run watch_live -
"watch_live": "webpack --watch --env mode=development"
Thanks for reading this article hope you learnt somthing from this and please drop a comment for any improvements.
Insightful!