Description
Currently TypeScript does not have a good understanding of loader plugins. Both AMD and SystemJS support the concept of loader plugins (though they vary in format). Currently the only way to integrate a loader plugin is specify the full module name as an ambient declaration and describe the shape of what is returned. For some plugins, this is quite a redundant activity (like a text plugin) since all resources returned by the plugin are text resources.
Both with AMD and SystemJS (also proposed for ES6 module loader), plugins do not have to return a consistent shape. Because of this, I think there are two approaches:
- Create resolution logic that supports some sort of glob pattern for ambient declarations, with resolution of the most specific declaration.
- Integrate more robust functionality in understanding plugins and what shape they return.
For background reading here is the specification of each:
For SystemJS there are four methods that can be overridden the are exposed by the plugin module:
locate
- Allows a return of an alternative location for the resource.fetch
- Allows the plugin to fetch the "raw" resource.translate
- Allows the plugin to modify the resource (e.g. translate on the fly from CoffeeScript to JS)instantiate
- Called when the loader actually tries to instantiate the module.
For AMD there:
normalize
- Allows the resource ID to be modifiedload
- Allows hooking into the actual load and instantiation of the module
RequireJS has support for a couple more, which are specifically geared for building code, but they are not officially part of the AMD standard:
write
- Write out the moduleonLayerEnd
- Allows a hook into when a layer is finishedwriteFile
- Hook when the file is writtenpluginBuilder
- Substitute another module for this module when doing a build
Also there is a big difference between AMD and SystemJS in the format of the MID for plugins, annoyingly (I won't get on my soap box about how we reinvent the wheel in on the web). AMD is [plugin]![resource]
and SystemJS is [resource]![plugin]
.
@mhegazy asked if plugins change their shape. My personal experience is with AMD and in that case, in practice, some plugins do change their shape (for example in Dojo we have a module that loads CommonJS modules called dojo/node
) and others that never change their shape (for example dojo/text
loads text resources) and ones where the resource ID determines what is loaded (for example dojo/has
take a feature flag and a ternary operator to determine what it loads).
My personal feeling is that option 2 would be horribly complex, likely to have all sorts of edge cases, and while highly useful for those using plug-ins, might just become too challenging. If/when the ES6 Loader is finalised and there is plugin support in there, then having a feature rich analysis of those plugins might be worth the effort. Until then, I think option 1 would allow people to achieve the most use cases with a minimum amount of complexity.
This is related to a discussion that came up in #5759.
Activity