How to build a Shopify theme app extension with React, Tailwind and Webpack
Get going from scratch with a few simple steps
An exemplary projects with all files mentioned in this article can be found on this Github Repository.
While I was in the process of building a Shopify App which integrates into the storefront, I learned that extensions are completely based on the Liquid templating language.
Since I already have experience with React development, I was looking for a simple way to integrate a React app into my extension. After looking around for a bit, I found some loose ideas and Github repositories using Vite (credits to https://github.com/iskurbanov/theme-app-extension-react).
But those repositories do not show the implementation process from scratch, which would be very helpful for people who are in the middle of development. Furthermore, I used the Remix template provided by Shopify for my project, which uses Webpack for bundling already. Since I couldn’t find instructions on how to inject a React project into Liquid via Webpack, I wrote this article to help other people achieve this more easily in the future. So without further detours, this is how I did it.
Contents
Create a Shopify theme extension
Create a new React app (or use an existing one)
Install and configure Tailwind
Install and configure Webpack
Deploy!
Create a Shopify theme extension
Navigate into your project folder and run the following command:
npm run shopify app generate extension
npm run deploy
Select Theme App Extension
and provide a name for your extension. This creates an extensions
folder along with a folder for your extension in it. In this folder, a couple of files with a simple extension example are generated as well. Open the Liquid file in the assets
folder and replace the contents with the following code:
<span>This is Liquid</span>
<div id="container"></div>
{% schema %}
{
"name": "React Extension Tutorial",
"target": "section",
"javascript": "react-extension.js",
"settings": []
}
{% endschema %}
The schema section will bind our bundled React project to the Liquid file, while ‘container’ div acts as its root element.
The detailed process to create a Shopify theme extension is described in the Shopify Developer Documentation.
Create a new React app (or use an existing one)
Navigate into your projects root folder and execute the following commands (replace my-app
with your react extensions name).
npx create-react-app my-app
cd my-app
npm start
Navigate into the src
folder in your newly created React project, open the index.js file and replace its contents with the following code:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('container'));
root.render(
<span className="text-blue-400">
This is React!
</span>
);
This will specify the previously created ‘container’ div in the Liquid file as the root element of the React app.
The detailed process to create a React app is described in the React Documentation.
Install and configure Tailwind
Install the following packages:
npm tailwindcss postcss autoprefixer
Create a tailwind tailwind.config.js file with the following contents in the root of your React project:
module.exports = {
content: ["./src/**/*.{js,jsx}", "./public/index.html"],
theme: {
extend: {
colors: {
primary: "#1B73E8",
},
},
},
plugins: [],
};
Add Tailwind classes to index.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
Install and configure Webpack
Install the following packages packages:
npm install webpack webpack-cli @babel/cli @babel/core @babel/preset-env @babel/preset-react babel-loader css-loader postcss-loader style-loader terser-webpack-plugin
Create webpack.config.js with the following content in the root folder of your React project:
const TerserPlugin = require("terser-webpack-plugin");
const path = require("path");
module.exports = {
mode: "production",
entry: "./src/index.js",
output: { path: path.resolve(__dirname, "../extensions/react-extension/assets"), filename: "react-extension.js" },
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/,
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader", "postcss-loader"],
},
],
},
optimization: {
minimizer: [
new TerserPlugin({
extractComments: false,
}),
],
},
};
This configuration will bundle your whole React package into one Javascript file, which will be created in your extensions/react-extension/assets
folder. Note that depending on your further development its possible that this configuration will not be sufficient anymore (e.g. because of specific file types, which require special loaders, etc.).
Create a .babelrc with the following content in the root folder of your React project:
{ "presets":["@babel/preset-env", "@babel/preset-react"] }
Change build command command in your package.json to webpack:
"scripts": {
"build": "webpack",
},
Now you simply have to bundle your react project using the command we just added:
npm run build
Note that you have to run this everytime you commit changes to your React project! I’ve noticed that sometimes the hot reload doesn’t catch on to some changes after bundling the project. If this happens to you, either try to restart you Shopify app or deploy another version of it.
Deploy!
Lastly, to publish the changes made to your Shopify expansion, simply run the deployment command again:
npm run deploy
Thats it! You should now be able to add the theme app extension to your Shopify theme as an app block:
After adding the extensions app block, the two spans from the Liquid file and React project should now be displayed on the chosen page.
I hope this small tutorial helped you with implementing React into your Shopify theme app extension. If thats the case or you have any questions, feel free to comment or connect with me on social media: