简体   繁体   English

为多个项目中的通用功能创建 typescript 库

[英]Creating a typescript library for generic functionality in several projects

I want to export several classes,some are standalone and some require each other, wrapped by one namespace, as a module for other projects to use.我想导出几个类,有些是独立的,有些是相互依赖的,由一个命名空间包装,作为其他项目使用的模块。

So I setup a webpack build to compile them into one minified.js file and one.d.ts file, and they are all wrapped by the namespace "Platform".所以我设置了一个 webpack 构建来将它们编译成一个 minified.js 文件和一个.d.ts 文件,它们都被命名空间“Platform”包裹。

Here is an example class I use for custom events:这是我用于自定义事件的示例 class:


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

the problem is, that once I wrapped them in this namespace, the build fails with this error:问题是,一旦我将它们包装在这个命名空间中,构建就会失败并出现以下错误:

ERROR in./Utilities/GameEvent.ts Module build failed (from../node_modules/ts-loader/index.js): Error: TypeScript emitted no output for \Platform\src\Utilities\GameEvent.ts. ./Utilities/GameEvent.ts 中的错误模块构建失败(来自../node_modules/ts-loader/index.js):错误:TypeScript 没有发出 output for \Platform\src\Utilities\GameEvent.ts。 at makeSourceMapAndFinish (\Platform\node_modules\ts-loader\dist\index.js:53:18) at successLoader (\Platform\node_modules\ts-loader\dist\index.js:40:5) at Object.loader (\Platform\node_modules\ts-loader\dist\index.js:23:5)在 makeSourceMapAndFinish (\Platform\node_modules\ts-loader\dist\index.js:53:18) 在 successLoader (\Platform\node_modules\ts-loader\dist\index.js:40:5) 在 Object.loader (\平台\node_modules\ts-loader\dist\index.js:23:5)

here is my tsconfig:这是我的 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/**/*",
    ]
}

here is my webpack.config.js:这是我的 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
          }
        }
      })
    ]
  }
};

and these are my devDependencies:这些是我的 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"

I tried just using "export default class" for each file without the namespace, but then when I publish the package and use it in another project, it fails to recognize it as a module and fails to build/test.我尝试只对每个没有命名空间的文件使用“导出默认类”,但是当我发布 package 并在另一个项目中使用它时,它无法将其识别为模块并且无法构建/测试。

How should I go about this?我应该怎么go一下这个?

Ok I figured it out, not completely how I would like but its working well.好吧,我想通了,不完全是我想要的,但它运作良好。

Here is my webpack.config.js:这是我的 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 } } }) ] } };

My file structure is like so:我的文件结构是这样的:

file structure src/ folder文件结构 src/ 文件夹

where each index.ts file has an "export * from 'filename'" for each of the class files.对于 class 个文件,每个 index.ts 文件都有一个“export * from 'filename'”。

and the platform.ts file exports all of the modules platform.ts 文件导出所有模块

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM