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