Webpack编译库在导入到其他项目时保留文件夹结构

ffscu2ro  于 2023-08-06  发布在  Webpack
关注(0)|答案(3)|浏览(137)

我正在创建一个库,它可以导出大量的React组件,以及一些用于公司内多个项目的TypeScript实用程序。但是,除了从库的根目录导出所有内容之外,我似乎不能做任何其他事情。
我有以下文件夹结构。.tsxutils.ts 文件仅导出命名属性,根 index.ts 文件包含export * from './Button';等。然后src/index.tsexport * from './ui',等等。

src/
  ui/
    Button/
      Button.tsx
    Input/
      Input.tsx
    index.ts
  utils/
    myUtilFunc1.ts
    myUtilFunc2.ts
    index.ts

字符串
使用下面的Webpack配置,

const path = require("path");

module.exports = {
  entry: "./src/index.ts",
  resolve: {
    extensions: [".ts", ".tsx", ".js"],
  },
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
    library: "@company/library",
    libraryTarget: "umd",
    umdNamedDefine: true,
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: "ts-loader",
        exclude: /node_modules/,
      },
    ],
  },
  externals: {
    react: "react",
    "react-dom": "react-dom",
  },
};


以及以下package.json属性:

"main": "dist/main.js",
"module": "dist/main.js",
"types": "dist/types/index.d.ts",


当我在另一个项目中使用这个库时,我可以根据需要导入,如下所示:import { Button, myUtilFunc2 } from "@company/library"
但我想这样导入:
import { Button } from "@company/library/ui"import {myUtilFunc2 } from "@company/library/util"
我知道这应该是可能的,因为MUI和其他库都有。我正在使用Webpack,因为我尝试了这将汇总,甚至使用Lerna设置monolithic repository(这工作得很好,但我只是觉得我不需要为此构建两个npm包,它们可以包含在一个包中)。

nqwrtyyt

nqwrtyyt1#

实现目标的一种可能方法是使用package.json文件中的exports字段,它允许您在使用import "package"import "package/sub/path"等模块请求时声明应使用哪个模块。Webpack 5及更新版本支持此功能。
例如,您可以在package.json中包含以下内容:

{
  "name": "@company/library",
  "main": "dist/main.js",
  "module": "dist/main.js",
  "types": "dist/types/index.d.ts",
  "exports": {
    ".": "./dist/main.js",
    "./ui": "./dist/ui/index.js",
    "./utils": "./dist/utils/index.js"
  }
}

字符串
这样,你可以像这样导入子模块:

import { Button } from "@company/library/ui";
import { myUtilFunc2 } from "@company/library/utils";


根据webpack documentation
当指定了exports字段时,只有这些模块请求可用。任何其他请求都将导致ModuleNotFound错误。
因此,如果您有太多的项目模块,这可能是乏味或不切实际的。
在这种情况下,您可以尝试使用一些语法功能,允许您指定多个或动态模块请求,例如:

  • 使用结果数组为同一模块请求提供替代方案。
  • 使用通配符(*)匹配任何值并在结果中替换它。
  • 在属性的末尾使用斜杠(/)将带有此前缀的请求转发到旧的文件系统查找算法。

要了解更多信息,请参阅Webpack 5通用语法,替代方案。
但它有一些兼容性问题。

  • 并非所有模块系统或工具都支持导出字段。例如,Node.js仅从版本12+开始支持它,并且仅适用于ES模块。(你可以在这里获得这些信息)。

您可以从this resource了解有关exports字段及其语法的更多信息。

ftf50wuq

ftf50wuq2#

您可以使用Webpackalias进行存档。
配置您的Webpack,将 @company 别名解析为组件所在的相应路径。这可以通过在Webpack配置中添加以下内容来完成:

const path = require('path');

module.exports = {
  // ...
  resolve: {
    alias: {
      '@company': path.resolve(__dirname, 'path/to/company/library/ui'),
    },
  },
  // ...
};

字符串
但你需要确保遵循相同的结构:

- company
      - library
        - ui
          - Button.js (Button comp)


那么这个应该行得通:

import React from 'react';
import { Button } from '@company/library/ui';

1mrurvl1

1mrurvl13#

要在从库中导入元件和实用程序时获得所需的文件夹结构,需要对项目的配置和文件结构进行一些调整。您可以使用Webpack配置中的resolve.alias属性为特定目录创建别名,以便可以直接导入它们。
以下是如何修改Webpack配置以实现所需的导入语法:
更新您的Webpack配置:

const path = require("path");

module.exports = {
  entry: "./src/index.ts",
  resolve: {
    extensions: [".ts", ".tsx", ".js"],
    alias: {
      "@company/library": path.resolve(__dirname, "src"),
    },
  },
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
    library: "@company/library",
    libraryTarget: "umd",
    umdNamedDefine: true,
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: "ts-loader",
        exclude: /node_modules/,
      },
    ],
  },
  externals: {
    react: "react",
    "react-dom": "react-dom",
  },
};

字符串
修改从src/index.ts导出的方式:

// src/index.ts
export * from "./ui";
export * from "./utils";


更新文件结构:

src/
  ui/
    Button/
      Button.tsx
      index.ts // Add index.ts to re-export Button.tsx
    Input/
      Input.tsx
      index.ts // Add index.ts to re-export Input.tsx
    index.ts   // Add index.ts to re-export components
  utils/
    myUtilFunc1.ts
    myUtilFunc2.ts
    index.ts   // Add index.ts to re-export utilities
  index.ts     // Re-export from ui and utils


通过这些更改,您应该能够根据需要导入组件和实用程序:

// Importing components
import { Button } from "@company/library/ui";
import { Input } from "@company/library/ui";

// Importing utilities
import { myUtilFunc1, myUtilFunc2 } from "@company/library/utils";


这将为您提供所需的文件夹结构,同时将所有内容保留在单个npm包中。Webpack配置中的别名允许您使用@company/library导入路径,该路径指向库的根src目录。每个目录中的index.ts文件用于重新导出组件和实用程序,使它们可以从各自的文件夹中轻松访问。

相关问题