Skip to content
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

Issue: I had to disable the Visual Studio integration with the TypeScript compiler #5448

Closed
kasajian opened this issue Oct 29, 2015 · 12 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@kasajian
Copy link

When I build a Visual Studio project that has multiple .ts files, the build system invokes a single tsc.exe compiler using syntax similar to the following:

C:[,,,,]\tsc.exe --sourcemap --target ES5 --noEmitOnError --locale en-US "C:[......]\file1.ts" "C:[......]\file2.ts" "C:[......]\file3.ts"

Notice that the three .ts files are all included in a single invocation of the compiler.

I would like to configure the Visual Studio project so that it invokes tsc.exe once for each .ts file.

That way, the resulting .js file will contain not only contents of the corresponding .ts file, but also the compiled contents from any .ts files it references using the /// references syntax.

Then I would only mark few of the .ts files with the TypeScriptCompile BuildAction. The other .ts files that are meant to be "included" will have their BuildAction NOT be set to TypeScriptCompile.

In addition, I need a way to mark a .ts file both "TypeScriptCompile" and "Embeded Resource". The reason is because I am using a self-hosting service with EmbeddedResourceFileSystem from Microsoft.Owin.FileSystems. I need the .ts file to be embedded so that it is served by the self-hosting web server -- that way it can be used for debugging from the browser when source-maps reference it. But it also has to be marked as "TypeScriptCompile" so that it actually compiles.

As a work-around, I'm doing the following steps:

  1. I removed the Microsoft.TypeScript.targets from the .csproj file. (the .csproj file didn't have it to begin with. I had to add it there. See http://stackoverflow.com/questions/33374040/how-do-i-enable-the-typescript-tab-of-a-visual-studio-project-thats-a-console-o/33374041#33374041 )
  2. put "library" style .ts files in a "mod" folder (stands for modules), but they're really separate namespaces (internal modules)
  3. put all of my "app" style .ts files, the ones I want to compile, into a main root folder. These .ts files may reference one or more .ts files from the mod folder using /// references syntax.
  4. I have a batch file where for every .ts file in the main root folder it invokes the tsc compiler and generates a output .js file which gets placed in an "output" folder. Those are the actual .js files that are referenced from html.

All of the .ts files and .js files in the output folder, along with .map files, are marked as "Embedded" so that they get served by the self-hosting server using EmbeddedResourceFileSystem.

I also added an uglifyjs2 step in there, but I won't discuss that here 'cause that's just an extra optimization step that it's strictly necessary.

Suffice it to say, I'm not using the Visual Studio TypeScript integration at all, which is unfortunate.

Do you guys think that what I'm trying to do is main-stream enough where it should be supported natively?

@mhegazy
Copy link
Contributor

mhegazy commented Oct 29, 2015

I would like to configure the Visual Studio project so that it invokes tsc.exe once for each .ts file.

I do not understand the problem. what do you mean by configure, and why is it not invoked once?
I would appreciate it if you start by explaining the original issue, rather than your solution to fix it.

that way it can be used for debugging from the browser when source-maps reference it. But it also has to be marked as "TypeScriptCompile" so that it actually compiles.

Consider using --sourceRoot to set the location of your .ts files for your debugger, this can be a different server, a local path, etc..

also consider using --inlineSourceMap with --inlineSources, this will avoid you needing a .ts file when you are debugging anyways.

Suffice it to say, I'm not using the Visual Studio TypeScript integration at all, which is unfortunate.

I still do not understand what that means. TypeScript integration is only Language Service (colorization, completion, errors, got to def), and as far as i can tell you can not suppress that. if what you are talking about is MSBuild integration, We provide a set of default targets and tasks, if you do not want to use them, and build your own, it is totally up to you. once you do that, VS will treat your files as "loose files" and will forget about your project file all together.

you can find more details in #2294

Do you guys think that what I'm trying to do is main-stream enough where it should be supported natively?

i do not understand the issue enough; and i also do not understand what you mean by "native" support.

@mhegazy mhegazy added the Needs More Info The issue still hasn't been fully clarified label Oct 29, 2015
@kasajian
Copy link
Author

kasajian commented Nov 5, 2015

mhegazy, yeah, you're absolutely right. I prefer that you close this issue and I'll open a new one that's more coherent :)

Also, based on your response I'm realizing that may be this is not the right repository. My issue is not a problem outside of the Visual Studio integration tool. Is there a separate repository where I can open up an issue to discuss this that's specific to the Visual Studio and MS Build integration..

Thank you.

@mhegazy mhegazy closed this as completed Nov 5, 2015
@kasajian
Copy link
Author

kasajian commented Nov 7, 2015

I asked a question above that didn't go answered which is whether this is the right issues list to bring up issues related to the msbuild portion of the visual studio integration of typescript, or is there another repo for that?

@mhegazy
Copy link
Contributor

mhegazy commented Nov 7, 2015

I asked a question above that didn't go answered which is whether this is the right issues list to bring up issues related to the msbuild portion of the visual studio integration of typescript, or is there another repo for that?

this is the one. please provide more details.

@mhegazy mhegazy reopened this Nov 7, 2015
@mhegazy
Copy link
Contributor

mhegazy commented Nov 13, 2015

@kasajian can you elaborate on the issue with TypeScript MSBuild targets/tasks?

@kasajian
Copy link
Author

Please give me a couple of days and I'll get back to you.

On Thu, Nov 12, 2015 at 10:20 PM, Mohamed Hegazy notifications@github.com
wrote:

@kasajian https://github.com/kasajian can you elaborate on the issue
with TypeScript MSBuild targets/tasks?


Reply to this email directly or view it on GitHub
#5448 (comment)
.

@kasajian
Copy link
Author

The following is what I hope to be a better explanation of the issue that I'm facing. I will start with what works for me using just the command line invocation of the tsc.exe compiler. Then I will describe how I am unable to replicate the same thing using Visual Studio. The question then would be whether my workflow is not main-stream enough to be supported by Visual Studio's typescript msbuild integration, or in fact, I do have a main-stream use case that warrants a feature enhancement for the type-script msbuild integration tool.

Here's what works for me with tsc.exe.
I have an app with two entry points:
admin.ts and play.ts
The files are referenced from two separate html files, admin.html and play.html. In the sample included below, since only console.log is used, you can test this code by either opening the respective html file in your browser the looking at the console, or you can run the .js file directly using node, as in:
node admin.js
or
node play.js

admin.ts uses the /// syntax to reference two ts files, auth.ts and users.ts
play.ts uses the /// syntax to reference two ts files, auth.ts and music.ts

to build admin.ts you invoke:
tsc admin.ts --outFile admin.js
You end up with a single js file, admin.js. Because --outFile is used, the result admin.js file contains not only the contents transpiled from admin.ts but also from auto.ts and users.ts
If you did not have the --outFile command, you'd end up with three .js files: admin.js, auth.js and users.js, which is not what I want. I want to only reference 'admin.js' from my admin.html file.

Similarly, to build play.ts, you invoke:
tsc play.ts --outFile play.js
which results in a single play.js file, a concatenation of the result of play.ts, auto.ts and music.ts

The pattern to have multiple html files in a web sites, each of which load a different set of javascript files is common. Also the pattern to concatenate multiple javascript files into a single one to avoid multiple round-trips to the server is also a common scenario, which I believe is the read why the --outFile options exists.

Now, if I were to attempt to do this in a Visual Studio project, the -outFile is not invoked by default ( as it is with tsc). So you end up with a .js file corresponding for each .ts file, which is not what you want. However, in the project properties under TypeScript Build, there's the option labeled 'Combine JavaScript output into file'. That's great if you have a single html file in your web application and wanted every single TypeScript created JavaScript file to be loaded. But that's the only use case. What if you have a multiple html files and each one to have their own concatenated .js file?

The approach I'm taking now is not ideal which is to remove TypeScript integration from my project than run a pre-build batch file that invokes the tsc compiler with the command line options that I want. It works, but it's not ideal. I'm curious if I'm somehow on the lunatic-fringe with what I'm doing 'cause it doesn't feel like it. It feels like I'm in a fairly mainstream use-case that doesn't seem to be directly supported from with Visual Studio.

By the way, I also tried allowing TypeScript simply create a separate .js file for each .ts file and then use something like uglify2 to concatenate the resulting .js files into a single js. That worked, but now you have two levels of .map files, ones created by the TypeScript compiler for each .js, and one for the final concatenated version. uglify2 supports .map file inputs specifically to deal with transpilers like this, but the resulting output doesn't seem to be compatible with Internet Explorer, which I need to debug from on occasion. Also, ulgify2 is big and slow, and seems unnecessary since TypeScript has the --outFile option that does what I want. And since I have to call uglify2 from a batch file anyway, I'm not saving a step.

admin.html:

<script src='admin.js'></script>

admin.ts:

/// <reference path="auth.ts" />
/// <reference path="users.ts" />

auth.process();
users.process();

auth.ts:

namespace auth {
    export function process() {
        console.log('auth.process called');
    }
}

users.ts:

namespace users {
    export function process() {
        console.log('users.process called');
    }
}

play.html:

<script src='play.js'></script>

play.ts:

/// <reference path="auth.ts" />
/// <reference path="music.ts" />

auth.process();
music.process();

music.ts:

namespace music {
    export function process() {
        console.log('music.process called');
    }
}

build:

tsc admin.ts --outFile admin.js 
tsc play.ts --outFile play.js 

Source code is also attached:
source.docx

@mhegazy
Copy link
Contributor

mhegazy commented Nov 23, 2015

Sorry for the delay. first thanks for the complete write up. short answer there is not a good way to do this in VS today. @paulvanbrenk has a fix for this allowing multiple tsconfig.json files in a project, but this will not be available until 1.8.

Here are some details, the compiler supports two output modes, 1. one-to-one mapping of input to output, and 2. all-to-one concatenating all outputs into a single input. if you want to have multiple islands, with each compromised from multiple files, you need to invoke the compiler multiple times.

you can get your setup working today on the commandline, by calling tsc twice, as you noted above. you can also use two tsconfig.json files to achive this, assuming you have two files admin\tsconfig.json and play\tsconfig.json:

tsc --p admin
tsc --p play

In VS a project maps to a single output, the targets are wired to call the compiler only once. so to achieve the same behavior, you will need to have two projects, admin.csproj, and play.csproj for instance, each will build one output.

Obviously this is a lot of projects for a website, all what you want is a way to build all your typescript files that build your one site. As mentioned above, in TypeScript 1.8, you should be able to do this using tsconfig.json files, you can have as many as you want, each tsconfig.json represents a call to the compiler, and when you build, they will all be fired up.

@mhegazy mhegazy added Question An issue which isn't directly actionable in code and removed Needs More Info The issue still hasn't been fully clarified labels Nov 23, 2015
@mhegazy mhegazy closed this as completed Nov 23, 2015
@kasajian
Copy link
Author

Thanks for the input.

So I'm curious about a feature request to support this, in a way that seems sensible. I now understand that the two scenarios we've been talking about are considered two output modes of the compiler, as you defined above. Perhaps there can be a third output mode to support this. First, could it be done in a simply-to-understand way. Second, is it main-stream enough to warrant it. I assume both of these need to be satisfied. I'll ignore the second one for the moment, so I can have a chance to brainstorm on the first.

We know that Visual Studio will invoke a single tsc.exe with every .ts file that needs to be compiled. So in this example, what is actually invoked is something like:
tsc.exe admin.ts, auth.ts, music.ts, play.ts, users.ts

In the output mode where each .ts is converted to a single corresponding .js file, you'd get those five js files.
What if there was a third "output mode", where the resulting output would be the equivalent of:
tsc admin.ts --outFile admin.js
tsc auth.ts --outFile auth.js
tsc music.ts --outFile music.js
tsc play.ts --outFile play.js
tsc users.ts --outFile users.js

This does not give us exactly what we want, but it's simple in that one can imagine a compiler option that does this, that is, building a separate context for each .ts file, based only on their internal references.

Now, in my case, I don't want the invocations on auth.ts, music.ts and users.ts, so I would change the 'Build Action' for those files to not have 'TypeScriptCompile', which means Visual Studio (msbuild) will only pass admin.ts and play.ts to tsc.exe

However, even if I didn't do that, I could simply ignore the produced auth.js, music.js and users.js since I don't need them.

The new compiler option could be called --embedReferences or --includeReferences.
the --outFile option would be incompatible with this mode.

@mhegazy
Copy link
Contributor

mhegazy commented Dec 1, 2015

Perhaps there can be a third output mode to support this. First, could it be done in a simply-to-understand way.

with the two modes the compiler support 1:1 and n:1, you can get all the combinations you need, you just need to run the compiler multiple times, once for each output. i do not see why we need the compiler to do be able to do everything in one shot.
i understand the scenario you want to achieve, the limitation is not that the compiler can not handle m:n output mode, the limitation is the build system/project system that does not allow you to do this easily. with the work we are doing in 1.8 that should be solved without a new compiler option, and you will have a way to specify different input:output combinations and they should all work.

Second, is it main-stream enough to warrant it. I assume both of these need to be satisfied. I'll ignore the second one for the moment, so I can have a chance to brainstorm on the first.

I think it is "main steam enough", that is why it will be in 1.8 :)

@kasajian
Copy link
Author

kasajian commented Dec 9, 2015

I don't know what 1.8 feature you're talking about, so I'll look into that.

The reason I suggested a 3rd output mode isn't because you couldn't do with the existing 2, but it was because I was lead to believe that Visual Studio will invoke the compiler once per project, to compile all the source files. So if for a single proj file, if there's only a single invocation of the tsc.exe compiler, then one could not do what I'm saying.

The "3rd output mode" would only be there to help Visual Studio. Maybe I misunderstood and Visual Studio can invoke tsc.exe multiple times.

Anyway, I'll see if I can find the feature you're talking about for 1.8.

@mhegazy
Copy link
Contributor

mhegazy commented Dec 9, 2015

I do not think we have on issue tracking all the changes, but here is a run down, first we will allow tsconfig to be used even if you have a project file, something that is not supported today: #5287; also we will be allowing multiple tsconfig files per project, see: #4714.

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

2 participants