Update - You actually don't need to do this. But it's still probably worth knowing for non-TypeScript projects, or other file manipulation.
If you need to strip comments from your code before publishing a package, or pushing to production, you might be inclined to spin up Gulp, or install an NPM dependency to do the work for you. But you may not need to.
It’s actually quite easy! (once you know how)
I recently had the need while building an NPM package. The project is written in TypeScript, and the problem arose when I needed to specify the compilerOptions
for the TypeScript compiler (funnily enough).
When you’re ready to compile your TypeScript you’ll run the tsc
command, or something that ends up calling tsc
. When that runs TypeScript looks for a tsconfig.json
file. In this file you can specify that comments should be removed.
End of story right, we need comments removed and that’s what removeComments
does. Note so fast.
The problem with removeComments
is the comments (a.k.a documentation) are not only removed from the generated JavaScript files, but also the declaration files. This might not always be a problem. But for me it was. I didn’t want the comments in the JavaScript, but keeping them in the declaration file is part of the projects documentation strategy.
So, what do we need?
- We need to run
tsc
and compile our code. - Grab the compiled JavaScript file and remove all the comments.
This is a small project with no dependencies. So it seems, shall we say... undesirable to add Gulp or what-not for this little task. But how else do we do it? 🤔
Here’s what I learned.
The Node-CLI has a print command that we use to execute an exported function from a JavaScript file somewhere in our directory. We’ll use it like this;
/** package.json **/
{
...
"scripts": {
"prepare": "tsc && node -p \"require('./cleaner').clean()\""
}
...
}
When I call npm run prepare
in the terminal the TypeScript compiler (tsc) will fire, and then node will look for a file called cleaner.js at the same directory level as package.json. If it finds one, it will attempt to call an exported function named clean.
Lets add the cleaner file, and export the clean function.
// cleaner.js
const fs = require(“fs”); // comes with node.
module.exports.cleaner = function () {
try {
let file, data, nocomments;
const filePath = "dist/index.js";
const regex = new RegExp(/((^\/\*\*\n(\D\W.+\n)+))/, "gm");
fs.accessSync(filePath, fs.constants.F_OK);
file = fs.openSync(filePath, "r+", fs.constants.O_RDWR);
data = fs.readFileSync(file, "utf8");
nocomments = data.replace(regex, "");
fs.writeFileSync(filePath, nocomments);
return "Comments Removed";
} catch (error) {
return error;
}
}
And that's it!
When the clean
function executes it locates our newly generated JavaScript file, reads in its content, replaces all the comments with nothing, and then writes the new version back to file.
There's probably a bit going on here you're not familiar with; what's all this fs
stuff? I didn't know either. But I found this good post that explains it all, so I'll point you there.
- Node.js File System API, Beginner Friendly Guid
- Oh, and NPM: Short Scale Units, incase you give any Fs about my little project.
This is a pretty specific solution. I now all the comments are block style, so the RegExp
has been designed to match that pattern.
/**
* My block style comment explaining important stuff
* @param tag explaining the param stuff.
* @return tag explaining the return stuff.
*/
And I know the compiler will output an index.js
file to a generated dist/
directory. But I think this gives a good outline of the type of solution you have available, with no added dependencies.
Update
Thanks to these Redditors
I since learned how to get the same desired outcome for a TypeScript project without needing to roll your own comments remover.
The tsconfig.json
file has an available property named extends
. We can use that and the command chaining we already used here to remove the comments from the output JavaScript, but leave them in the declaration files.
-
We'll change our run command in package.json to
"prepare": "tsc && tsc -p ./tsconfig.nocomments.json"
-
We'll create the new config file, and extend it from the main
tsconfig
.
{ "extends": "./tsconfig.json", "compilerOptions": { "declaration": false, "removeComments": true } }
The main, default tsconfig
file runs first generating declaration and JavaScript files with comments in place. Then our next call to tsc
specifies a path to the new config file (tsconfig.nocomments
), and that one does not create a new declaration file, but does create a new JavaScript file with no comments; which replaces the existing file.
So while you don't need to roll your own comments cleaner in a TypeScript project, the strategy outlined here can still be used for non TypeScript projects, or to do some other manipulation of a files content.
Top comments (2)
What a wonderful article. That saved me a lot of time, thank you.
One suggestion could be to replace
tns
withtsc
in Update section 1st item.Cheers. At the time I was doing a lot of work with NativeScript, that’s probably why I wrote
tns
.