Nativescript: change the outDir of the transpiled code

Created on 15 Sep 2017  路  53Comments  路  Source: NativeScript/NativeScript

I don't like the js files being generated next to my ts/ng files , it's so annoying , so I was trying to put the compiled/transpiled js files outside the app directory, as any Angular app.

what I did is :

I added outDir to the compilerOptions inside the tsconfig.json file

{
    "compilerOptions": {
        "outDir": "./compiled/",
....

and changed the main entrypoint inside app/package.json

{
  "android": {
    "v8Flags": "--expose_gc"
  },
  "main": "./compiled/main.js",

by doing so the app crashes since it can't find the main.js...

what is the correct way to achieve that?


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

feature low

Most helpful comment

  • not everyone is using VS code or any editor with the ability to hide transpiled files
  • Some version control systems might try to add transpiled files into version control each time the files are generated. Separate dist folder can be easily put into version control system's ignore list.
  • Imagine you'd like to .zip you project for any reason. There is no need to include any unnecessary files which would increase the .zip file size.

Ideally I would like to set the tsconfig.json's outDir under root folder where also node_modules are.

All 53 comments

Hi @AbanoubNassem,
In case you are using VSCode, I would suggest simply to hide those files, which you do not want to see instead of moving them outside the app folder. More about this suggestion you could find here in this thread.
Regarding the topic, if this suggestion is not applicable to you, could you provide some detailed info, why you would like to move those files.

Closing this issue due to inactivity

  • not everyone is using VS code or any editor with the ability to hide transpiled files
  • Some version control systems might try to add transpiled files into version control each time the files are generated. Separate dist folder can be easily put into version control system's ignore list.
  • Imagine you'd like to .zip you project for any reason. There is no need to include any unnecessary files which would increase the .zip file size.

Ideally I would like to set the tsconfig.json's outDir under root folder where also node_modules are.

As a workaround, could we use a src directory for our TS files and have all compiled output go to app?

Hiding all the JS files is not a suitable approach, since even in a Typescript application some of your source files may still be Javascript.

Having transpiled files alongside source files is a nightmare since there is no simple way to exclude them from being committed into source control when the transpiled files are potentially the same type as some of your source files. Not to mention the fact that it makes your codebase look twice the size in your editor thus making anything twice as hard to find.

Is there any reason why this would be a difficult issue to fix? Can't tns simply be modified to respect the output directory defined in tsconfig.json? Is the source for tns in this repo?

I see that in NS 4.0 they've enabled Livesync to function with WebPack watch mode. I wonder if there is some way that could that be used to achieve a separation of source and output files?

Any progress on this ? This is really annoying to have src and dist in the same place :(

So this is about a year old issue now, but to me this looks like something that should have been in the tooling from day 0.

Regarding the topic, if this suggestion is not applicable to you, could you provide some detailed info, why you would like to move those files.

Keeping sources and products of a build process separate is a very basic and obvious need in my opinion. By definition sources is something you're working with and something you modify to get desired results. You never want to modify those .js files, nor you ever deal with them in any way as they are just an intermediate result needed by the framework. They do pollute the source directory.

It really is not a viable option to solve it on the IDE side. What if I use terminal to work with my source code or an IDE that doesn't let me hide files?

@ilyalukyanov - First of all speaking preferences -- I would tend to disagree; I'm glad they are in the same folder because when I'm debugging a file and the a crash points to a line in the JavaScript; it is very helpful to just open up the JS file and look. phpStorm by default hides the JS files in the same folder; like so it looks like so (what JS files? :grinning: )

image

and so I just hit the little arrow button:
image
and bam I have VERY easy access to the actual source file I need. I would REALLY HATE to have to go navigate and find the JS files...


Now as to the technical reasons why it does this; is because NS supports not only TS, but it also supports people who prefer to use straight ES5/6 JS code. These people don't need any transpile step, the files are in the folder like so:

image

So, this would add a bit more complication to the tooling to add extra code to automatically split out the JS (from the TS version) into a separate folder and then during the build to grab all files EXCEPT the TS files from the normal directories and merge them in with the newly "separated" JS for building the application.

Right now; the tools don't have to do any extra work to build a JS or a TS app. So tooling wise the current design is a lot simpler, meaning less things can go wrong in not only the TS->JS phase, but the JS to app, and LiveSync'ing.

However, if someone from the community create a PR to add all the extra code to the CLI tool to handle this properly for both TS and for JS apps without slowing down anything -- they would probably gladly merge it...

@NathanaelA Although I agree that this is a question of preferences, speaking about debugging I always want stack traces to point in the actual source file, which in that case would be .ts, not .js files. Normally this is solved by sourcemaps and I'm not sure whether there are any limitations in NS that make those impossible. Nevertheless, I know that there are ways to enable them in V8 and if that's also the case for NS, sourcemaps would be a very useful improvement.

I appreciate there are design benefits of having it this way. However, I'd like to challenge some of those design decisions. I can be terribly wrong, but is there actually a relatively big number of developers using vanilla JS with NS? I'm not saying TS is our everythings, but there are other tools like babel, flow and numerous JS dialects which need transpiling. While some of those things can be easily sacrificed for the sake of simplicity, I think in most cases it's all about type safety, which is a big trend if not a defacto standard in modern app development.

I'm not saying support of vanila JS shouldn't be a priority. Many NS apps were created before this era and compatibility is important. I guess my point is that there would be enough demand to make tooling more transpile friendly in an opt-in way.

@ilyalukyanov

  1. Sourcemaps; I'm pretty sure actually do work inside of the Chrome & phpStorm tools to step through code; I'm like 99% sure I've done it several times. Hard to keep track, I do web work too. :grinning:
    However the crash reports do not use source maps to my knowledge; so having quick access to the JS while developing is a good thing. I can pop open the JS see the line that it is failing on, and know right where to go in the original TS (if I'm using TS) file. :grinning:
  1. JS support depreciation, your talking to the wrong guy, I'm totally on the opposite page. :grinning: I'm a huge huge fan on pure ES6 JS. TS has some things that are very cool; but I can't think of anything that it can really do over pure ES6 w/ phpStorm. However I can think of several negatives to TS that I've personally ran into, things that have cost me days of work, that was trivial in JS. The largest is that the apps/plugins that I've written in TS; have always been developed in probably 10%-15% more time than the JS versions. The reason why is because LiveSync/LiveEdit is incredibly fast with pure JS over TS. You eliminate the whole TS transpiling which actually does sap a lot of time over the life of the project. I ran the numbers about a year ago; I think, if I recall correctly liveedit was like < 1ms to sync a JS file. Transpiling the TS into JS was > 200ms. (these number are from memory; I just recall thinking holy crap TS transpiling is a killer time suck and you get hit each change...) Now maybe this is because of the way I develop; (add and test a feature, then add and test another feature, etc); but TS has always slowed me down when a client has required it for their project. Please note; the benefits the TS offers, phpStorm pretty much mimics for pure JS, which is why I said TS doesn't offer me much -- if I was using vsCode; I probably would be more firmly in the TS camp for the features it does offer.

So demand for excellent JS support is very high from me. As one of the top plugin authors ( https://plugins.nativescript.rocks/authors ) ; I hope my opinion still matters. :grinning:

Please note; several of my team members at nStudio are huge TS supporters; and the entire NativeScript is developed in TS, so their is a huge number of people using TS. So I fully understand your desire. The NativeScript team has to walk a fine line, and at this point the tools actually works; adding another location for JS files to be transpiled to would add a bit of work in the CLI as they would have to merge two trees of code during each build rather than the single tree (which would slow down building/livesync'g slightly). This does take engineering resources, and creates more code that could be buggy. And overall doesn't really offer any major benefit, that I can think of. (And this is the key point, what Major benefit does it offer?)

For ways to make it easier to use the existing tooling:
I do know vsCode can also hide JS files, not sure it is as seemless as phpStorm (haven't touched vscode in over a year), but there is a setting for it... In addition; for projects that I do use TS on, my .gitignore excludes .js files on those projects.
image

Most version controls allow you to exclude file types; and then even include them manually if you need a a couple .JS file added to your repo...

When I need to zip it up; it is trivial to use 7zip to archive it up and exclude js files:
image

Please note, I'm not at all against this feature (assuming it is opt-able); -- I just was trying to help everyone on this bug understand the reasons this feature request is probably a very low priority (maybe even a non-starter) for Progress. Fix bugs that do exist and are reported; or add a feature that will actually complicate the CLI some, slow things down some, and could risk adding more bugs. The benefits really has to out way the detriment for them to consider it...

So, imho, the most likely way for you to get this feature implemented is if the community does so...

Just because you don't like typescript isn't a valid reason to ignore the issue that writing in typescript causes generated code in the same folder as source code. The {N} project highley promotes using typescript however the experience is cringeworthy to have generated code mixed in with source.

This should be a top priority. Separating src and build files is an extremely common workflow. Your personal opinions are not valid reasons to ignore your community.

Found a way around it, move the app folder to src (leave App_Resources in app), set paths in tsconfig.json to be src/* and outDir to be app

So, this would add a bit more complication to the tooling to add extra code to automatically split out the JS (from the TS version) into a separate folder and then during the build to grab all files EXCEPT the TS files from the normal directories and merge them in with the newly "separated" JS for building the application.

Not sure where this thinking comes from. The only real example where you would need the nativescript process to "grab all files EXCEPT the TS files from the normal directories" would be the App_Resources folder, which could very easily be separated from the rest of the actual application source. Everything else is handled by the various (optional) build systems. This is not even a typescript issue, as the issue exists when handling css preprocessors like sass.

A larger issue here is, why should nativescript even care where or what my source is? Why can I not point nativescript to a folder that has pure js and css and everything works out of the box? Regardless of opinion or preference, this option should be configurable, and it should have been configurable from the start.

Can someone from the NativeScript team please respond to this ticket? Is this something you plan on working on? @NickIliev @vakrilov @hamorphis @PanayotCankov

@stweedie - Not sure where this thinking comes from.

It comes from me knowing how all the tooling to make a NativeScript app works, including committing patches to fix issues in pretty much every single NS repo. In fact I had LiveSync working for several releases before progress/Telerik had LiveSync in TNS. I also have working app wide JS encryption, and working app updating outside of stores. So sufficed to say, I am quite familiar with ALL the tooling and internals. :grinning:

Right now it is a copy all files out of the /app/ into the platforms/<some path to>/app folder and it is done (well it is a bit more complex, but we will pretend it is this simple); if you had a separate output folder; you would have to

  1. Copy everything as is (except: ts) from /app/
  2. Copy everything from new /outputsrc/ export folder tree into the same /app/ folder.

So first you are adding the speed hit of adding a second descending copy pass, for all those TS users. Yes, it isn't hard to add; but it adds another point of failure and addition build time.

Next instead of just watching just the /app/ folder for changes; you now have to watch the /outputsrc/ folder tree for for LiveSync change purposes. And then these files have to be remapped back into the proper folder structure during a live sync. Again not hard to add; but add another couple failure points and additional memory required for more watches.

In addition if you are using webpacking, you now have to make sure webpack is now aware of two separate folder that are the same; as webpack can include xml/css/html into the webpack file in NativeScript; and if you do read("./blah") it needs to understand ./blah could be in either the ./app/ tree or the ./outputjs/ tree.. Again not hard to add; but adds more failure points.

Each of these can be handled, but each adds new possible corner cases. And some of those adds additional speed hit, as the deeper your directory tree is; the longer it takes to have to process TWO copies of the tree.

The only real example where you would need the nativescript process to "grab all files EXCEPT the TS files from the normal directories" would be the App_Resources folder.

And you would be wrong. :grinning: At this moment; you can have a "fonts" folder, maybe some .json configurations files, images, sound, sqlite database. I can keep going on, and on; but there can be a lot of NON JS/CSS/XML files in your app that you or other developers may use.

A larger issue here is, why should nativescript even care where or what my source is?

Because right now it is using the KISS principle. Keep It Simple & Stupid. The less moving wheels; the less likely something is to break.


I have stated several times in the thread; I'm not against this support. The only reason I tried answering was to try to provide some context for you all. I'm not on the NativeScript team; but over the last couple years I've seen which items they work on and which they don't. (There are several issues with considerably more votes, that are also just sitting, so don't take it personally.) If they have 20 hours of man time to work on say adding TS to external locations; or they can fix X bugs. Unless you can give them a compelling reason to prioritize adding a preference feature over bugs; the odds of this being done are extremely slim. It has nothing to do with my preferences, just me trying to say hey guys; this is the reason why this isn't likely to see the light of day, and nobody so far on this thread has made a good case for it taking the development resources over other projects that already have a compelling reason (like fixing bugs).

So, in summary, and as I stated several times; if you feel this is a needed must-have feature; be an contributing community member and create the PR! :grinning:


Btw, @joesonw solution is a valid solution to separate out the TS code; it is the opposite direction; you move your TS source out of the app directory; and leave the APP directory for the compiled JS code. This way everything in the tooling continues to work as it expects the JS to be in the app directory.

I see this has been quite a discussion and I would like to call for good will and respect. The JS community is so diverse that it would be hard to find to devs that share exactly the same tools and workflow. It is part of the reason this community is so great and fast-moving.

That said, here are the reasons we haven't really worked on having configurable out dir and haven't considered it a high priority:

  • To create an app-package you use the nativescript CLI which goes to numerous steps to prepare, build and pack the application. In the end you get .apk(Android) or .ipa(IOS) file. There are really no cases when you need a production-sources-only dist folder, which you want to manually deploy. You would need the app-package instead, which is already cleared of all the TS files.

    • Typescript transpile is just one of the many steps performed during build. There are a bunch of other dev-plugins (SASS, LESS, webapck etc.) which plug into the prepare process. Most of this tools work in the current folder by default and for the sake of simplicity (and stability) we left it this way. You would need a way to configure/pass an "out" folder for each of them otherwise.

    • Most of the IDEs and source control managements tools support an easy way to hide/ignore unneeded files. Many of the TS/Angular templates come with a preconfigured .gitignore file. We are not forcing you to use git (or VSCode) of course - we added it because many of the NS users do.

    • There is some level of configuration of you project dirs you can use decried in the project structure docs. It doesn't allow a lot of flexibility and it will not let you split the TS/JS files by default, but you can build on top of that. For example, there are folks using gulp to copy files the NS app folder in order to achieve code-sharing. As @NathanaelA said - @joesonw's solution also seems legit - you would have to find a way to copy other file types (.html, .css, package.json-s etc.).

Yesterday we ran into a really annoying bug (that we caused ourselves), which was really hard to debug due to keeping transpiled outputs alongside source files.

_The following assumes that you've hidden output .js files (VSCode), as most people would..._

Suppose you have a module with a buggy dependency:

import { NgModule } from '@angular/core';
import { SettingsComponent } from './settings.component';

@NgModule({
    declarations: [
        SettingsComponent, // <-- Buggy
    ]
})
export class SettingsModule { }

The developer now decides he wants the rename the file to user-settings.component.ts instead of settings.component.ts, before starting his bug fixing.

What will happen?

  1. VSCode's automatic refactoring help when renaming files will do absolutely nothing. Why? Because the import in the above module would still be valid, but now point to a hidden (buggy) .js file instead of the renamed .ts file. VSCode would look at the references and go: "Hmm, I can't find any references to settings.component.ts (because the import now implicitly points to the .js file), I guess there wasn't anything using that file".
  2. The developer would gladly code along in his new user-settings.component.ts file, fixing all the bugs, not realizing that his module is pointing to the hidden, buggy and wrongly-named settings.component.js file.

Imagine working on really big projects, with hundreds of files, and how hard a problem like this could be to debug.

Could we please escalate this from low to a higher priority?

Not sure why this isn't a higher priority. Having build files separate from source files is a very common workflow and should be supported based on shear popularity alone.

It clears the source folder from clutter, makes files easier to find, makes source control easier, and is just good separation of concerns. Imagine having your byte code in the same folder as your Java code, your assembly code in the same folder as your C++ code.

We shouldn't have to rely on editor config that not all editors support. Also consider using a file explorer or a terminal to find a file, then you definitely can't rely on editor config. Is NativeScript not aiming for excellent Developer Experience?

Yesterday we have ran into a really annoying bug (that we caused ourselves), which was really hard to debug due to keeping transpiled outputs alongside source files.

_The following assumes that you've hidden output .js files (VSCode), as most people would..._

Suppose you have a module with a buggy dependency:

import { NgModule } from '@angular/core';
import { SettingsComponent } from './settings.component';

@NgModule({
    declarations: [
        SettingsComponent, // <-- Buggy
    ]
})
export class SettingsModule { }

The developer now decides he wants the rename the file to user-settings.component.ts instead of settings.component.ts, before starting his bug fixing.

What will happen?

  1. VSCode's automatic refactoring help when renaming files will do absolutely nothing. Why? Because the import in the above module would still be valid, but now point to a hidden (buggy) .js file instead of the renamed .ts file. VSCode would look at the references and go: "Hmm, I can't find any references to settings.component.ts (because the import now implicitly points to the .js file), I guess there wasn't anything using that file".
  2. The developer would gladly code along in his new user-settings.component.ts file, fixing all the bugs, not realizing that his module is pointing to the hidden, buggy and wrongly-named settings.component.js file.

Imagine working on really big projects, with hundreds of files, and how hard a problem like this could be to debug.

Could we please escalate this from low to a higher priority?

I ran into the same problem last week. I had simply moved a service up one directory, started making changes, and recompiled. I wasn't hitting any of my new debuggers, and seeing what I thought was stale code, but was the old .js file being used over the new recompiled one (I had 2 instances of my service being registered because of this as well). Wasted a good hour or more trying to understand what was happening, and ended up writing a cleanup script to handle old .js files.

Found a way around it, move the app folder to src (leave App_Resources in app), set paths in tsconfig.json to be src/* and outDir to be app

Has anyone confirmed if the solution from @joesonw works? I plan on trying it myself soon to see if its a good enough workaround.

Found a way around it, move the app folder to src (leave App_Resources in app), set paths in tsconfig.json to be src/* and outDir to be app

It builds but the android app is not working now.

Death by 1000 minor inconveniences . i m tired of wasting my time on this kind of issues. Could have learnt swift and java by now.

Can there be an elegant solution for this?

Perhaps something in nsconfig.json:

{
  "appResourcesPath": "App_Resources",
  "appPath": "src",
  "buildPath": "dist"
}

HINT HINT

https://github.com/NativeScript/nativescript-cli/issues/3257

to be honest , I have completely gave up on NativeScript, because of this issue!

Maybe one day Telerik will read this thread and think "geez, maybe they have a point"

Not sure why this hasn't been mentioned but, using --bundle does not generate js files all over the place, as webpack handles the transpiling.

@AbanoubNassem sorry to hear that was s showstopper for you.

@dolanmiu we have stated the reasons why this feature is not a priority - you can see the details here https://github.com/NativeScript/NativeScript/issues/4842#issuecomment-408868005.

Not sure why this hasn't been mentioned but, using --bundle does not generated js files all over the place, as webpack handles the transpiling.

Is there a way to include --bundle by default in tns run command?

@umutesen tns run android --bundle --env.aot is my preferred command these days.

@umutesen tns run android --bundle --env.aot is my preferred command these days.

Does this work with an Angular NativeScript project?

@dolanmiu the --env.aot (Ahead-Of-Time compilation) is in fact an Angular specific command.

I would also recommend also including the --env.uglify which provides further improvments for your app.

tns run android --bundle --env.uglify --env.aot

Good point by Nick, however be aware that --env.uglify can increase your build times by quite a lot. Personally I recommend it in production builds mainly.

The thing that lead me here is this error:

Error: It's not clear which file to import for '@import "app-root"'.
       Candidates:
         app-root.scss
         app-root.css

Compiling is breaking on even the most basic of projects because of this.

Alright, I got a nice setup going for separating app from src
The basic gist is making a your nativescript project into a js one, then doing all the transpiling yourself.

  1. Make sure sass is installed (if you're using it) npm i sass
  2. If using TS, deprecate the tns.tsconfig.json file. Delete it, change it to gibberish, etc. I named it deprecated(tns.tsconfig.json).
  3. In your tsconfig file update moduleResolution, paths and outdir
{
  "compilerOptions": {
    ...all the same old options otherwise
    "moduleResolution": "node",
    "outDir": "app",
     "paths": {
         "~/*": [
              "src/*"
          ]
      }
  }
}
  1. Then add some scripts to package.json (not the one in /app)
"scripts": {
                "watchXml": "You'll have to make this one yourself",
        "watchSass": "sass --watch src/:app/ --no-source-map ",
        "watchTsc": "tsc --watch",
        "watch": "npm run watchTsc & npm run watchSass & npm run watchXml",
        "debugAndroid": "npm run watch & tns debug android --chrome"
  },
  1. Copy /app to /src

  2. Then spend a bunch of time deleting all the .ts and .scss files from app and all the .js .css files from src.

My setup is now a /src/ folder and an /app/ folder, if I run npm run watch files get updated automatically. I'm not using xml for my project, so you'll have to implement that bit yourself.

Hope this helps someone!

The reason it is /extremely/ uncommon to transpile in place is that it leave artifacts from previous builds throughout your code.

Nativescript makes no attempt to clean up these artifacts and if your ts code doesn't compile and you have one of these previous artifacts it will happily compile your program using a previous version of your source code leading to many headaches

I have no problem with frameworks having differing preferences than me. I have problems with bad architectural designs that result in many real hours lost for the developers using the framework.

I know this isn't as good as having it built in, but it was pretty easy to circumnavigate the built in system and set up custom transpiling.

There's basically two commands you need to know:

  • sass --watch src/:app/ --no-source-map for sass and
  • tsc --watch with an src->app tsconfig setup

I mean, given how easy it was, I'm really not sure why it can't be built in, but don't let this block you!

@SephReed So this setup basically treats app as the 'out' folder and the nativescript plugin picks everything else up?

Yeah. It's like having a nativescript js project.

Moving from Ionic I was in love with NativeScript...until I saw this.

Absolutely mind-boggling how this isn't implemented yet. One of the few things Ionic got right.

The problem @larssn mentioned is serious and I can see it happening all the time. This isn't a design choice at all, this is a breaking point, I would rather abandon the Angular project and stick with the pure XML/JS just so I don't stress myself, or just not use NS at all, because Typescript is really valuable.

@gbbarroso what do you think of Ionic? I am thinking of using it next

In the next nativescript versions webpack will be enabled by default, so there will be no more traditional transpiling to the src folder. This isn't an issue for me personally, but if you care about it, the solution is probably around the corner.

I just add js to .gitignore and hide in vs code when there's a TS with the same name. When I need to use js I just manually git add.

@edusperoni that's good. Well I've manually deleted the .js files and am using the --hmr. This seems to work for me (althought it is still in beta from what I've seen in docs)

Since 5.2 or 5.3 it was officially out of beta, so it's probably fine :)

Waiting with baited breath. Ran into another issue with this today. A ts file was removed and the project still compiled fine with references to it because of old js files... that is until the build bot ran the codebase using a clean checkout 馃挜

@DanLatimer you can use it today with --bundle or --hmr

Thanks @edusperoni 馃憤

Just started a new NS project. I could not for the life of me remember why I really should not use a typescript project. Had to come find this thread to remember.

@SephReed (& others) - I believe this is no longer a real issue as early in NS 5 they introduced HMR.
And with 5.4 (just tested, but named it demo60) already it is smart enough not to put any JS files in the app directory.. I just did a

  • tns create demo60 --ts
  • cd demo60
  • tns run android

And this is what my directory looks like after...
image
Notice anything missing? Yep, no JS files are transpiled in your app directory any more...

That does seem really nice, but the webpack flow still doesn't really work in my project, so I'm going to be sticking with using ts and running tsc myself for now.

@SephReed - Are you aware that NS 6 (the next release of NS) only supports the webpack flow. All the legacy build code is being being removed...

Yeah, I know. I've managed to do a lot of try catch stuff for dealing with issues related to holding references to views which are no longer valid (created by earlier roots). I'm going to DM you with some details on my situation.

Resolved via nsconfig.json and the path options described here + we can also have a dist folder set in the tsconfig.json (as done here)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

valentinstoychev picture valentinstoychev  路  3Comments

guillaume-roy picture guillaume-roy  路  3Comments

dhanalakshmitawwa picture dhanalakshmitawwa  路  3Comments

tsonevn picture tsonevn  路  3Comments

OscarLopezArnaiz picture OscarLopezArnaiz  路  3Comments