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
相关产品推荐
相关产品推荐

