Credit: Big thanks to Simon Lax for guiding me towards focusing on the bundler aspects...
In my development setup, I utilize rollup.js, along with the plugin-strip.
By toggling a single switch in my rollup.config.js
, I can easily enable/disable the 'transpile away' feature.
// src/main.ts
import fs from "fs";
class Service {
expensive(res = ""): string {
for (let i = 0; i < 1000; i++) res += i;
return res;
}
normal(): string {
return "Hi mom!";
}
}
class Logger {
public static log<T>(statement: T): T | undefined {
console.log(statement);
return statement;
}
}
const s = new Service();
Logger.log(`${s.expensive()}`);
console.log(s.normal());
// and I can even use it in different situations, which usually expect the output.
fs.writeFileSync(
"/tmp/abc",
Logger.log(
"not printed to screen nor to file but I wont have runtime exceptions, because TS hints me to catch the undefined case with the null'ish concealing",
) ?? "",
);
// rollup.config.js
import typescript from "@rollup/plugin-typescript";
import strip from "@rollup/plugin-strip";
export default [
{
external: ["fs"],
input: ["src/main.ts"],
output: {
dir: "dist",
format: "es",
},
strictDeprecations: true,
plugins: [
strip({
include: ["**/*.ts"],
functions: process.env.DEBUG ? [] : ["logger.log"],
}),
typescript(),
],
},
];
// package.json
"type": "module",
"scripts": {
"bundle": "rollup --config rollup.config.js"
},
"devDependencies": {
"@rollup/plugin-strip": "^3.0.2",
"@rollup/plugin-typescript": "^11.0.0",
"rollup": "^3.15.0",
"typescript": "^4.9.5"
},
Upon executing npm run bundle
, the stripped version will be generated
// dist/main.js
import fs from 'fs';
class Service {
expensive(res = "") {
for (let i = 0; i < 1000; i++)
res += i;
return res;
}
normal() {
return "Hi mom!";
}
}
const s = new Service();
console.log(s.normal());
// and I can even use it in different situations, which usually expect the output.
fs.writeFileSync("/tmp/abc", "");
Running DEBUG=1 npm run bundle
will create the full version
// dist/main.js
import fs from 'fs';
class Service {
expensive(res = "") {
for (let i = 0; i < 1000; i++)
res += i;
return res;
}
normal() {
return "Hi mom!";
}
}
class Logger {
static log(statement) {
console.log(statement);
return statement;
}
}
const s = new Service();
Logger.log(`${s.expensive()}`);
console.log(s.normal());
// and I can even use it in different situations, which usually expect the output.
fs.writeFileSync("/tmp/abc", Logger.log("not printed to screen nor to file but I wont have runtime exceptions, because TS hints me to catch the undefined case with the null'ish concealing") ?? "");
(In case you are interested, here is my tsconfig.json
)
// tsconfig.json
{
"compilerOptions": {
"outDir": "dist",
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"baseUrl": "."
},
"ts-node": {
"transpileOnly": true
}
}