Runtime Module Resolution

Topics: General
Oct 1, 2012 at 8:48 PM

How does runtime module resolution work? How are modules defined after compilation takes place in the case where the browser is the target and AMD is needed? Can I plugin requirejs or is there a built-in module loader that is exclusively used?

Oct 1, 2012 at 9:59 PM

You can find a complete description of how module resolution works in the language spec section 9.4.1, but in brief: when you want to import "./foo", the compiler will look for foo.ts in the same directory as the file that referenced it.

The compiler will only emit the modules themselves (either AMD or CommonJS). If you're targeting the browser, you will still need to include an AMD-compatible module loader. RequireJS works great for this!

Oct 1, 2012 at 11:12 PM

I am really, really happy about this :)

Oct 2, 2012 at 12:13 PM
Edited Oct 2, 2012 at 12:13 PM

I've been trying to compile the mankala sample for use with an amd loader. No matter what compiler options I specify, it does not generate anything with amd define calls. Can you give me an example of what I'm supposed to give the compiler?

Oct 2, 2012 at 1:45 PM

Ok. Now that I've gone and read the language spec on modules ;)....I understand why it's doing what it's doing. I'll play around with some of my own code and see if I can get it to do what I want.

Oct 2, 2012 at 3:48 PM
Edited Oct 2, 2012 at 3:51 PM

To get my samples working with AMD, I downloaded the latest require.js file and added the following script reference to my HTML file:

<script src="lib/require.js" data-main="src/app"></script>

I also had to modify my tsc command-line as follows:

tsc --module AMD
Oct 2, 2012 at 3:58 PM

Yeah. I figured that out eventually...the problem was that the sample I was trying to compile wasn't written with external modules.

Oct 2, 2012 at 4:05 PM
Edited Oct 2, 2012 at 5:12 PM

It seems like we have 3 options for modules:

  1. If we're using node and import/module syntax, then we must use CommonJS modules (--module CommonJS)
  2. If we're using the browser and import/module syntax, then we must use AMD modules (--module AMD)
  3. If we use ///<reference> directives, but not import/module syntax, then we can use a single JS file in either node or the browser (--out file.js)

This is all nice, but I would also love it if we could have support for #2 (import/module syntax in the browser) without requiring an external AMD loader (i.e. RequireJS).

This is similar to what browserify does for node, allowing node modules to be run directly in the browser. The require function works because the dependencies were detected at build time and included in the build output file. It seems like TypeScript is very close to being able to do this as well.

Oct 2, 2012 at 4:24 PM

Do you mean by including a minimalistic loader script in the final build? That's probably a good idea as long as there's still an option to provide your own.

Oct 2, 2012 at 5:10 PM
Edited Oct 2, 2012 at 5:11 PM

Yes, basically the build output would detect and "bundle" all dependencies in the output file, plus would include an implementation of the require function which would provide the required modules directly (i.e. without looking in the file system or making an http request, etc).

This is what browserify/browserbuild/ender all do for node modules in order to get them to work without modification in the browser.

I want to be able to write one syntax (e.g. import my = module("./my");) and have it work in both node and the browser without having to worry about AMD, RequireJS, or compiler options.

Oct 2, 2012 at 5:16 PM

That sounds good to me. I think a lot of people would find that to be a natural usage and expected output. I'd be all for that...though on the condition that you can apt to supply your own amd loader like you can today....for those of us that are using loader plugins and doing other....interesting things...