Search code examples
reactjsantdvite

Error in [email protected] + [email protected] + react@16 : Unknown theme type: undefined, name: undefined


I am trying to migrate an old project into vite and I'm very close to success. There is just one bug which occurs in one of the javascript files of ant design when I deploy the app on server.

bug.

This is happening in the following function exported by [email protected]

export function withSuffix(name, theme) {
  switch (theme) {
    case "fill":
      return name + "-fill";
    case "outline":
      return name + "-o";
    case "twotone":
      return name + "-twotone";
    default:
      throw new TypeError("Unknown theme type: " + theme + ", name: " + name);
  }
}
icons.forEach(function (icon) {
  _this2.definitions.set(withSuffix(icon.name, icon.theme), icon);
});

I think this forEach loop is running on an array of undefined ([undefined, undefined..]) but I can't figure out why. I suspect it is due to some configuration I'm missing in my vite file or some other configuration.

If I change the code to this,

export function withSuffix(name, theme) {
  switch (theme) {
    case "fill":
      return name + "-fill";
    default:
    case "outline":
      return name + "-o";
    case "twotone":
      return name + "-twotone";
  }
}

My project runs perfectly on local as well as on server. Here are my package.json and vite.config.ts

`{
  "name": "ta",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "start": "vite --mode local",
    "start:dev": "vite --mode local-development",
    "start:qa": "vite --mode local-qa",
    "build:dev": "tsc && vite build --base=/ta-admin --mode development",
    "build:qa": "tsc && vite build --base=/ta-admin --mode qa",
    "build:staging": "tsc && vite build --base=/admin --mode staging",
    "build:prod": "tsc && vite build --base=/admin --mode production",
    "preview": "vite preview"
  },
  "dependencies": {
    "@ant-design/plots": "^1.2.4",
    "@material-ui/core": "^4.4.0",
    "@material-ui/icons": "^4.2.1",
    "@reduxjs/toolkit": "^1.9.2",
    "antd": "^3.19.3",
    "antd-virtual-select": "^1.1.2",
    "axios": "^1.3.0",
    "file-saver": "^2.0.5",
    "history": "^4.10.1",
    "html2canvas": "^1.4.1",
    "immutability-helper": "^3.0.1",
    "jquery": "^3.6.3",
    "jspdf": "^2.5.1",
    "keycloak-js": "^20.0.3",
    "less": "^4.1.3",
    "loadable-components": "^2.2.3",
    "lodash-decorators": "^6.0.1",
    "lodash.difference": "^4.5.0",
    "moment": "^2.29.4",
    "popper.js": "^1.16.1",
    "react": "^16.8.6",
    "react-dnd": "^9.4.0",
    "react-dnd-html5-backend": "^9.4.0",
    "react-dom": "^16.8.6",
    "react-html-parser": "^2.0.2",
    "react-intl": "^2.9.0",
    "react-intl-universal": "^2.6.11",
    "react-monaco-editor": "^0.31.0",
    "react-redux": "^8.0.5",
    "react-router-dom": "^5.3.4",
    "styled-components": "^5.3.6"
  },
  "devDependencies": {
    "@types/node": "^18.11.18",
    "@types/react": "^16.8.6",
    "@types/react-dom": "^18.0.10",
    "@types/react-router-dom": "^5.3.3",
    "@vitejs/plugin-react": "^3.0.0",
    "typescript": "^4.9.5",
    "vite": "^4.0.0"
  }
}

import { defineConfig, loadEnv } from "vite";
import react from "@vitejs/plugin-react";

const getApiHost = (npm_lifecycle_event: string) => {
  switch (npm_lifecycle_event) {
    default:
    case "start":
      return "http://localhost:8080";
  }
};
export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), "");
  const scriptArray = env?.npm_lifecycle_script?.split(" ") || [];
  const basePortion = scriptArray.find((scriptPortion) => {
    return scriptPortion.includes("--base");
  });
  let outDir = basePortion ? basePortion.split("/")[1] : "build";
  const target = getApiHost(env.npm_lifecycle_event);
  const runningLocally = mode.includes("local");

  return {
    plugins: [react()],
    ...(runningLocally
      ? {
          define: {
            global: {},
          },
        }
      : {}),
    server: {
      port: 3000,
      open: true,
      proxy: {
        "/api": {
          target,
          changeOrigin: true,
          secure: false,
        },
      },
    },
    css: {
      preprocessorOptions: {
        less: {
          javascriptEnabled: true,
          additionalData: "@root-entry-name: default;",
        },
      },
    },
    build: {
      outDir,
      commonjsOptions: {
        transformMixedEsModules: true,
      },
    },
  };
});

Solution

  • The problem is because of the "namespace import"

    https://github.com/ant-design/ant-design/blob/3.x-stable/components/icon/index.tsx#L4

    import * as allIcons from '@ant-design/icons/lib/dist';
    

    When the build is done for some reason vite adds the "allIcons.default" attribute and that breaks everything

    const allIcons = /*#__PURE__*/ _mergeNamespaces(
      {
        WindowsFill,
        WindowsOutline,
        WomanOutline,
        YahooFill,
        YahooOutline,
        YoutubeFill,
        YoutubeOutline,
        YuqueFill,
        YuqueOutline,
        ZhihuCircleFill,
        ZhihuOutline,
        ZhihuSquareFill,
        ZoomInOutline,
        ZoomOutOutline,
        default: dist$4,
      },
      [dist$4]
    );
    

    Four hours later

    I found the reason for the problem

    https://github.com/rollup/plugins/blob/54c1a7cd6754e2f7b03615529869fd6711fc17fe/packages/commonjs/src/generate-exports.js#L229

    I created a plugin to correct this problem:

    vite.config.ts

    function antDesignIconsFix() {
      return {
        name: '@ant-design-icons-fix',
        transform(code, id) {
          if (id.includes('@ant-design/icons/lib/dist.js'))
            return code.replace(', dist as default', '')
          return code
        },
      }
    }
    
    export default defineConfig({
        ...,
        build: {
          rollupOptions: {
            plugins: [antDesignIconsFix()],
          },
        }
    })