Search code examples
javascriptreactjsviterollupjs

How to build a multi-module react-library where components can be imorted via import { MyComponent } from "shared-ui/my-component"


I built a react component library using Vite.js. Here's the vite-config:

// vite.config.js
export default defineConfig({
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
  build: {
    lib: {
      entry: resolve(__dirname, "src/index.js"),
      name: "SharedUI",
      formats: ["es"],
      fileName: "shared-ui",
    },
    rollupOptions: {
      plugins: [peerDepsExternal()],
      output: {
        globals: {
          react: "React",
        },
      },
    },
  },
});

Here's my folder structure:

shared-ui/
├─ src/
|  ├─ index.js
│  ├─ components/
│  │  ├─ index.js
│  │  ├─ select
|  |  | ├─index.js
|  |  | ├─select.component.jsx
│  │  ├─ input
|  |  | ├─index.js
|  |  | ├─input.component.jsx
├─ vite.config.js
├─ dist

The shared-ui/src/index.js-file contains the following:

// shared-ui/src/index.js
export * from "./input";
export * from "./select";

The vite build command created one file shared-ui.js, which lands in dist folder.

If I install the package (in my case in an app using pnpm workspace) I can import the Select-component using:

import { Select } from "shared-ui";

and it works.

But I want to achieve imports like:

import { Select } from "shared-ui/select";

How is that possible? I tried using rollup-plugin-includepaths like

// vite.config.js
import includePaths from "rollup-plugin-includepaths";

let includePathOptions = {
  include: {},
  paths: ["src/components"],
  external: [],
  extensions: [".js", ".jsx"],
};

//... vite rollupOptions->plugins-option
plugins: [includePaths(includePathOptions), peerDepsExternal()]
//...

But the import fails.

Thanks


Solution

  • Once you know it is easy:

    export default defineConfig({
      resolve: {
        alias: {
          "@": path.resolve(__dirname, "./src"),
        },
      },
      build: {
        lib: {
          entry: {
            "single-select": resolve(
              __dirname,
              "src/components/single-select/index.js"
            ),
            input: resolve(
              __dirname,
              "src/components/input/index.js"
            ),
          },
          name: "SharedUI",
          formats: ["es"],
        },
        rollupOptions: {
          plugins: [peerDepsExternal()],
          output: {
            globals: {
              react: "React",
            },
          },
        },
      },
    });
    

    You also have to set the correct exports in the package.json.