Skip to content

Compiling with --noResolve elides needed imports #3122

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

Closed
breck7 opened this issue May 11, 2015 · 19 comments
Closed

Compiling with --noResolve elides needed imports #3122

breck7 opened this issue May 11, 2015 · 19 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@breck7
Copy link

breck7 commented May 11, 2015

car.ts:

export class Car {
    public beep(): void {}
}

truck.ts:

import Car = require("./car");
class Truck extends Car.Car {}
new Truck().beep();

I expected ./car to be defined in both of these scenarios but it's elided in the first:

'tsc --target es5 --module amd --noResolve truck.ts' => 'define(["require", "exports"]'

'tsc --target es5 --module amd truck.ts' => 'define(["require", "exports", "./car"]'

@danquirk
Copy link
Member

This is exactly what --noResolve is for. From the docs in our wiki:

Do not add triple-slash references or module import targets to the list of compiled files.

What were you trying to do with it?

@danquirk danquirk added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label May 12, 2015
@breck7
Copy link
Author

breck7 commented May 12, 2015

@danquirk, in a larger project we are extending a class just like in this simplified test case. I understand that TS will omit imports if the imported file only includes type info required at compile time but in this case the imported file is required at runtime.

I get the expected output even with --noResolve if I add an "amd-dependency" tag or use the import in a value position like:

import Car = require("./car");
Car;
class Truck extends Car.Car {}
new Truck().beep();

but this seems odd. Ideally there would be a command line option to tell the compiler to always force imports.

@breck7
Copy link
Author

breck7 commented May 12, 2015

@danquirk I could be reading it wrong but I think the wiki seems to refer to not compiling those triple-slash references or module imports into new js files, which is what happens and what I expect. I don't understand why it would assume that the "extends" is only being used for type information, when in this case it's structural.

@danquirk
Copy link
Member

amd-dependency is for explicitly specifying what gets emitted into the require list, regardless of other logic (specifically to override things like the omitting logic for type only imports, or non-javascript require targets that TS doesn't support). That directive is one way to 'force imports' although it isn't as convenient as some global option. But it's not clear why you actually need to force imports here since it's doing the correct thing by default (without --noResolve).

The compiler isn't omitting the import for car because it thinks it's only used in type position. As you see in your original example it gets emitted correctly when you do not use --noResolve. When you use --noResolve you've explicitly told the compiler not to emit the import for car because it was an import target (of any kind). If I use Car in a value position like you did then there is a compilation error if I also use ---noResolve.

I still don't understand why you actually need --noResolve here. It is doing exactly what it's supposed to do though.

@breck7
Copy link
Author

breck7 commented May 12, 2015

Yes there is a compiler error in the output messages but the js output is fine.

I'm using --noResolve for incremental compilation in Visual Studio Code.

Without --noResolve compiler takes ~12 seconds to recompile all dependencies even though only the current file has changed. Adding --noResolve drops it to under 2 seconds.

I'm not sure if there is a better way to compile only the changed file.

@danquirk
Copy link
Member

The compiler makes a best effort to emit in the presence of a variety of errors. But there are still errors for a reason. Sometimes the emit is still usable, sometimes it is not, it depends on the particular error(s).

@breck7
Copy link
Author

breck7 commented May 12, 2015

Sorry, seems the rest of my response got cutoff.

I'm using --noResolve for incremental compilation in Visual Studio Code.

Without --noResolve compiler takes ~12 seconds to recompile all dependencies even though only the current file has changed. Adding --noResolve drops it to under 2 seconds.

I'm not sure if there is a better way to compile only the changed file.

@danquirk
Copy link
Member

Ah, sorry, missed the expando button in your last reply. Yeah --noResolve is not really what you want to be doing here to get compile on save behavior. It's really for a very different set of scenarios.

Until VS Code has proper compile on save built in you should just use the tsc -watch (--w) option on the command line. Just run tsc -w from the folder where your tsconfig.json is and the compiler will automatically recompile files in your project as they are changed.

@breck7
Copy link
Author

breck7 commented May 12, 2015

Much simpler! Thanks @danquirk

@breck7
Copy link
Author

breck7 commented May 12, 2015

:( @danquirk even with watch tsc is recompiling all dependent files.

@DanielRosenwasser
Copy link
Member

Can you elaborate? Does tsc compile dependencies on the first run, or is it only on recompilations?

@breck7
Copy link
Author

breck7 commented May 13, 2015

It compiles all dependencies both on the first run and everytime a single file changes that requires that dependency.

I have a folder with the 2 files above ("car.ts" and "truck.ts"). Truck.ts imports car. When I modify truck.ts both files are recompiled.

I'm running the command: "tsc --watch"

My tsconfig.json is:

{
    "compilerOptions": {
        "target": "es5",
        "module": "amd"
    }
}

@breck7
Copy link
Author

breck7 commented May 13, 2015

Output messages seem to indicate that tsc is doing an incremental compile but yet the modified timestamp on all dependencies changes.

message TS6032: File change detected. Starting incremental compilation...
message TS6042: Compilation complete. Watching for file changes.

@DanielRosenwasser
Copy link
Member

@breck7 can you open a new issue given that the original issue is slightly different?

@breck7
Copy link
Author

breck7 commented May 15, 2015

@DanielRosenwasser Done. #3184 Thanks!

@mhegazy
Copy link
Contributor

mhegazy commented May 18, 2015

@breck7 VS allows the feature you are asking about (compile-on-save). Why you are not using compile-on-save?

@breck7
Copy link
Author

breck7 commented May 18, 2015

@mhegazy Compile-on-save works, but it ends up recompiling all dependencies as well. We are seeing an order of magnitude slow down versus compiling only the edited file via --noResolve. (~12.5s vs ~1.3s for most files in our project).

--noResolve leads to a lot of noise in the output but for rapid prototyping allows you to do a code-compile-test loop a lot faster. The only problem we are running into is when we don't use an import in a value position and TS assumes that import is only being used at compile time, even when it is a class being extended.

There are definitely hacks we can use to workaround this, like simply using the import in a noop value position or using // <amd..> tags, but ideally there'd just be a way to force imports.

@mhegazy
Copy link
Contributor

mhegazy commented May 18, 2015

--noResolve is to tell the compiler to not include dependencies into the compilation that were not passed on the command line. i would use that only if i have a custom resolution setup, i.e. my modules exist in a different place than where the compiler would expect them to be. using them to limit the compilation in the manner you are trying is not something that is supported..

The real problem is that the language itself does not grantee that a single file transformation is sufficient. e.g. const enums and internal module property qualification. I believe what you need is a fast compile-on-save if you are using --separateCompilation. I have files #3204 for this.

For the MSBuild incremental build, incremental build is done on a project level, the whole project is built in one shot or not. The compilation will be triggered if the any file in the project has changed, and this would be the case regardless of what flags we pass, if that is something that you really need, i would recommend looking into other build systems like broccoli, grunt, or gulp.

@breck7
Copy link
Author

breck7 commented May 21, 2015

Thanks @mhegazy! Seems like --separateCompilation flag might help. I'll look into optimizing for our situation using the TS service as well. It seems Atom compiles just the changed file so I'll see what they are doing.

@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
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead
Projects
None yet
Development

No branches or pull requests

4 participants