-
Notifications
You must be signed in to change notification settings - Fork 6
Typescript preprocessor #59
Description
thanks for this, I have been looking for it! Great job!
I am considering to write a TS pre/post processor which should take care of at least following actions:
- Conditional compilation (known from other languages)
- Minified name to unminified name mapping (i.e. for usage in string references to properties).
- Eventually other actions such as
- joining all the same namespaces / modules which are using the single class per file pattern to just single file in order to prevent resulting code to be polluted by many namespace/module definitions (as it is now).
- maybe handy, but I am not sure how much at this time
- Minified to unminified library file mappings (something like C header file generation)
- Unminified to minified library linking
The preprocessor should be implemented like that:
the preprocessor.ts must be included in the TS project. It will "virtually" pollute the main object with following statements:
$DEFINE = function $DEFINE(statement: string) {...};
$IFDEF = function $IFDEF(statement: string) {...};
$IFNDEF = function $IFNDEF(statement: string) {...};
$ELSE = function $ELSE(statement: string) {...};
$ENDIF = function $ENDIF() {...};
If we are talking mainly about minification, something like this would be great:
$LIBRARY = function $LIBRARY(libname: string)
It should take all classes from the same module and put them to the single library file or take classes from various namespaces / modules and make a single library source code file from it. The main reason would be to try to avoid a lot of repetitive namespace/module definitions in the compiled code.
I am still looking for the way how to reference minified property by a string so I came with this concept:
$MINIFIEDNAME = function $MINIFIEDNAME(name: string, object: any);
As previous statements are I would say straightforward this one I guess requires deeper explanation.
The function returns the original unminified variable/object/property name defined in string but after minification the preprocessor will take the resultant object parameter and will replace whole definition in the code by the minified name. The syntax looks really horrible so I am still trying to find a better way, how to define this in order to look nicer.
Let me give you an example:
// original .ts class definition:
class Test {
protected _computedValue: number;
protected _someName: number;
public set someName(value: number) {
this._someName = value;
this[$MINIFIEDNAME('_computedValue', this._computedValue)] = value + 3;
console.log('Property ' + $MINIFIEDNAME('someName', this.someName) + ' was changed');
}
}
// minified .ts:
class a {
protected a: number;
protected b: number;
public set c(a: number) {
this.b = a;
console.log('Property ' + $MINIFIEDNAME('someName', this.b) + ' was changed');
this[$MINIFIEDNAME('_computedValue', this.a)] = a + 3;
console.log('Property ' + $MINIFIEDNAME('someName', this.a) + ' was changed');
}
}
// postprocessed .ts (before compilation):
class a {
protected a: number;
protecte b: number;
public set c(a: number) {
this.b = a;
console.log('Property ' + 'b' + ' was changed');
this['a'] = a + 3;
console.log('Property ' + 'a' + ' was changed');
}
}
The Pre-Post processor will be included in the build process like this:
Unminified program -> Preprocessor -> Clean code without DEFS/IFDEFS/LIBRARIES -> Minifier -> Minimized code -> MinPreprocessor -> String names replaced -> Compiler -> Compiled JS and .map to generated lib files -> Postprocessor-> Compiled JS with maps to original source code
It will preprocess all TS files in the project (eventually defined folder walked through recursively) before and after minification step in order to:
Before minification:
- Remove the preprocessor.ts from the target compilation
- Remove all the code defined (and including) $IF ans so on
- Join all related files to specified library/libraries
Calls minifier to do his job
After minification:
- Replaces all occurences of $MINFIELDNAME ... by the minified name of the variable / object / property string
Calls compiler to do his job
Post processing:
- remaps all compiler generated map files to match the original source code (because of joined libraries) in order to be possible to debug it.
Main requirements:
- don't modify the typescript compiler
- the preprocessor directives must be a valid TS code as the Dev IDE must be able to recognize without any additional changes to the Dev IDE itself (it would be great to have syntax highlighting for preprocessor directives but it is not that important)
- if the preprocessor is not included in the build process the code must be still valid and must work in the same way as the processed code (even while it will be slower)
- support for "changed source" compilation - compile just those files which were changed
Any comments and recommendations are welcome. Especially ideas, how to exactly implement it in order to be compatible with existing build systems.