You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React组件库ESM打包Tree Shaking失效问题求助

React组件库ESM打包Tree Shaking失效问题

我正在开发React组件库,使用Webpack打包为ESM格式,但组件库无法实现Tree Shaking。

库的使用方式

import {Button, Input} from "my-lib"

通过source-map-explorer等分析工具查看项目构建详情时,发现最终构建文件包含了整个组件库,而非仅引入的Button和Input组件。

以下是组件库的相关配置:

Webpack配置

const fs = require("fs");
const { join, resolve } = require("path");
const TerserPlugin = require("terser-webpack-plugin");
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
const webpack = require("webpack");
// const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");

const getPackageJson = function (...args) {
    const packageJSON = JSON.parse(
        fs.readFileSync(join(__dirname, "./package.json"))
    );
    if (!args.length) {
        return packageJSON;
    }
    return args.reduce((out, key) => {
        out[key] = packageJSON[key];
        return out;
    }, {});
};

const {
    name: pkgName,
    version,
    description,
    license,
    author,
    homepage,
} = getPackageJson(
    "name",
    "version",
    "description",
    "license",
    "author",
    "homepage"
);

const banner = ` Name: ${pkgName}
 Version: ${version}
 Description: ${description}
 Author: ${author}
 Homepage: ${homepage}

 Copyright (c) ${author.replace(/ *<[^)]*> */g, " ")} and project contributors.

 This source code is licensed under the ${license} license found in the LICENSE file in the root directory of this source tree.`;

// common
const common = {
    mode: "production",
    devtool: "source-map",
    entry: "./src/index.ts",
    externals: ["react"],
    resolve: {
        plugins: [new TsconfigPathsPlugin()],
        extensions: [".js", ".jsx", ".ts", ".tsx", ".css", ".scss"],
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ["style-loader", "css-loader"],
            },
            {
                test: /\.scss$/i,
                use: ["style-loader", "css-loader", "postcss-loader"],
            },
            {
                // Include ts, tsx, js, and jsx files.
                test: /\.(ts|js)x?$/,
                exclude: /node_modules/,
                use: [{ loader: "ts-loader" }],
            },
            {
                test: /\.m?js$/,
                resolve: {
                    fullySpecified: false,
                },
            },
        ],
    },
    plugins: [
        // new CleanWebpackPlugin(),
        new webpack.BannerPlugin(banner),
        new BundleAnalyzerPlugin(),
    ],
    optimization: {
        minimize: true,
        minimizer: [
            new TerserPlugin({
                // parallel: true, // Multi-threading
                extractComments: false,
            }),
        ],
    },
};


module.exports = [
    {
        output: {
            path: resolve(__dirname, "dist"),
            filename: "[name].common.js",
            library: {
                type: "commonjs",
            },
        },
        ...common,
    },
    {
        output: {
            path: resolve(__dirname, "dist"),
            filename: "[name].umd.js",
            libraryTarget: "umd",
        },
        ...common,
    },
    {
        experiments: {
            outputModule: true,
        },
        output: {
            path: resolve(__dirname, "dist"),
            filename: "[name].esm.js",
            library: { type: "module" },
            environment: { module: true },
            // sourceType: module,
        },
        ...common,
    },
    {
        output: {
            path: resolve(__dirname, "dist"),
            filename: "[name].min.js",
        },
        ...common,
    },
];

.babelrc配置

{
    "sourceMaps": "inline",
    "presets": [
        [
            "@babel/preset-env",
            {
                "loose": true,
                "modules": false,
                "targets": {
                    "esmodules": true
                },
                "useBuiltIns": "entry",
                "corejs": { "version": 3, "proposals": true }
            }
        ],
        "@babel/preset-react",
        [
            "@babel/preset-typescript",
            {
                "isTSX": true,
                "allExtensions": true
            }
        ]
    ],
    "plugins": [
        [
            "babel-plugin-styled-components",
            {
                "ssr": false
            }
        ]
    ]
}

tsconfig.json配置

{
    "compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "lib": ["ES2017", "ES7", "ES6", "DOM"],
        "strict": true,
        "strictNullChecks": true,
        "noImplicitAny": false,
        "removeComments": true,
        "preserveConstEnums": true,
        "baseUrl": "./",
        "outDir": "./lib",
        "typeRoots": ["node_modules/@types"],
        "moduleResolution": "node",
        "esModuleInterop": true,
        "sourceMap": true,
        "declaration": true,
        "declarationDir": "./build/",
        "noEmitOnError": true,
        "jsx": "react-jsx",
        "importHelpers": true,
        // "noEmit": false,
        // "allowJs": true,
        // "skipLibCheck": true,
        // "noImplicitThis": false,
        // "allowSyntheticDefaultImports": true,

        "paths": {
            "@components/*": ["src/components/*"],
            "@providers/*": ["src/providers/*"],
            "@utils/*": ["utils/*"],
            "@src/*": ["src/*"]
        },
        "noErrorTruncation": true
    },
    "include": ["src/**/*.ts", "src/**/*.tsx", "examples/**/*"],
    "exclude": ["node_modules", "dist", "**/*.spec.tsx", "**/*.spec.ts"]
}

package.json配置

{
    "type": "module",
    "main": "dist/index.js",
    "module": "dist/main.esm.js",
    "unpkg": "dist/main.min.js",
    "types": "dist/index.d.ts",
    "sideEffects": false,
    "files": [
        "dist",
        "src",
        "tsconfig.json"
    ],
    "scripts": {
        "bundle": "webpack --config webpack.lib.config.js"
    }
}

我的期望:当项目仅使用组件库中的2个组件时,最终构建文件应只包含这2个组件,而非整个组件库。


内容的提问来源于stack exchange,提问作者Malkeet Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 19:14:58