Large TS project for use in nodejs and browser, with reusable *modules*... having problems :(

Topics: General
Aug 8, 2013 at 8:55 PM
Edited Aug 8, 2013 at 8:57 PM
I will try and keep this short, but I am sure I will ramble on for a while... a bit of background first.

I was converting a large predominantly JS browser app over to use typescript, which has been brilliant and works fine. In this environment I was laying my code out like I would with a c# project in .net, so I would have a module called "Shared" in a folder called "Shared" and that would contain lots of files within that namespace. Then they would all be compiled into one js file, in this case called "Shared.js" which would contain all the Shared.* namespaces.

So then in another module I could do "var localStorage = Shared.LocalStorage.LawnchairBackedStorage("some-store-name");", which all worked great as they were all done as internal modules, so due to the browsers global scoping they could all just be bulk included in the page and would all just work. So providing everything was included in order the module namespaces would all get shared so my module mentioned above would know about the Shared.* namespace as its in the global scope.

Then I decided I was sick of having 2 versions of my app models and certain logic, as the web service was all written in C# with ASP.MVC, so nodejs made sense as I can re-use a lot of the same code and to be honest it looked like it would solve more of my problems easier than MVC (such as sending back models with dynamic json data).

So I am now going down that path and the first issue I encountered was that nodejs would not require my modules, as if I did "var Shared = require('shared.js')" it would just complain because there is no module export definition in the file. Which made sense as to this point I had been using internal modules, but was happy to use exported modules, as this would make more sense than having ///references all over the place.

So I asked this question:

However most answers were all aimed at using internal modules with ///references sprinkled throughout my app, which I didnt want to do. So like the answer in that question shows, I found a nice hack which would let me have my cake and eat it (or so I thought).

So now lets fast forward to my current problem, So I have module_a which is dependant upon module_b, both modules are comprised of many smaller files all within a given root level namespace, so "ModuleA." and "ModuleB.", now although my "export.modules = <MyModuleRootNamespace>" hack seemed to work, where there are module dependencies it just falls over, as within the context of the "ModuleB.js" file it wont know about the stuff within "ModuleA.js" as each node.js require is in its own scope. So in the browser all the namespaces just kinda oozed together like a nice blob of logic, whereas in node.js each is compartmentalised and although I do like this approach, I cannot see how I can achieve the following 3 things:
  • Have my module code split out over many files
  • Have my code grouped via namespaces
  • Have my modules know about other Modules
I am currently looking at doing some sort of pre-processing hack so the top of each file would have a "var ModuleA = require("ModuleA.js");" so it would at least let me continue on with my project until I find a better solution, but its all very hacky.

I did find this question below, which seemed to give me one avenue to look down but again the module flag paired with the out flag dont seem to play well with code grouped by namespaces.

So could anyone offer any advice? as I need to share these modules between the browser and the server, each which consumes them in different ways, but currently it seems like I cannot have inter-module dependencies on the nodejs side...

Any help would be great!
Aug 9, 2013 at 9:47 AM
Just to add to this, currently I have added a preprocessor file which will add the "Module1 = require("Module1");" so it will satisfy the internal dependencies between the modules, it feels a bit like a hack but without it the generated Typescript will never be able to satisfy its references at compile time without global scoping.
Aug 9, 2013 at 7:33 PM
Just to make sure I understand, it sounds like what you're basically asking about is:
  • Having multiple TS files contribute to a single external module (roughly analogous to multiple C# source files contributing to a single DLL), which currently is not supported by the Typescript compiler.
  • How to manage circularity between these individual files which would somehow contribute to a single external module.
Is that right?
Aug 10, 2013 at 7:30 AM
First bit is correct, second point not so much.

As I do not have any circular dependencies, I just have a lot of modules which just expose logic for re-use or extending within other modules, so currently the problems are that typescript is not compiling my module (like c# dll) with any exports, so I have to manually append "module.exports = mymoduleroot" to my compiled files which outputs the module in a node compatible format for requiring. However if a given module depends upon other given modules I could not find a way to represent this dependency through typescript, so currently I manually pre-process the typescript files with the requires I need in place.

It all works, it just feels a bit hacky, I may not be developing 100% the way I should be as in an ideal world each one of these modules would be its own node package, however I cannot find a solid way to flag these dependencies to node package manager without them being in their own git repository, which would make the project unwieldy as there are lots of modules and various application end points which use them (web-service, web-ui, mobile-ui etc). So maybe if I was developing this way it would be slightly easier to require modules.