Description
Background
The traditional method of transpiling a typescript application is through ts.CompilerHost
. This is awesome, and there are slowly becoming more and more CompilerHost based "flavors" of tsc
that developers are wanting to use. I spoke about this with @alexeagle and @mhegazy briefly on this as well:
Webpack Loaders
A webpack loader in its most simple form does the following:
function takeASingleFileThatIsServedToThisFunctionViaWebpack(rawFileStringContent) {
let newlyUpdatedRawFileString = rawFileStringContent + 'console.log(WOW THIS MAKES SENSE);'
return newlyUpdatedRawFileString;
}
As you can see all a loader does is take a raw source, and return it. On top of this webpack handles file resolution through some crafty regex:
loaders: [
{
test: /\.ts/, // this regex string tells webpack which files to 'send' to the loader
loader: ‘ts-loader’ // this specifies the loader to use (resolves to node modules)
}
]
Webpack Typescript Loaders Cannot & Should Not Use ts.CompilerHost
So knowing what we know about how a file is tranformed and resolved through webpack, ts.CompilerHost
is not an option for a ts-webpack loader. Why? Loaders are a powerful tool in webpack because they can be chained together with other loaders. For example: This Angular2 TS Loader I wrote. CompilerHost (as you know probably) runs a build/transpiliation against a whole project, and not one file per time. Therefore if you tried to plop a CompilerHost in a webpack loader, it would lose the context between each file.
Webpack TS Loaders & ts.LanguageServiceHost
.
Because of this, the current typescript webpack loaders that are being used (ts-loader, awesome-typescript-loader) are both using ts.LanguageServiceHost
. Why? Because LSG's support transpilation at a long-term lifetime one-file-at-a-time transpilation, persisting the transpile context back to the ts.Program
. (This is tranditionally useful for IDE'S yes, but its a match made in heaven for a webpack loader). I would call this an 'edge-case' request, however, with 5+ million downloads a month, webpack is increasingly more popular than any bundler at the moment.
The Problem:
Trying to use ts.CompilerHost
implementations in a ts.LanguageServiceHost
is a huge pain, and doesn't port well into an existing LSH. Its true that they share some functions, however there lacks a way to use a CompilerHost in a LanguageService incrementally.
The Solution.
Create some way to attach the functionality of a custom CompilerHost implementation, and then perform it on a per-file basis, updating the LanguageServiceHost
to help persist the transpilation/program contex. This will allow not only @s-panferov and @TypeStrong able to create plugin's systems that allow for super powerful TS builds in webpack. Or instead a plugin system where you add/override certain functionalities to an existing LSH.
Please refer to this conversation thread of me explaining the issue to @DanielRosenwasser with lots of examples:
Start: https://gitter.im/Microsoft/TypeScript?at=5757ab04662b042b7e596b70
End: https://gitter.im/Microsoft/TypeScript?at=5757b77445cf128e5f1d7429
References
#6508 (comment)
angular/angular#8759
TypeStrong/ts-loader#223
https://github.com/TypeStrong/ts-loader/issues/
s-panferov/awesome-typescript-loader#153
TypeStrong/ts-loader#224