Webpack 编译库在导入到另一个项目时保留文件夹结构

问题描述 投票:0回答:3

我正在创建一个库,它导出大量 React 组件以及一些用于我公司内多个项目的打字稿实用程序,但是除了从库的根导出所有内容之外,我似乎无法做任何其他事情。

我有以下文件夹结构,.tsx和utils.ts仅导出命名属性,根index.ts包含

export * from './Button';
等... 那么
src/index.ts
就是
export * 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 设置了一个 mono 存储库(效果很好,但我只是觉得我不需要为此构建 2 个 npm 包,它们都可以包含在一个包中)

reactjs webpack lib
3个回答
1
投票

您可以使用 webpack alias

进行存档

配置您的 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';

0
投票

实现目标的一种可能方法是使用

package.json
文件中的导出字段,该字段允许您在使用
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文档

当指定exports字段时,只有这些模块请求 可用的。任何其他请求都会导致 ModuleNotFound 错误。

因此,如果您有太多项目模块,这可能会很乏味或不切实际。

在这种情况下,您可以尝试使用一些允许您指定多个或动态模块请求的语法功能,例如:

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

要了解更多信息,请参阅 Webpack 5 通用语法替代方案

但它有一些兼容性问题。

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

您可以从此资源了解有关导出字段及其语法的更多信息。


0
投票

为了在从库中导入组件和实用程序时获得所需的文件夹结构,您需要对项目的配置和文件结构进行一些调整。您可以使用 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 文件用于重新导出组件和实用程序,使它们可以从各自的文件夹轻松访问。

© www.soinside.com 2019 - 2024. All rights reserved.