简体   繁体   中英

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".

Here is an example class I use for custom events:


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. 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)

here is my 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:

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:

"@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.

How should I go about this?

Ok I figured it out, not completely how I would like but its working well.

Here is my 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

where each index.ts file has an "export * from 'filename'" for each of the class files.

and the platform.ts file exports all of the modules

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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