【问题标题】:WebPack-React-TypeScript: loading CSS and exporting typesWebPack-React-TypeScript:加载 CSS 和导出类型
【发布时间】:2026-01-09 08:40:01
【问题描述】:

问题

我正在构建一个 UI 组件库以在我的项目中重复使用。该库是用 TypeScript 和 React 的 .less 编写的,并使用 WebPack 构建。

.
├── README.md
├── dist
├── index.js
├── package-lock.json
├── package.json
├── src
│   ├── Span
│   │   ├── Span.less
│   │   └── index.tsx
│   └── Tag
│       ├── Tag.less
│       └── index.tsx
├── tsconfig.json
├── types
│   └── custom.d.ts
└── webpack.config.js

每个组件都被导出为一个命名模块。在 WebPack 中,我将每个 .ts 文件作为一个条目,将其传递给 ts-loader 并将其输出到另一个文件夹中的 dist 文件夹,其中包含模块的名称。然后我处理 TypeScript 声明文件并将它们发送到这个文件夹结构。 使用根文件夹中的 index.js 文件,我从其文件夹中导入每个模块,并使用 commonjs 语法将其导出为命名模块。

// ./index.js
exports.Span = require('./dist/Span').Span;
exports.Tag = require('./dist/Tag').Tag;

在 package.json 中,我将我的 npm 模块的 files 声明为 [ "/dist", "index.js" ];因此,发布的 npm 模块将是:

.
├── dist
│   ├── Span
│   │   ├── index.d.ts
│   │   ├── index.js
│   │   └── index.js.map
│   └── Tag
│       ├── index.d.ts
│       ├── index.js
│       └── index.js.map
└── index.js

最后,我可以从我的客户端代码中将这些组件导入为命名模块,例如:

// client code
import { Span, Tag } from 'components_library_example';

我的问题是:

  1. 目前没有加载css文件。

    • 我的客户端代码无法读取内联的 css 代码有什么原因吗?
    • 另一种解决方案是使用MiniCssExtractPlugin 提取css,并从index.js 导入样式;理论上很容易,但实际上,这似乎是不可能的。有什么好的方法吗?
  2. 目前,当我导入组件时,打字稿无法识别声明文件,因此我丢失了所有类型。

    • ¿如何导出 index.js 中的模块以保持对 .d.ts 声明文件的访问?

谢谢!


注意:我的 webpack 配置文件:

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  name: 'server',
  entry: {
    Span: path.join(__dirname, 'src/Span/index.tsx'),
    Tag: path.join(__dirname, 'src/Tag/index.tsx'),
  },
  output: {
    filename: '[name]/index.js',
    path: path.join(__dirname, 'dist'),
    libraryTarget: 'commonjs2',
    globalObject: "(typeof self !== 'undefined' ? self : this)", 
    library: 'MyLib',
    umdNamedDefine: true,
  },
  target: 'node',
  devtool: '#source-map',
  externals: [nodeExternals(), 'react'],
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.svg'],
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx|ts|tsx)$/,
        loader: ['ts-loader'],
        exclude: /node_modules/,
      },
      {
        test: /\.(less|css)$/,
        use: ['css-loader', 'less-loader'],
      },
      {
        test: /\.svg$/,
        use: ['@svgr/webpack'],
      },
    ],
  },
  stats: 'errors-only',
  plugins: [
    new CleanWebpackPlugin({
      dry: false,
      verbose: true,
      protectWebpackAssets: false,
      cleanOnceBeforeBuildPatterns: [path.join(__dirname, 'dist', '/**/*')],
    }),
  ],
};

【问题讨论】:

    标签: javascript reactjs typescript webpack redux


    【解决方案1】:

    首先,webpack is not the most suitable tool for making libraries 目前,您的每个组件都包含许多重复的运行时内容。 将组件转换为 es 模块可能就足够了,因为您可能会将它们捆绑为某些应用程序的一部分。

    目前没有加载 css 文件。 我的客户端代码无法读取内联的 css 代码有什么原因吗?

    您的样式包含在捆绑的文件中,但不会应用。样式应该以某种方式注入到页面中,通常,style-loaded 用于此目的。注入是一种副作用,因此您的库不会是可摇树的。

    根据您将如何使用该库,我建议避免在组件中导入样式以及以下之一:

    1. 如果消费应用使用 webpack 并且将处理自己的 less 文件,则将它们作为 less 文件提供给消费者
    2. 处理更少的文件并公开一个可以以任何方式包含到 index.html 的 css 文件。它可能适合没有构建过程的消费者,比如说简单的静态 html。是的,这似乎不太可能,因为您的组件需要做出反应:)
    3. 使用一些css-in-js 解决方案。这是 2020 年大多数 React 库使用的方式。

    目前,当我导入组件时,打字稿无法识别声明文件,因此我丢失了所有类型。 您可以在库的根目录中添加index.d.ts 文件并重新导出那里的所有组件类型

    export * from './src/Span';
    export * from './src/Tag';
    

    如果您想将它们放在 package.json 中的其他位置 you need to specify types field

    【讨论】:

    • 谢谢@shlang。然后我将从 src/index.ts 中导入我所有的组件,将其声明为 webpack 的入口,这将输出 /dist/index.js/dist/index.d.ts/dist/index.css/dist/[module_name]/index.d.ts。我现在将使用 webpack,但会在某个时候将此构建重构为 webpack。再次感谢!