-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using shared classes for single output client and common.js based node.js code #5094
Comments
what does your shared code look like? does it have any dependency on node modules? do you have issues using modules in general for your client, v.s. a single output file? |
First things first, i think you should have a two or three tsconfig files, each represent one of your build targets. so a directory structure like so: src\client
src\client\clientClass1.ts
src\client\tsconfig.json
src\server
src\server\serverModule.ts
src\server\tsconfig.json
src\shared
src\shared\sharedLibrary.ts
Then a simple proposal is to use ES6 modules all the way. the compiler will emit your modules down to the appropriate format, so in your server tsconfig.json, you would specify the other option, which is more convoluted and will require a post build step to massage the code; if you can not use module loaders in your client code, is to isolate all module dependencies in your server code, then in the shared, they are just classes. Build the shared files without |
Thanks for the reply! My shared code is very simple: it has no dependency on node or anything outside it's folder, it is just a bunch of interfaces and classes (typically simple models with some methods to validate data). A sample structure would be:
The reason I would want to avoid any dynamic module loading on the client is that I will likely have a lot of module files (= classes in my case), loading them all dynamically would have a significant effect on startup time, and I will most likely need all the classes in my app that are referenced (directly or indirectly) by the main WebApp file anyway so it doesn't add much value to only load the modules dynamically. My aim is to have a single minified js file. So your second suggestion sounds quite good. The only problem I have with is that it's a nice feature of the "--out" flag that it will only compile files that are referenced, so unused classes will not be compiled into the result. The same way it would be useful to only use the classes of the shared folder that are used by the server. However if this is not possible, it's not a biggie. I'm thinking that it could also be possible to have a preprocess step on the shared classes before compiling them for the server code: I could just add some wrapper code to make them modules and so the server compile will work ok with that and it will only pick up the files that are used (required) by the server code). |
We have a PR out (#5090) that will allow you to emit all your modules to a single file (assuming you are not targeting CommonJS). i think this will solve the startup speed, and will act like your bundler. you still need a loader to resolve dependencies, but i think the worst case scenario, you can have a microloader that is 20 lines long, if you have no external dependencies.
this is an interesting proposition. it should be fairly easy to do that, if you are using modules all the way, do you mind filing an issue for this suggestion.
you could do that, but i would reconsider modules. ES6 is now the standards, and modules will be the norm in the coming years, so i would definitely consider them for new projects, to avoid the migration work a year or two down the line. |
That sounds good about that PR and using a microloader. For the suggestion, do you mean that the PR you linked could be able to only output referenced modules or? ES6 modules seems to be the standard, although I definitely remember a few years ago when everyone was all about amd and that that was going to be the future. I believe that it will in fact be ES6 modules, but my biggest concern about that is that I feel it has a slightly different purpose than how I'm organizing my code. I try to follow best practices used in Java, C#, C++ codebases ie. to use a lot of classes, even for the smallest things, each being in it's own physical file, so I really have a lot of classes. To me namespaces work well, and I prefer using references instead of imports/requires (a small annoyance with imports is that WebStorm only shows the import/require line if I click on a Class type as opposed to navigating me to the actual Class file. |
Sorry about that. i was thinking of #4434. i think for your needs, you can get this working today. assuming that you have your code all organized in modules, if you pass your "entry module" to the compiler, it will follow the "import" statements and only emit the ones that are used. giving you a module-level tree shaking support.
it is totally up to you, but again, if you are starting on a new project, i would give modules another look
hopefully merged within the next few days or so, once it is in master it should appear in the nightly npm release ( |
I thought of another way, but I can't get it to work.
The problem is the variable express should have proper typing, and I couldn't get it work.
but this doesn't work:
Then I tried the methods suggested here: But even when I had a typings.d.ts file with the content:
and I try to use it like this:
I get these errors:
This is with TS 1.6.2 with compiler options: Index.ts --target ES5 --out index.js |
I do not think this is going to work. the way the express typings are authored is to only be imported as a module. |
That's ok. In the meanwhile I have found a solution for this entire topic which I think will work for me, but I'm still going to consider switching over to ES6 modules in the long term.
|
Looks like this has been addressed. please reopen if you have other questions. |
I have a general question about project structures / modules.
It's a project with 3 types of code:
My aim is this:
I can't seem to achieve these goals. The problem is this:
These are the options I think I have:
What I'm really looking for is a way for each TypeScript class/file to be able to "say" what is the class it exports, but not specify how it will be consumed, ie. via commonjs or as a single file output. Probably that's not possible though in a simple way?
The text was updated successfully, but these errors were encountered: