646

I wanted to start a simple hello world app for Angular.

When I followed the instructions in the official quickstart the installation created 32,000 files in my project.

I figured this is some mistake or I missed something, so I decided to use angular-cli, but after setting up the project I counted 41,000 files.

Where did I go wrong? Am I missing something really really obvious?

skink
  • 5,133
  • 6
  • 37
  • 58
Moshe Shaham
  • 15,448
  • 22
  • 74
  • 114
  • 108
    It's normal for projects powered by NPM. – Everettss Aug 02 '16 at 11:06
  • 14
    Why would you even bother counting number of files. If your hello world app is working, everything is fine – hendrix Aug 02 '16 at 11:07
  • 116
    @hendrix because my deployment (google app engine) allows only 10K files – Moshe Shaham Aug 02 '16 at 11:09
  • 8
    Yes, and I think it's horrible too. But a lot of those files are necessary for debugging only! For instance: 'lite-server', a lightweight (irony here, i guess) web-server. – Sander_P Aug 02 '16 at 11:15
  • 5
    When bundled up it only takes 1 file – Harry Ninh Aug 02 '16 at 11:15
  • 2
    I had the same problem once and used the "skip_files" expression in the app.yaml. With that you can tell GAE which files or directories not to upload – Zeus Aug 02 '16 at 11:49
  • 50
    For anyone curious about the number of votes on this question and its answers, this made the HN front page. https://news.ycombinator.com/item?id=12209028 – ceejayoz Aug 02 '16 at 11:52
  • 7
    @MosheShaham the huge number of files you're seeing are npm modules, which go in the node_modules folder. This folder is not meant to be deployed or checked in and is meant to be dynamically created during build/deployment by using npm install. You should only be deploying a few small files and your deployment should then restore the npm packages on the server. – Amberite Aug 02 '16 at 12:35
  • sort of tangential but relevant http://stackoverflow.com/questions/25124844/should-i-npmignore-my-tests – Daniel Lizik Aug 02 '16 at 12:36
  • 3
    For comparison, I have a react/redux/router project that's about 6 months old. I counted `node_modules`: 101k files in 761 modules. Number of files deployed to the server: 1. – thom_nic Aug 02 '16 at 12:41
  • 50
    @hendrix - I bet you commit .DS_Store files to git as well. – Martin Konecny Aug 02 '16 at 13:28
  • Are you using Google App Engine for a client-side web app? If so, why? If you're using Angular 2 on the server side we may have a problem, but I doubt that you are. – Dan Aug 02 '16 at 13:49
  • @DanPantry, like most of the web there is probably client **and** server code. GAE serves static files, as configured by app.yaml – Paul Draper Aug 02 '16 at 14:40
  • 65
    I think "If your hello world app is working, everything is fine" isn't a good philosophy to follow, especially for someone who is learning. The OP is exactly right to question why so many files were created. The example itself references only 5 files. And honestly, any application that has more files than there are letters in its output should be questioned. – Shawn Aug 02 '16 at 19:45
  • You may all argue, but I have just included cdn for angular in my project and it makes 0 new files ... – Buksy Aug 03 '16 at 05:54
  • 1
    @MartinKonecny ever heard about bundling your sources to few files before deploying? – hendrix Aug 03 '16 at 07:18
  • @Buksy do you have a link how can I set up angular 2 from cdn? – Moshe Shaham Aug 03 '16 at 07:49
  • @MosheShaham Actually I used angular 1 (sorry), but seems like this works http://embed.plnkr.co/9Xbw3M/preview – Buksy Aug 03 '16 at 08:35
  • 1
    Its just for create and run build use ng build --prod it will dicrease amount of file in dist directory and it will increase speed of angular project, just give dist folder path then to get high speed of project – Jalay Oza Jun 06 '17 at 13:45
  • 2
    I'm the only one here who thinks this is just I N S A N E. Something went horribly wrong. I understand that I can create a bundle and deploy only one file. Fine. But downloading thousands of files from GitHub... Who designed that? – Dávid Molnár Jun 09 '17 at 08:10
  • it's funny the way you posted the question regarding the file limit, but if you're using angular-cli then you can build the application using , `ng build` which will convert all the type script files and combine them in less file. – Touqeer Shafi Sep 29 '17 at 13:40
  • 1
    using **yarn** can alse helpul. see the difference between yarn and npm here : [https://www.sitepoint.com/yarn-vs-npm/](https://www.sitepoint.com/yarn-vs-npm/) – Noopur Dabhi Dec 21 '17 at 05:17
  • I was also shocked with the amount of files .... was expecting simplicity .... – yeahman Jun 03 '18 at 16:41
  • It almost 500MB in size. the worst part is it get downloaded again for every project folder. – AzizSM Aug 21 '18 at 09:19
  • [Welcome to NPM](https://i.redd.it/tfugj4n3l6ez.png) – Mike Doe Jan 11 '19 at 07:07
  • Is it just me or is there no way they could have designed it so that you only get the files you need??? – CYoung Aug 30 '21 at 06:39

14 Answers14

388

There is nothing wrong with your configuration.

Angular (since version 2.0) uses npm modules and dependencies for development. That's the sole reason you are seeing such a huge number of files.

A basic setup of Angular contains transpiler, typings dependencies which are essential for development purposes only.

Once you are done with development, all you will need to do is to bundle this application.

After bundling your application, there will be only one bundle.js file which you can then deploy on your server.

'transpiler' is just a compiler, thanks @omninonsense for adding that.

Lazar Ljubenović
  • 18,976
  • 10
  • 56
  • 91
Bhushan Gadekar
  • 13,485
  • 21
  • 82
  • 131
  • 7
    It also typically brings the test data and tests and build tools for the dependencies and their dependencies and so on. – Benjamin Gruenbaum Aug 02 '16 at 12:19
  • 65
    A "transpiler" is just a compiler. – omninonsense Aug 02 '16 at 13:01
  • 34
    but compiles to another language instead of to byte code or machine code – Hunter McMillen Aug 02 '16 at 13:16
  • 5
    A compiler is a program that get code in A, produce temporal T, and transform T in final B. B is usually binary code for a real CPU, but can be another programming language. A compiler don't need to generate byte code. – Tei Aug 02 '16 at 13:21
  • The 5 Min Quick start includes a lot more modules than actually needed to function. You don't need ''router', 'router-depreciated', forms, or 'angular2-in-memory-web-api'. – Timigen Aug 02 '16 at 13:38
  • 34
    @HunterMcMillen Byte code and/or Machine code is another language. The term "transpiler" has no additional meaning than "compiler." – Brandon Buck Aug 02 '16 at 13:50
  • 77
    With respect to all involved I'm not sure the semantics argument is really relevant to OP's question ^^ – Dan Aug 02 '16 at 13:57
  • 2
    If I'm reading the answer right, does this mean that Angular 2 has 40k (!!) dependencies (including transitive one) on external modules? Or could you expand the link between *Angular 2 uses npm modules and dependencies for development* and such an unrealistic number of files? – Tunaki Aug 02 '16 at 20:35
  • 1
    @Tunaki no, not really. Each project has quite a few files. For instance, `lodash` has 1021 files on the release I just downloaded. (Granted, this is probably more than the average, but the point remains). Not to mention the NPM ecosystem is meant to be very modular so every dependency has quite a few other dependencies. – rmobis Aug 02 '16 at 21:54
  • 3
    Welcome to J̶a̶v̶a̶S̶c̶r̶i̶p̶t̶ dependency hell. It'll kick in once you start updating components :) – Navin Aug 02 '16 at 21:56
  • The large number of files stems from npm. Angular 2's BUILD-time dependencies are based on npm, which uses an ill-advised recursive filesystem-based dependency system. These aren't 40k different dependencies, they're maybe 1-5k dependencies and a bunch of redundant copies of the same files over and over again. That being said, a front-end project shouldn't be deploying anything from node_modules, so something is definitely wrong with the deployment configuration if those files are being included. – Jeremy Bell Aug 03 '16 at 01:15
  • 4
    @Navin That's not what dependency hell means; check up the definition. npm is one of the few package managers that **does not** suffer from dependency hell by design. – mgol Aug 03 '16 at 09:52
  • @JeremyBell Care to elaborate on the 'recursive' part? – rmobis Aug 03 '16 at 13:24
  • 3
    @DanPantry If we didn't have off-topic semantic arguments in the comments section, I'm not sure I would remember I'm on SO! – Dave Aug 03 '16 at 14:17
  • @rmobis as in transitive dependencies are contained in their parent dependency's folder in node_modules, and so on down recursively. That is why you might have several hundred copies of some files from popular npm modules - because lots of other modules have dependencies on them and so on. This is in contrast to a "flat" dependency system where all dependencies are at the same root level without duplicates. – Jeremy Bell Aug 03 '16 at 17:28
  • @JeremyBell then it's worth noting that this is no longer the case in npm v3, which has been the default on Node for quite a while already. – rmobis Aug 03 '16 at 17:31
  • @rmobis npm v3 tries to flatten the dependency tree but can only do so when "duplicates" are the same version. Otherwise it falls back to v2 behavior which is nested. It's a vast improvement to be sure, but large file counts are still common. – Jeremy Bell Aug 03 '16 at 22:08
  • @omninonsense, technically, a transpiler is not an exact equivalent of a compiler. A transpiler takes the source code of a program written in one language and converts it to source code in another programming language. In this case, your TypeScript code is converted to Javascript and then your Javascript is compiled. – strizzwald Dec 04 '17 at 11:00
  • 2
    @strizzwald a compiler is a program that translates a source language to a target language, as Tei explained. The fact that the target language is also human readable does doesn't mean the compiler is any less of a compiler. However, you can use _transpiler_ as a synonym for "source-to-source" compilers; I didn't mean to imply there is something wrong with the word when submitting the comment. :) – omninonsense Dec 17 '17 at 01:46
  • transpiler = TRANSlate + comPILER – Sami Apr 23 '18 at 14:44
156
                                Typical Angular2 Project

NPM Package                       Files (Development)                   Real World Files (Deployment)

@angular                       3,236                             1
rxJS                           1,349                             1*
core-js                        1,341                             2
typings                        1,488                             0
gulp                           1,218                             0
gulp-typescript                1,243                             0
lite-server                    5,654                             0
systemjs-builder               6,470                             0
__________________________________________________________________
Total                         21,999                             3  

*: bundled with @angular

[ see this for bundling process ⇗ ]

Community
  • 1
  • 1
Ankit Singh
  • 24,525
  • 11
  • 66
  • 89
53

There is nothing wrong with your development configuration.

Something wrong with your production configuration.

When you develop a "Angular 2 Project" or "Any Project Which is based on JS" you can use all files, you can try all files, you can import all files. But if you want to serve this project you need to COMBINE all structured files and get rid of useless files.

There are a lot of options for combine these files together:

hurricane
  • 6,521
  • 2
  • 34
  • 44
  • 2
    You shouldn't (citation needed) be concatenating files together on the server. At most, I would use a transpiler. – Dan Aug 02 '16 at 13:50
  • 1
    @DanPantry Transpilers are source-to-source compilers. I think they can only change "X" to "JS". File counts are same. – hurricane Aug 02 '16 at 13:54
  • 1
    ..Yes, but I'm not sure of your point. My point is that you probably shouldn't try to minify server code (by concatenating files and thus reducing file size). At most, you should use Babel on your code if you're using bleeding features like async/await. – Dan Aug 02 '16 at 13:56
  • 2
    @DanPantry I am agree with you. But on the comments questioner says "because my deployment (google app engine) allows only 10K files". In these conditions we need to minify file counts. – hurricane Aug 02 '16 at 13:59
  • 4
    I'd agree with you but OP seems to have an XY issue here – Dan Aug 02 '16 at 14:00
30

As several people already mentioned: All files in your node_modules directory (NPM location for packages) are part of your project dependencies (So-called direct dependencies). As an addition to that, your dependencies can also have their own dependencies and so on, etc. (So-called transitive dependencies). Several ten thousand files are nothing special.

Because you are only allowed to upload 10'000 files (See comments), I would go with a bundler engine. This engine will bundle all your JavaScript, CSS, HTML, etc. and create a single bundle (or more if you specify them). Your index.html will load this bundle and that's it.

I am a fan of webpack, so my webpack solution will create an application bundle and a vendor bundle (For the full working application see here https://github.com/swaechter/project-collection/tree/master/web-angular2-example):

index.html

<!DOCTYPE html>
<html>
<head>
    <base href="/">
    <title>Webcms</title>
</head>
<body>
<webcms-application>Applikation wird geladen, bitte warten...</webcms-application>
<script type="text/javascript" src="vendor.bundle.js"></script>
<script type="text/javascript" src="main.bundle.js"></script>
</body>
</html>

webpack.config.js

var webpack = require("webpack");
var path = require('path');

var ProvidePlugin = require('webpack/lib/ProvidePlugin');
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
var UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');

/*
 * Configuration
 */
module.exports = {
    devtool: 'source-map',
    debug: true,

    entry: {
        'main': './app/main.ts'
    },

    // Bundle configuration
    output: {
        path: root('dist'),
        filename: '[name].bundle.js',
        sourceMapFilename: '[name].map',
        chunkFilename: '[id].chunk.js'
    },

    // Include configuration
    resolve: {
        extensions: ['', '.ts', '.js', '.css', '.html']
    },

    // Module configuration
    module: {
        preLoaders: [
            // Lint all TypeScript files
            {test: /\.ts$/, loader: 'tslint-loader'}
        ],
        loaders: [
            // Include all TypeScript files
            {test: /\.ts$/, loader: 'ts-loader'},

            // Include all HTML files
            {test: /\.html$/, loader: 'raw-loader'},

            // Include all CSS files
            {test: /\.css$/, loader: 'raw-loader'},
        ]
    },

    // Plugin configuration
    plugins: [
        // Bundle all third party libraries
        new CommonsChunkPlugin({name: 'vendor', filename: 'vendor.bundle.js', minChunks: Infinity}),

        // Uglify all bundles
        new UglifyJsPlugin({compress: {warnings: false}}),
    ],

    // Linter configuration
    tslint: {
        emitErrors: false,
        failOnHint: false
    }
};

// Helper functions
function root(args) {
    args = Array.prototype.slice.call(arguments, 0);
    return path.join.apply(path, [__dirname].concat(args));
}

Advantages:

  • Full build line (TS linting, compiling, minification, etc.)
  • 3 files for deployment --> Only a few Http requests

Disadvantages:

  • Higher build time
  • Not the best solution for Http 2 projects (See disclaimer)

Disclaimer: This is a good solution for Http 1.*, because it minimizes the overhead for each Http request. You only have a request for your index.html and each bundle - but not for 100 - 200 files. At the moment, this is the way to go.

Http 2, on the other hand, tries to minimize the Http overhead, so it's based on a stream protocol. This stream is able to communicate in both direction (Client <--> Server) and as a reason of that, a more intelligent resource loading is possible (You only load the required files). The stream eliminates much of the Http overhead (Less Http round trips).

But it's the same as with IPv6: It will take a few years until people will really use Http 2

efirvida
  • 4,592
  • 3
  • 42
  • 68
swaechter
  • 1,357
  • 3
  • 22
  • 46
  • 1
    Not necessary though, since the OP mentioned using `angular-cli` which already comes with a bundler (the same suggested webpack). – mattarau Oct 10 '17 at 08:03
  • 2
    @mdentinho Yes, in more modern releases. But in 2016 SystemJS and CLI was the way to go (Gladly we have webpack now) – swaechter Oct 11 '17 at 11:58
23

You need to ensure that you're just deploying the dist (short for distributable) folder from your project generated by the Angular CLI. This allows the tool to take your source code and it's dependencies and only give you what you need in order to run your application.

That being said there is/was an issue with the Angular CLI in regards to production builds via `ng build --prod

Yesterday (August 2, 2016) a release was done which switched the build mechanism from broccoli + systemjs to webpack which successfully handles production builds.

Based upon these steps:

ng new test-project
ng build --prod

I am seeing a dist folder size of 1.1 MB across the 14 files listed here:

./app/index.js
./app/size-check.component.css
./app/size-check.component.html
./favicon.ico
./index.html
./main.js
./system-config.js
./tsconfig.json
./vendor/es6-shim/es6-shim.js
./vendor/reflect-metadata/Reflect.js
./vendor/systemjs/dist/system.src.js
./vendor/zone.js/dist/zone.js

Note Currently to install the webpack version of the angular cli, you must run... npm install angular-cli@webpack -g

Brocco
  • 62,737
  • 12
  • 70
  • 76
17

Creating a new project with angular cli recently and the node_modules folder was 270 mb, so yes this is normal but I'm sure most new devs to the angular world question this and is valid. For a simple new project it would make sense to pare the dependencies down maybe a bit;) Not knowing what all the packages depend on can be a bit unnerving especially to new devs trying the cli out for the first time. Add to the fact most basic tutorials don't discuss the deployment settings to get the exported files only needed. I don't believe even the tutorial offered on the angular official website talks about how to deploy the simple project.

Looks like the node_modules folder is the culprit

maguy
  • 1,599
  • 1
  • 15
  • 26
14

Angular itself has lots of dependencies, and the beta version of CLI downloads four times more files.

This is how to create a simple project will less files ("only" 10K files) https://yakovfain.com/2016/05/06/starting-an-angular-2-rc-1-project/

Lazar Ljubenović
  • 18,976
  • 10
  • 56
  • 91
Yakov Fain
  • 11,972
  • 5
  • 33
  • 38
12

Seems like nobody have mentioned Ahead-of-Time Compilation as described here: https://angular.io/docs/ts/latest/cookbook/aot-compiler.html

My experience with Angular so far is that AoT creates the smallest builds with almost no loading time. And most important as the question here is about - you only need to ship a few files to production.

This seems to be because the Angular compiler will not be shipped with the production builds as the templates are compiled "Ahead of Time". It's also very cool to see your HTML template markup transformed to javascript instructions that would be very hard to reverse engineer into the original HTML.

I've made a simple video where I demonstrate download size, number of files etc. for an Angular app in dev vs AoT build - which you can see here:

https://youtu.be/ZoZDCgQwnmQ

You'll find the source code for the demo here:

https://github.com/fintechneo/angular2-templates

And - as all the others said here - there's nothing wrong when there are many files in your development environment. That's how it is with all the dependencies that comes with Angular, and many other modern frameworks. But the difference here is that when shipping to production you should be able to pack it into a few files. Also you don't want all of these dependency files in your git repository.

Lazar Ljubenović
  • 18,976
  • 10
  • 56
  • 91
Peter Salomonsen
  • 5,525
  • 2
  • 24
  • 38
8

This is actually not Angular specific, it happens with almost any project that uses the NodeJs / npm ecosystem for its tooling.

Those project are inside your node_modules folders, and are the transititve dependencies that your direct dependencies need to run.

In the node ecosystem modules are usually small, meaning that instead of developing things ourselves we tend to import most of what we need under the form of a module. This can include such small things like the famous left-pad function, why write it ourselves if not as an exercise ?

So having a lot of files its actually a good thing, it means everything is very modular and module authors frequently reused other modules. This ease of modularity is probably one of the main reasons why the node ecosystem grew so fast.

In principle this should not cause any issue, but it seems you run into a google app engine file count limit. In that I case I suggest to not upload node_modules to app engine.

instead build the application locally and upload to google app engine only the bundled filesn but don't to the build in app engine itself.

Lazar Ljubenović
  • 18,976
  • 10
  • 56
  • 91
Angular University
  • 42,341
  • 15
  • 74
  • 81
8

If you are using angular cli's newer version use ng build --prod

It will create dist folder which have less files and speed of project will increased.

Also for testing in local with best performance of angular cli you can use ng serve --prod

Pac0
  • 21,465
  • 8
  • 65
  • 74
Jalay Oza
  • 772
  • 7
  • 11
6

if you use Angular CLI you can always use --minimal flag when you create a project

ng new name --minimal

I've just run it with the flag and it creates 24 600 files and ng build --prod produces 212 KB dist folder

So if you don't need water fountains in your project or just want to quickly test something out this I think is pretty useful

SebOlens
  • 519
  • 3
  • 15
3

If your file system supports symbolic links, then you can at least relegate all of these files to a hidden folder -- so that a smart tool like tree won't display them by default.

mv node_modules .blergyblerp && ln -s .blergyblerp node_modules

Using a hidden folder for this may also encourage the understanding that these are build-related intermediate files that don't need to be saved to revision control -- or used directly in your deployment.

Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
  • My breadcrumb has gone stale, but here's what it refers to: https://web.archive.org/web/20150216184318/https://docs.npmjs.com/misc/faq#node_modules-is-the-name-of-my-deitys-arch-rival-and-a-forbidden-word-in-my-religion-can-i-configure-npm-to-use-a-different-folder – Brent Bradburn Apr 11 '20 at 15:16
2

There is nothing wrong. These are all the node dependencies that you have mentioned in the package.json.

Just be careful if you have download some of the git hub project, it might have lot of other dependencies that are not actually require for angular 2 first hello world app :)

  • make sure you have angular dependencies -rxjs -gulp -typescript -tslint -docker
0

There is nothing wrong with your development configuration.

if you use Angular CLI you can always use --minimal flag when you create a project

ng new name --minimal
Naeem Bashir
  • 1,937
  • 20
  • 17