Open kitsonk opened 5 years ago
I’m not familiar with this behavior (don’t think I’ve ever targeted AMD before), but just to clarify a few things:
baseUrl
or rootDir
have any impact on the output?I think I would personally expect module specifiers to be relative to the rootDir, and would feel pretty safe about this not changing. I’m kind of surprised if that’s not already the case, but it seems like I might be missing something about your request?
@andrewbranch I've created an example repo which recreates an environment which relates to this request.
- where is the project root in this example scenario?
I don't believe this has an impact. In my example the project root contains a src
directory, but all the module IDs are emitted based on their common root.
- does
baseUrl
orrootDir
have any impact on the output?
I don't believe so, I experimented in the example project and setting the baseUrl
to ./
doesn't add src
to the specifiers. It is the same output. I tried rootDir
but I only tried one (setting it to [ "./" ]
and again no impact.
- if the output module specifiers were consistently predictable from project file structure, would that be sufficient?
They are, as far as I can tell, and I am using the logic I detected to determine the emitted specifiers. But that means that I am coupling to a behaviour that is not really part of the contract. It feels like something that I should be able to determine from the SourceFile
.
I believe that SourceFile.moduleName
is populated when you use the AMD directive (e.g. ///<amd-module name="foo"/>
) and the module will always be emitted with that name. Typically when you target AMD and don't use outFile
, the modules are written without any module name. It is only when you set and outFile
or use the directive. If SourceFile.moduleName
as populated on writeFile
with the module names that were used in the emit, that would ensure that there is no doubt about what the module name is in the out file.
I’m kind of surprised if that’s not already the case, but it seems like I might be missing something about your request?
I was surprised too. 😁 Hopefully that adds a bit of clarity.
Cool, thanks for the example. It looks like this comes from the getCommonSourceDirectory
on EmitHost
(which is internal), and despite some 4-year-old JSDoc that says
* The emitted output name can be different from the input if:
* 1. The module has a /// <amd-module name="<new name>" />
* 2. --out or --outFile is used, making the name relative to the rootDir
it looks like it’s intentionally finding the common source directory instead of using the rootDir.
If
SourceFile.moduleName
as populated onwriteFile
with the module names that were used in the emit, that would ensure that there is no doubt about what the module name is in the out file.
So is it undefined right now? Are you using (I guess you’re not using transpileModule
or program.emit
? If the former, you can provide a module name as an option.transpileModule
since that doesn’t take any kind of host object.) But either way, it seems reasonable to me to add the module name (it’s already been calculated at the top of the function) to the transformed source file here: https://github.com/microsoft/TypeScript/blob/71a91763f49ce168782eac59a65161ed0e1595dc/src/compiler/transformers/module/module.ts#L198-L199
@rbuckton thoughts?
So is it undefined right now?
Correct, on writeFile()
on the host, the sourceFiles
that are all there, just .moduleName
is always undefined
(I suspect unless I use the directive, but I haven't tried).
Search Terms
amd outfile module specifier
Suggestion
Currently when utilising the compiler APIs to emit as AMD to a single outfile, the emitted module specifier in the outfile is not exposed, but does not match the source file
SourceFile.fileName
or any other attribute.It appears that there are internals of the TypeScript emitter which determine the module specifier that is included output. For example, if given
/foo/bar/baz.ts
and/foo/qat/qux.ts
being part of the same program, when emitted as AMD in a single bundle the module specifier, the outfile willdefine()
a module namedbar/baz
andqat/qux
. It appears that the algorithm used looks for the common root and removes the extension to determine the module specifier.Use Cases
When loading the bundle with an AMD loader, knowing what a module specifier is in the outfile is needed to be able to specify a module to load in a
require()
statement. So if we were automating a custom build, outputting a "bundle" and determining which module torequire()
to bootstrap the application, we have to "guess" and hope that the emitter doesn't change its algorithm of determining the module specifiers.Examples
I'm not totally sure, but a public API that would take a
SourceFile[]
and provide back astring[]
array of module specifiers. This could be used inHost.writeFile()
to determine what module specifiers are contained in the written file.Checklist
My suggestion meets these guidelines: