Open seant-ca opened 7 years ago
@seansat TsMinifier will soon provide a CLI, but currently is can only be used as a node package. Please check out the TsMinifier Wiki.
If you are still having problems, please post a comment with additional details so that I can try to help you out.
Hi Todd, thanks for responding. I did in fact read the Wiki...if it's not too much to ask, can you provide a step by step walkthrough of how to minify a file and where it gets outputted to. Please be as explicit as possible because I think I am missing something. If you can provide example script files, that I can follow along exactly with settings, etc then I will repeat exactly what you do.
Otherwise, I guess I would have to retrace my steps and provide a detail report of what I am doing. In a nutshell, I include the node "tsminifier" library and attempt to minify but not sure where the files get outputted to or if any output is actually happening at all.
@seansat TsMinifier does not (yet) provide a CLI. It is available only as a node package that can be used as a dependency in your own node package through the use of the API.. It can also be used within a node based build system ( like gulp ). I'm happy to address any specific questions you have concerning the use of the API to minify a file(s).
@seansat TsMinifier is a transform plugin for the ts2js compiler. Under the hood, The TsMinifier calls ts2js with the minifier transform as a parameter. When minifying, the return result provides the details of the minification.
I apologize for the pretty much non-existent document on the API. It will be coming...
Yes, the documentation for TsMinifier was pretty much "nothing", but I understand the project(s) are new. Am I the first from the "outside public" to attempt to use them?
I started to embark on the journey of writing a minifier for TypeScript after seeing that one didn't already exist. I read further down in the TypeScript feature request and saw posts from yourself and decided to check out what you have already done instead of re-inventing the wheel. After starting writing, I realized it wouldn't be a quick write so it would be nice to save time by leveraging an existing solution.
I noticed that the existing javascript minifiers tend to not mangle property names because they aren't aware which are public or private or referenced externally, etc, so I thought at the typescript level there would be way more context about types that could be used to provide better minification and it seems like this is what you have done.
Google Closure seems like a good one but after using advanced mode things started to break.
I haven't yet tried building the sample app for TsBundler, is your minifier currently NOT renaming public properties?
@seansat I feel strongly that leveraging the Typescript AST is the best way to optimally minify a Typescript source file. There are just obvious benefits.
I initially wrote TsProject, so that I could have complete control over how I bundled and minified the javascript based apps/code that I write. TsProject proved to me that I could do a much better job at minifying at the source or AST level rather that applying uglify during the build pipeline. TsProject was just a bit too much of a do everything package, so I decided with Typescript 2.1 ( with transforms ) that I'd split it up into the transform compiler, minifier and bundler.
The minifier in TsProject utilizes the Typescript AST to properly mangle identifiers such that the minified javascript will always work. It also works with inheritance. Coupling this with whitespace removal the output from TsProject was always smaller that when using uglify.
I've added a few new features to the minifier post TsProject. The TsMinifier now can use jsdoc comments to allow annotations
Where minification becomes interesting is in the context of bundling. I also do bundling at the Typescript source level. By defining ambient modules which can be used for re-exporting only public accessible objects the set of "internal" modules can be treated as private which results in substantial space savings.
You are prob. the first user to brave using the TsBundler, TsMinifer and Ts2Js! Unfortunately, right now each of the 3 projects are still a work in progress ( even though TsProject has been around for over a year ). I suspect that release 1.0.0 will happen in early January.
I am very much open to taking input, ideas and PR's on any of these open source projects.
Question: "MinifierOptions.externalNamespace:string" - can you explain how this option works and what it does..
The minifier in TsProject would look for the given namespace to force everything outside of this namespace to be logically internal. Since minification was applied to a monolithic bundle, even public names could be considered internal/private and thus mangled. There were some cases where this was a bit too optimistic so the new TsMinifier has the /* nomangle / annotation to make sure an "internal" public identifier is not mangled (this is usually when an identifier is referenced by an external template - react, angular, etc ). This mechanism will likely change a bit before the initial 1.0.0 release of TsBundler and TsMinifier. I want to remove the externalNamespace configuration option and replace it with something that is annotation based.
Note that TsProject was built by TsProject. TsProject is highly optimized/minified. This is not that important for the node/commonjs module environment, but it is important for the ES5 browser world that we will have for a long while yet.
Thanks for all the clarification. I believe I have enough info to take another stab at the entire process. I will keep you posted with results and/or if I have any issues.
I think I like the fact that even the public identifiers are mangled as well if they are deemed "internal".
@seansat Start with the TsBundlerSamples "Greeter" typescript app.
@seansat Yes, the best thing about the minifier is the use of a conventions based "internal" modifier. With the new TsBundler and TsMinifier annotations I hope to make this simple to use. The added benefit is that bundles could be conveniently optimized for specific end user needs ( a set of needed API surfaces ).
I have a lot more context and understanding now.
One major point to stress in the documentation is that TsMinifier minifies to "memory", I guess this follows in the same way that Ts2Js compiles to memory. This was really confusing to me at first because I thought the result object returned represented files that should have been outputted. So it made me think it "wasn't working".
Based on your explanations, my understanding now is that TsBundler takes the output from memory and exports it into a bundle file. My initial expectations as a user was that file output would have happened by default.
Another thing that threw me off at first was that I assumed/expected the "minifyProject" function to read the tsconfig.json and minify all the files that were imported in my "entry" file. In my tsconfig, I don't specify a list of all files, I usually have one main entry file. I believe what TsMinifier does is only minify the "list" of files specified in the "files" property of tsconfig.
With all that being said, I tested one individual class file and I was able to minify it.
I notice that function parameter names have been minified, however it seems as though the minification process has totally removed any class properties that were labelled protected or private or even public for that matter?
It seem as though method names that are public are NOT mangled? It looks like the private ones are being mangled.
Do you have any insight re: the stripping/removal of class properties? Oh wait...it looks like they are being added to the constructor and initialized there? If so, what was your motivation for this...for efficiency or something?
I was able to notice these things by NOT removing white space in the MinifierOptions, so thats what made me think the class properties were "gone" but upon looking at the constructor and counting the parameters of the constructor, it seems like there are some additional this.x = y statements.
I set the following compiler options: target: ES2015 module: ES2015 moduleResolution: node
I'm not sure if the property re-arraning thing is something specific to the way how TypeScript exports files for ES2015?
Is TsMinifier optimized/tested to work with certain settings in the compiler options?
I realize that my comment about the rearranging of class properties is not a TsMinifier thing, it's a javascript thing, basically there aren't really class properties in Javascript so this is just the way Typescript translates protected x = y; to this.x = y in the constructor.
I was thinking in TypeScript terms but I have to remember the output is javascript which does not have separate syntax for class properties, yet, I guess.
For the 1.0.0 release of TsMinifier ( and TsBundler ) there will be an option to output the minified ( and bundled ) typescript source.
Are public method names suppose to remain unmangled?
I inspected the source code and Minifier.canShortenIndentifier() doesn't seem to be returning true for Public methods so I guess this was intentional. I would like to see it mangle public methods as well in "internal" classes but I guess this feature isn't implemented yet.
I did some further inspection and it seems the reason why the public method names are not being mangled is because the class I minified is an abstract class. I see that you have a comment in the code to review this.
Actually, I removed the abstract label from the class and it still didn't mangle the method names
Hello, Todd, the idea of your project sounds great, but I was unable to run it with NodeJS. :-) It just does nothing (after a time of processing files)...
I have a RequireJS project with big number of files:
module1/submodule1.ts module1/submodule2.ts module2/submodule1.ts module2/submodule2.ts ... api/api_not_for_obfuscation.ts
I need to compile anything to one "out.js" with obfuscation of anything except "api/api_not_for_obfuscation.ts" file classes and their public methods.
It there any chance to do it with TsMinifier? Could you give me a sample?
@seansat identifiers that are public are not mangled because they must be accessible/referenced outside their scope by name.
This is why the bundler has the concept of making external modules "internal". If you have a single file bundle and you "know" all the references to "internal" identifiers, then even public identifiers can be mangled.
@dmido TsMinifier is a result of breaking apart the major features/functions of TsProject. TsProject did exactly what you want. Essentially, TspProject itself was built using TsProject. It offers an API which is left intact from the minification process, but all the other component modules are "internalized" and optimally minified. Take a look at how TsProject bundled TsProject to get started for now.
TsProject is now TsBundler, TsMinifier, and Ts2Js. The official first release of these packages will happen in January 2017.
I will provide a documentation Wiki for each package ( they've already been started ).
I will also provide samples to help users get started. However, until the official release I unfortunately cannot do everything at once.
The main goal for the new packages is to make them more mainstream. TsProject really just started out as a tool for my development.
Before the 1.0.0 release, I"m more than happy to answer any of your questions.
Thank you for answer, I will follow for progress in these projects.
Just wondering how to get started using the minifier...is it from the command line? Does it output TS files or JavaScript files...can you give the beginner's guide...i tried using it from the command line but it didn't output any files? but i'm not sure if I'm using it correctly...