Retrieve custom tailwind overrides from an endpoint after the build process is complete

Currently, I am working on a Next.js project utilizing Tailwind CSS. During the build process, I load in a default configuration, but I also need to wait for an API response to retrieve custom styles from an endpoint.

Below is my current setup, but it seems like I might be approaching this the wrong way as I am encountering webpack errors:

Error: Cannot find module './services/getThemeStyles'

// ./tailwind.config.js

// Default styles
const theme = require('./lib/themes/default/tailwind/tailwind.config');

// Website custom styles
const custom = require('./services/getThemeStyles');

module.exports = {
    ...theme, // Deep merge of theme and custom
    content: ['./lib/**/*.{js,ts,jsx,tsx}', './pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
};
// ./services/getThemeStyles.ts

// Fake temporary endpoint; would fetch data from an API when live.
const theme = require('/data/theme');

export default async function getThemeStyles(): Promise<any> {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(theme);
        }, 1);
    });
}

// ./data/theme.ts

const Theme = {
    extend: {
        colors: {
            'banner-background': 'rgb(220,220,0)'
        }
    }
}
export default Theme;

Has anyone encountered this issue before or can provide assistance?

Edit

I have revised my approach by setting up a Node server to make data retrieval more authentic. As a result, my tailwind.config.js now appears as follows:

const fetch = require('node-fetch');
const merge = require('merge-deep');

module.exports = (async function() {
    let theme = require('./lib/themes/default/tailwind/tailwind.config');

    const response = await fetch('http://localhost:5000/data');
    const data = await response.json();
    
    return {
        ...merge(theme, data),
        content: ['./lib/**/*.{js,ts,jsx,tsx}', './pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
    }
})();

However, I am facing an issue where I cannot use await before fetch because it is not within an async function, causing the module to be exported before the request is completed.

Answer №1

Just solved a problem that others might find useful to know!

I managed to achieve this by using a next plugin (although it might be doable without one) to download a file before building, and then importing this file into the tailwind config.

The only drawback is encountering an infinite loop when running next dev, so I recommend pulling the file only during production builds.

Fortunately, this approach works well for my specific scenario.

// next.config.js

const WebpackBeforeBuildPlugin = require('before-build-webpack');
const fs = require('fs');

/** @type {import('next').NextConfig} */
const nextConfig = {
    reactStrictMode: true,
    webpack: (config, options) => {

        if (process.env.NODE_ENV === 'development') {
            return config;
        }

        // Important: return the modified config
        config.plugins.push(new WebpackBeforeBuildPlugin(async function(stats, callback) {
            const response = await fetch("http://localhost:5000/data");
            const dt = await response.json();

            fs.writeFileSync('./.tmp/custom.json', JSON.stringify(dt));

            callback();
        }))
        return config;
    },
};

module.exports = nextConfig;
// tailwind.config.js

const merge = require('merge-deep');

const theme = require('./lib/themes/default/tailwind/tailwind.config');
let custom = null;

// Try merging any custom styles with the selected theme
try {
    custom = require('./.tmp/custom.json');
} catch (e) {
    custom = [];
}

module.exports = {
    ...merge(theme, custom),
    content: ['./lib/**/*.{js,ts,jsx,tsx}', './pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble displaying images in Express JS

Here are the lines of code that I wrote in Express: res.write("The current temperature is "+temp+". "); res.write("Weather is currently "+weatherDes); res.write("<img src=" +imageURL+ ">"); res.send() ...

What sets apart ajax calls from getJSON requests?

I am encountering an issue with my Web.API app being served from the URL http://server/application. When I try to pull data from the servers using a GET request on the client side, I am facing unexpected behavior. The following code snippet works as expec ...

Issue encountered in Three.js related to the THREE.ObjectLoader

Help Needed with Three.ObjectLoader. I am exporting a scene in JSON Format 4.3, containing geometries, materials, and lights. The scene opens error-free in the Three.js Editor. Working on firefox with Three.js r70 master. View the generated json here: htt ...

using jquery to retrieve values from a json object

After making an AJAX call, I received this JSON data: [ {message:"haha", type:"error"}, {message:"nice work", type:"success"}, {message:"closed.", type:"success"} ] My goal is to determine if any of the items have a type of error. While I understand ...

Is the Typescript index signature limited to only working with the `any` type?

I recently made changes to my interface and class structure: export interface State { arr : any[]; } export const INITIAL_STATE: State = { arr: [] }; This updated code compiles without any issues. Now, I decided to modify the Interface to incl ...

Problems encountered with nested AJAX calls and the $.when.apply function handling deferred promises efficiently

I am attempting to create a triple nested series of AJAX calls, as shown in the basic structure below (fail calls have been omitted). Progress is being made up to the second level with the eventCalls. The final when.apply.done only triggers after every si ...

Creating Responsive Image Map Areas in HTML

Implementing image maps on my website has been a challenge because of the lack of responsiveness. I am struggling to adjust the size of map areas when resizing the window. If anyone can help with this issue, I am open to using either JavaScript or CSS met ...

Encountered an issue with resolving the module specifier while attempting to import a module

Whenever I attempt to import a module, I consistently encounter this error message Failed to resolve module specifier "mongodb". Relative references must start with either "/", "./", or "../". and I have searched ext ...

Switching from React Router version 3 to 4.1.1, what is the best way to organize my routes separately from my app.jsx file?

After successfully running a site with React Router 3.0.5, I decided to update to React Router 4.1.1 which resulted in some errors. My main goal is to have the root route as "/" leading to the app component, while other routes are directed elsewhere. An e ...

Three.js brings life to reflections through dynamic rendering

Embarking on my coding journey with JavaScript and exploring Three.js I created an experiment using shaders and an environment map (http://jsfiddle.net/gnazoa/3hxrky6k/1/) Through a tutorial on the Three.js website, I discovered how to achieve reflection ...

Live AJAX inquiries in progress

Is there a way to track the number of active AJAX requests in jQuery, Mootools, or another library similar to Prototype's Ajax.activeRequestCount? I am looking for a method that can be used across different libraries or directly through XMLHttpRequest ...

Joi validation that focuses on required array elements while disregarding nested keys

Why is my Joi array required validation not detecting an empty array? I have an array called userData that contains objects with keys dateMilli and value. Despite adding required validations everywhere, passing an empty array [] for userData does not resul ...

Issue with the close button on ngb-alert not functioning properly

As I develop my website, I have incorporated an ngb-alert component to display an alert message to users upon login. While the alert itself is functioning properly, I have encountered an issue with the close button being misaligned, and I am struggling to ...

Continuously update the content within a paragraph using jQuery

After searching for a jQuery animation that would constantly change text within a paragraph, I stumbled upon a solution at this link : Text changing with animation jquery. However, I encountered a challenge as I wanted to include a bootstrap button beneath ...

jQuery setInterval is not functioning as expected

I need help comparing two password fields and displaying a Popover message if they do not match. HTML <div class="form-group col-lg-6"> <label>Password</label> <input type="password" class="form-control" name="password" id="p ...

How can I detect numeric strings in any input or textarea using an event listener?

Interested in creating a clever script or browser extension that, when the first four digits of my credit card are entered, automatically opens a tab with distracting content like porn to help curb unnecessary spending. Can this innovative solution be im ...

Develop a unique splitter code that utilizes pure javascript and css, allowing users to drag and drop with precision

I am facing an issue with setting the cursor above my drop panel, as it results in a flicker effect. How can I set the cursor for my example to work properly? I have tried multiple different approaches to make this work. Although I am using the provided ...

(IONIC) Issue with MomentJS locale functionality not functioning properly post-building process

I am currently utilizing the IONIC Framework and incorporating Moment.js for handling dates. I have set all strings to be in French using the code below: moment.locale('fr'); Interestingly, this works perfectly on the "serve" mode of Ionic. Ho ...

What techniques did infusion.com use to distort the elements? The CSS file doesn't appear to incorporate any skewing effects, yet the menu still appears skewed

I'm curious to know how the developers over at were able to create such a unique skew effect on everything, including the sub-menu which opens up skewed. The text remains straight, and there doesn't seem to be any image cropping involved. Hoveri ...

When employing JQuery toggle, why does the script only condense the initial value in my iterator?

Upon testing this code on my server, I encountered an issue where only the first value in my iterated list would minimize or maximize when clicking on the options. How can I modify it so that all values in the list can be minimized and ...