How to config Nextjs for Babel Plugin Macros like twin.macro without disabling SWC compiler.

How to config Nextjs for Babel Plugin Macros like twin.macro without disabling SWC compiler.

In this article I've shared with you that how I used twin.macro + emotion without disabling the SWC compiler in the Nextjs 12

I recently made a theme for blogger with Nextjs v12 that I used twin.macro with emotion plugin. I got a bunch error about babel-plugin-macros when I started the server.

// Error
 ./node_modules/twin.macro/node_modules/babel-plugin-macros/node_modules/cosmiconfig/dist/getDirectory.js
// ...

Also in the console I had another error: SWC Failed to Load, because I've used .babelrc for twin.macro.

After searching, I found that the nextjs uses Rust-based compiler SWC to compile JavaScript/TypeScript. This new compiler is up to 17x faster than Babel when compiling individual files and up to 5x faster Fast Refresh.

Finally for fixing the issues, I deleted the .babelrc and move my babel config to nextjs.config.

If you have same issue like me, so first of all create a next-twin.js file. then replace the directories with your directories that included the emotion & twin.macro.

const path = require("path");
const { NextConfig } = require("next");

module.exports = function withTwin() {
  return (nextConfig) => {
    return {
      ...nextConfig,

      webpack(config, options) {
        const { dev } = options;

        // replace your directories
        const componentsDir = path.resolve(__dirname, "_includes");
        const pagesDir = path.resolve(__dirname, "pages");
        const layoutDir = path.resolve(__dirname, "_layout");

        config.module = config.module || {};
        config.module.rules = config.module.rules || [];
        config.module.rules.push({
          test: /\.(tsx|jsx)$/,
          include: [componentsDir, pagesDir, layoutDir],
          use: [
            options.defaultLoaders.babel,
            {
              loader: "babel-loader",
              options: {
                sourceMaps: dev,
                plugins: [
                  [
                    require.resolve("babel-plugin-macros"),
                    {
                      twin: {
                        perest: "emotion",
                      },
                    },
                  ],
                  [
                    require.resolve("@babel/plugin-syntax-typescript"),
                    { isTSX: true },
                  ],
                ],
              },
            },
          ],
        });

        if (typeof nextConfig.webpack === "function") {
          return nextConfig.webpack(config, options);
        } else {
          return config;
        }
      },
    };
  };
};

After that, edit the next.config.js file.

  • Nextjs config with one plugin:
// next.config.js
const withTwin = require('./next-twin.js');
const nextConfig = {
  reactStrictMode: true,
  // ...
};
module.exports = withTwin(nextConfig);
  • Nextjs config with multiple plugins:
const withPlugins = require('next-compose-plugins');
const { withContentlayer } = require('next-contentlayer');
const withTwin = require('./next-twin.js');
const nextConfig = {
  reactStrictMode: true,
  // ...
};
const contentLayer = withContentlayer()({
  nextConfig,
});
const twin = withTwin(nextConfig);
module.exports = withPlugins([contentLayer, twin], nextConfig);

Thank you for reading!

Thank you for reading my blog. Feel free to subscribe to my weekly newsletter and let me know if you have any questions.