为多个项目中的通用功能创建打字稿库

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

我想导出几个类,一些是独立的,一些是相互依赖的,被一个命名空间包裹,作为一个模块供其他项目使用。

所以我设置了一个 webpack 构建来将它们编译成一个缩小的 .js 文件和一个 .d.ts 文件,它们都被命名空间“Platform”包裹。

这是我用于自定义事件的示例类:


namespace Platform {
    export class GameEvent {
        ****code****
    }
}

问题是,一旦我将它们包装在这个命名空间中,构建就会失败并出现以下错误:

./Utilities/GameEvent.ts 中的错误 模块构建失败(来自 ../node_modules/ts-loader/index.js): 错误:TypeScript 没有为 \Platform\src\Utilities\GameEvent.ts 发出任何输出。 在 makeSourceMapAndFinish(\平台 ode_modules s-loader\dist\index.js:53:18) 在 successLoader (\Platform ode_modules s-loader\dist\index.js:40:5) 在 Object.loader (\Platform ode_modules s-loader\dist\index.js:23:5)

这是我的 tsconfig:

{
    "compilerOptions": {
        "target": "es6",
        "module": "esnext",
        "strict": true,
        "noEmit": false,
        "importHelpers": true,
        "moduleResolution": "node",
        "esModuleInterop": true,
        "sourceMap": true,
        "baseUrl": "./src",
        "rootDir": "./src",
        "outDir": "./types",
        "emitDeclarationOnly": true,
        "declaration": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "lib": [
            "es6",
            "dom"
        ],
        "removeComments": true,
        "typeRoots": [
            "node_modules/@types",
            "node_module/phaser/types"
        ],
        "types": [
            "phaser",
            "jest"
        ]
    },
    "include": [
        "src/**/*",
    ]
}

这是我的 webpack.config.js:

const path = require("path");
const webpack = require('webpack');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const DeclarationBundlerPlugin = require('declaration-bundler');
const fs = require('fs');

const srcDir = path.resolve(__dirname, 'src');
const typesDir = path.resolve(__dirname, 'types');

function scanDirectory(dir) {
  const fileArr = [];

  fs.readdirSync(dir).forEach((file) => {
    const filepath = path.join(dir, file);
    if (fs.lstatSync(filepath).isDirectory()) {
      fileArr.push(...scanDirectory(filepath));
    } else if (/\.tsx?$/.test(file)) {
      fileArr.push(path.resolve(filepath));
    }
  });

  return fileArr;
}

const entryPoints = scanDirectory(srcDir);
const typeEntryPoints = scanDirectory(typesDir);

module.exports = {
  mode: "production",
  context: path.resolve(__dirname, 'src'),
  entry: {
    'platform': entryPoints
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: "[name].min.js",
  },
  externals: {
    phaser: 'phaser',
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: [
          {
            loader: 'ts-loader',
          },
        ],
        include: [path.resolve(__dirname, 'src')],
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new webpack.DefinePlugin({
      'typeof SHADER_REQUIRE': JSON.stringify(false),
      'typeof CANVAS_RENDERER': JSON.stringify(true),
      'typeof WEBGL_RENDERER': JSON.stringify(true)
    }),
    new DeclarationBundlerPlugin({
      entry: typeEntryPoints,
      moduleName: 'Platform',
      out: './platform.d.ts',
    }),
  ],
  performance: { hints: false },
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: true,
          safari10: true,
          mangle: true,
          output: {
            comments: false
          }
        }
      })
    ]
  }
};

这些是我的 devDependencies:

"@jest/globals": "^29.3.1",
    "@declaration-bundler": "^1.0.1",
    "@types/jest": "^29.2.5",
    "before-build-webpack": "^0.2.13",
    "clean-webpack-plugin": "^3.0.0",
    "glob": "^8.0.3",
    "html-webpack-plugin": "^5.3.1",
    "jest": "^29.3.1",
    "jest-canvas-mock": "^2.4.0",
    "jest-environment-jsdom": "^29.3.1",
    "terser-webpack-plugin": "^5.3.6",
    "ts-jest": "^29.0.3",
    "ts-loader": "^8.0.18",
    "ts-node": "^10.9.1",
    "typescript": "^4.9.4",
    "webpack": "^5.28.0",
    "webpack-cli": "^4.9.1"

我尝试对每个没有命名空间的文件使用“导出默认类”,但是当我发布包并在另一个项目中使用它时,它无法将其识别为模块并且无法构建/测试。

我该怎么办?

typescript webpack module namespaces
2个回答
0
投票

好吧,我想通了,虽然不完全是我想要的,但它运作良好。

这是我的 webpack.config.js:

const path = require("path");
const webpack = require('webpack');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const DtsBundleWebpack = require("dts-bundle-webpack");
const removeEmptyDirectories = require('remove-empty-directories');

const libPath = path.resolve(__dirname, 'lib');

module.exports = {
  mode: "production",
  context: path.resolve(__dirname, 'src'),
  entry: {
    'platform': "./platform.ts"
  },
  output: {
    path: libPath,
    filename: "[name].min.js",
    libraryTarget: 'commonjs2'
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new webpack.DefinePlugin({
      'typeof SHADER_REQUIRE': JSON.stringify(false),
      'typeof CANVAS_RENDERER': JSON.stringify(true),
      'typeof WEBGL_RENDERER': JSON.stringify(true)
    }),
    new DtsBundleWebpack({
      name: "<lib name>",
      main: "lib/platform.d.ts",
      out: "platform.d.ts",
      removeSource: true,
      outputAsModuleFolder: true
    }),
    function () {
      this.hooks.done.tap("Done", (stats) => {
        removeEmptyDirectories(libPath);
      });
    }
  ],
  performance: { hints: false },
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: true,
          safari10: true,
          mangle: true,
          output: {
            comments: false
          }
        }
      })
    ]
  }
};

我的文件结构是这样的:

file structure src/ folder

对于每个类文件,每个 index.ts 文件都有一个“export * from 'filename'”。

platform.ts 文件导出所有模块


0
投票

这里的另一个陷阱,在这个例子中可能不是你的问题,但

Error: TypeScript emitted no output for _____.ts
的另一个常见原因是
noEmit
tsconfig.json
中设置为真。

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