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

Storybook升级后Webpack5未转换TSX为TS文件问题求助

问题描述

将Storybook项目从5.1.8升级至6.5.16后,执行npm run build-lib构建供外部调用的自研组件时,Webpack未将MyComponent文件夹下的TSX文件生成对应的TypeScript类型声明文件(.d.ts)。组件已在index.ts导出并配置为Webpack入口,相关配置文件如下:

package.json

{
  "name": "@xxx/components",
  "version": "0.0.0",
  "private": false,
  "main": "build/xxxxx",
  "types": "build/lib/index",
  "files": [
    "build"
  ],
  "scripts": {
    "build-lib:dev": "cross-env NODE_ENV=development webpack && npm run copy-css-to-lib",
    "build-lib": "cross-env NODE_ENV=production webpack && npm run copy-css-to-lib",
    "storybook": "start-storybook -p 6006 -s ./src/public -c .storybook",
    "build": "npm run build-lib && build-storybook",
    "build-storybook": "build-storybook",
    "copy-css-to-lib": "cpx \"./src/**/*.scss\" ./build/lib",
    "prepublishOnly": "npm run build-lib",
    "lint": "eslint ./.eslintrc.js"
  },
  "repository": "xxxxx",
  "license": "UNLICENSED",
  "peerDependencies": {
    "bootstrap": "^4.5.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "reactstrap": "^8.7.1"
  },
  "devDependencies": {
    "@storybook/addon-a11y": "^6.5.16",
    "@storybook/addon-actions": "^6.5.16",
    "@storybook/addon-essentials": "^6.5.16",
    "@storybook/addon-interactions": "^6.5.16",
    "@storybook/addon-links": "^6.5.16",
    "@storybook/builder-webpack5": "^6.5.16",
    "@storybook/manager-webpack5": "^6.5.16",
    "@storybook/node-logger": "^6.5.16",
    "@storybook/preset-scss": "^1.0.3",
    "@storybook/react": "^6.5.16",
    "@storybook/testing-library": "^0.0.13",
    "@types/query-string": "^6.3.0",
    "@types/react-router-dom": "^5.3.3",
    "@typescript-eslint/eslint-plugin": "^5.54.1",
    "@typescript-eslint/parser": "^5.50.0",
    "babel-plugin-named-exports-order": "^0.0.2",
    "clean-webpack-plugin": "^4.0.0",
    "copy-webpack-plugin": "^11.0.0",
    "webpack": "^5.75.0",
    "webpack-bundle-analyzer": "^4.7.0",
    "webpack-cli": "^5.0.1",
    "webpack-hot-middleware": "^2.25.3"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "outDir": "build/lib",
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "moduleResolution": "node"
  },
  "include": ["src/**/*", "types/**/*"],
  "exclude": ["node_modules", "build", "scripts"]
}

index.ts

export { MyComponent } from "./components/folder/MyComponent";

webpack.config.js

// Imports
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const IgnoreNotFoundExportPlugin = require("./IgnoreNotFoundExportPlugin");
const StyleLintPlugin = require("stylelint-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;

const buildPath = path.join(__dirname, "./build");
const env = process.env.NODE_ENV;
const isDev = env === "development";

console.log("Env: " + env + "|Dev: " + isDev);

module.exports = () => [
  {
    stats: { modules: false },
    devtool: "inline-source-map", //devtool: false,
    entry: {
      index: ["./src/index.ts"],
    },
    resolve: {
      extensions: [".js", ".jsx", ".ts", ".tsx"],
      alias: {
        react: path.resolve(__dirname, "./node_modules/react"),
        "react-dom": path.resolve(__dirname, "./node_modules/react-dom"),
      },
    },
    externals: {
      // Don't bundle react or react-dom
      react: {
        commonjs: "react",
        commonjs2: "react",
        amd: "React",
        root: "React",
      },
      "react-dom": {
        commonjs: "react-dom",
        commonjs2: "react-dom",
        amd: "ReactDOM",
        root: "ReactDOM",
      },
    },
    mode: isDev ? "development" : "production",
    output: {
      path: path.join(__dirname, "./build"),
      filename: "xxxxx.js",
      library: "xxxxxxComponents",
      libraryTarget: "umd",
      publicPath: "/build/",
    },
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          include: /src/,
          use: "ts-loader", 
        },
        {
          test: /\.scss$/,
          exclude: /node_modules/,
          use: [
            MiniCssExtractPlugin.loader,
            "css-loader",
            "resolve-url-loader",
            {
              loader: "sass-loader?sourceMap",
              options: {
                includePaths: [path.join(__dirname, "src/styles")],
              },
            },
          ],
        },
        {
          // URL-loader to handle image resources (one URL-loader could be used for both images and fonts)
          test: /\.(png|jpg|jpeg|gif|svg|ttf|woff|woff2|eot)$/,
          use: "url-loader?limit=25000",
          exclude: /node_modules/,
        },
      ],
    },
    optimization: {
      minimizer: [new TerserPlugin()],
    },
    plugins: [
      new IgnoreNotFoundExportPlugin(),
      new ForkTsCheckerWebpackPlugin({ typescript: { checkSyntacticErrors: true, measureCompilationTime: true } }),
      new MiniCssExtractPlugin(),
      new CopyPlugin({
        patterns: [
          { from: "src/public/fonts", to: "lib/fonts" },
          { from: "src/public/images", to: "lib/public/images" },
        ],
        options: {
          concurrency: 100,
        },
      }),
      new BundleAnalyzerPlugin({
        analyzerMode: isDev ? "static" : "disabled",
        openAnalyzer: false,
      }),
    ],
  },
];
缺失配置与修复方案

核心问题是当前配置未生成TypeScript类型声明文件(.d.ts),Webpack的ts-loader默认仅转译TS/TSX为JS,不会输出类型文件,需补充以下配置:

1. 修改tsconfig.json开启类型声明生成

添加declaration、declarationDir和emitDeclarationOnly配置,让TypeScript单独生成类型文件:

{
  "compilerOptions": {
    "outDir": "build/lib",
    "noImplicitAny": true,
    "module": "esnext", // 替换es6为esnext,适配现代模块规范
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "moduleResolution": "node",
    "declaration": true, // 开启类型声明文件生成
    "declarationDir": "build/lib", // 指定类型文件输出目录
    "emitDeclarationOnly": true // 仅生成类型文件,不编译JS(Webpack已负责JS编译)
  },
  "include": ["src/**/*", "types/**/*"],
  "exclude": ["node_modules", "build", "scripts"]
}

2. 更新package.json的构建脚本

在build-lib和build-lib:dev脚本中添加tsc命令,确保构建时同步生成类型文件:

"scripts": {
  "build-lib:dev": "cross-env NODE_ENV=development webpack && tsc && npm run copy-css-to-lib",
  "build-lib": "cross-env NODE_ENV=production webpack && tsc && npm run copy-css-to-lib",
  // ...其他脚本保持不变
}

3. 优化webpack.config.js的ts-loader配置

设置transpileOnly: true让Webpack仅转译JS,类型检查交给ForkTsCheckerWebpackPlugin,提升构建速度:

{
  test: /\.tsx?$/,
  include: /src/,
  use: {
    loader: "ts-loader",
    options: {
      transpileOnly: true // 仅转译,不做类型检查
    }
  }
}

4. 验证配置正确性

  • 执行npm run build-lib后,build/lib目录下应同时存在编译后的JS文件和对应的.d.ts类型文件
  • 确保package.json的types字段指向正确的入口类型文件(当前"types": "build/lib/index"已正确配置)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 10:22:06