每个Angular项目都会生成大量文件

647

我想为Angular创建一个简单的“Hello World”应用程序。

当我按照官方快速入门中的说明进行操作时,安装程序在我的项目中创建了32,000个文件。

我认为这是某种错误或者我错过了什么,所以我决定使用angular-cli,但在设置完项目后,我数了一下有41,000个文件。

我到底做错了什么?我是不是漏掉了非常明显的东西?


108
这在使用NPM驱动的项目中是很正常的。 - Everettss
116
@hendrix 因为我的部署(Google App Engine)只允许10K个文件。 - Moshe Shaham
50
对于对此问题及其回答的投票数量感到好奇的任何人,该问题已经登上了 Hacker News 的首页。https://news.ycombinator.com/item?id=12209028 - ceejayoz
50
@hendrix - 我敢打赌你也会将 .DS_Store 文件提交到 git 上。 - Martin Konecny
65
我认为“如果您的hello world应用程序可以工作,一切都很好”的哲学不是一个好的跟随方式,特别是对于正在学习的人。原帖提出质疑为什么会创建这么多文件,这是完全正确的。示例本身只引用了5个文件。而且,任何拥有超过输出字母数的文件数量的应用程序都应该受到质疑。 - Shawn
显示剩余21条评论
14个回答

390

你的配置没有问题。

Angular (自2.0版本起) 使用npm模块和依赖项进行开发。这就是为什么你会看到这么多文件的唯一原因。

Angular的基本设置包含了编译器、类型依赖项,这些只是用于开发的基本必需品

一旦开发完成,你只需要将这个应用程序打包即可。

在打包你的应用程序之后,你只会得到一个bundle.js文件,然后你就可以将其部署在你的服务器上。

'transpiler'仅仅是一个编译器,感谢@omninonsense的补充。


7
通常还会携带测试数据、测试和构建工具以及依赖项及其依赖项等。 - Benjamin Gruenbaum
65
“Transpiler”就是编译器。 - omninonsense
34
但是编译成另一种语言,而不是编译成字节码或机器码。 - Hunter McMillen
34
字节码和/或机器码是另一种语言。术语“转译器”与“编译器”没有任何其他区别。 - Brandon Buck
77
关于所有相关方面,我不确定语义学争论是否与主题帖的问题真正相关。^^ - Dan
显示剩余15条评论

156
                                Typical Angular2 Project

NPM包                     文件(开发)                 真实世界文件(部署)

@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

[查看此链接以获取打包过程 ⇗]


26
我猜 -3 是因为没有做这道题目而被扣分,但是现在我已经做了 :) - Ankit Singh
1
你所说的“真实世界文件”是什么意思? - yeahman
1
@yeahman "真实世界文件"是指您的项目在部署或生产时的文件数量。 - Maarti
同时,文件数量只有3个,但它们可能非常大(适用于Web)。 - pdem

53

你的开发配置没有问题。

你的生产配置有问题。

当你开发一个 "Angular 2 项目" 或 "任何基于 JS 的项目" 时,你可以使用所有文件,你可以尝试所有文件,你可以导入所有文件。但如果你想要提供此项目,你需要合并所有结构化文件并且摆脱无用的文件。

有很多选项可以将这些文件合并在一起:


2
你不应该(需要引用)在服务器上拼接文件。最多,我会使用转译器。 - Dan
1
@DanPantry 转译器是源码到源码的编译器。我认为它们只能将“X”更改为“JS”。文件计数相同。 - hurricane
1
是的,但我不确定你的观点。我的观点是,您可能不应尝试使服务器代码最小化(通过连接文件从而减少文件大小)。 最多,如果您正在使用像async/await这样的新功能,则应在代码上使用Babel。 - Dan
2
@DanPantry 我同意你的观点。但是在评论中,提问者说“因为我的部署(谷歌应用引擎)只允许10K个文件”。在这种情况下,我们需要减少文件数量。 - hurricane
4
我同意你的观点,但 OP 好像在这里存在一个 XY 问题。 - Dan

30

正如几位已经提到的人所说:您node_modules目录中的所有文件(包的NPM位置)都是您项目依赖项(所谓的直接依赖项)的一部分。除此之外,您的依赖关系也可以有自己的依赖关系,等等(所谓的传递性依赖关系)。几万个文件并不算特别。

因为您只允许上传10,000个文件(参见评论),我建议使用打包引擎。该引擎将捆绑所有JavaScript、CSS、HTML等文件,并创建单个包(或更多,如果您指定)。您的index.html将加载此包,就这样。

我喜欢webpack,所以我的webpack解决方案将创建一个应用程序包和一个供应商包(有关完整的工作应用程序,请参见此处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));
}

优点:

  • 完整的构建流程(TS检查、编译、缩小等)
  • 仅需几个HTTP请求的3个文件用于部署

缺点:

  • 较长的构建时间
  • 对于Http 2项目不是最佳解决方案(请参见免责声明)

免责声明:这是Http 1.*的一个好的解决方案,因为它最小化了每个Http请求的开销。您只需要一个请求来获取您的index.html和每个捆绑包 - 而不是100-200个文件。目前,这是正确的方法。

另一方面,Http 2试图将Http开销最小化,因此它基于流协议。该流能够在两个方向(客户端<-->服务器)进行通信,并因此可以进行更智能的资源加载(您只加载所需的文件)。流消除了许多Http开销(减少Http往返)。

但这就像IPv6一样:人们真正使用Http 2还需要几年时间。


1
不必要,因为OP提到使用angular-cli,它已经带有一个打包工具(与建议的webpack相同)。 - mattarau
2
@mdentinho 是的,在更现代的版本中是这样的。但在2016年,SystemJS和CLI是最好的选择(现在我们很高兴有了webpack)。 - swaechter

23

您需要确保只部署由Angular CLI生成的项目的dist(缩写为distributable)文件夹。这允许该工具获取您的源代码及其依赖项,并仅提供运行应用程序所需的内容。

话虽如此,Angular CLI在通过`ng build --prod`进行生产构建方面存在/曾经存在问题。

昨天(2016年8月2日)发布了一个版本,将构建机制从broccoli + systemjs 切换到webpack,成功处理生产构建。

基于这些步骤:

ng new test-project
ng build --prod

在这里列出的14个文件中,我看到一个dist文件夹大小为1.1 MB

./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

注意 当前安装 Angular CLI 的 webpack 版本,你需要运行... npm install angular-cli@webpack -g


17
最近使用angular cli创建了一个新项目,node_modules文件夹大小为270 mb,所以这是正常的,但我相信大多数新的angular开发人员会对此产生疑问,这是合理的。对于一个简单的新项目,缩减依赖项可能会更有意义;) 不知道所有软件包依赖的内容可能会让一些新手感到不安,尤其是第一次尝试cli的新手。另外,大多数基本教程都没有讨论如何设置部署以获取仅需要的导出文件。我甚至不认为官方网站上提供的教程讨论了如何部署简单的项目。

Looks like the node_modules folder is the culprit


14

12
似乎没有人提到这里描述的 Ahead-of-Time Compilation:https://angular.io/docs/ts/latest/cookbook/aot-compiler.html
我的经验是,Angular中的 AoT 创建了最小的构建体积,并且几乎没有加载时间。而最重要的是,正如在这个问题中所提到的——您只需要将几个文件发送到生产环境。
这似乎是因为 Angular 编译器不会随着生产构建一起发布,因为模板是“提前编译”的。看到 HTML 模板标记被转换为 JavaScript 指令非常酷,这很难逆向工程成原始的 HTML。
我制作了一个简单的视频,演示了开发和 AoT 版本的 Angular 应用程序的下载大小、文件数量等——您可以在这里观看:https://youtu.be/ZoZDCgQwnmQ
您可以在此处找到演示的源代码:https://github.com/fintechneo/angular2-templates
就像其他人在这里说的那样,在开发环境中有许多文件并没有问题。这是 Angular 和许多其他现代框架所带来的所有依赖项的情况。但不同之处在于,当发送到生产环境时,您应该能够将它打包成几个文件。此外,您不希望在 git 存储库中拥有所有这些依赖文件。

8

实际上,这并不是Angular特有的问题,几乎任何使用NodeJs / npm生态系统进行工具开发的项目都会遇到这种情况。

这些项目位于您的node_modules文件夹中,是直接依赖项需要运行的传递依赖项。

在Node生态系统中,模块通常很小,这意味着我们倾向于以模块的形式导入大部分所需内容,包括诸如著名的left-pad函数之类的小东西。如果不是为了练习,我们为什么要自己编写它们呢?

因此,拥有大量文件实际上是一件好事,这意味着一切都非常模块化,模块作者经常重复使用其他模块。这种易于模块化可能是Node生态系统快速增长的主要原因之一。

原则上,这不应该引起任何问题,但似乎您遇到了Google App Engine文件计数限制。在这种情况下,我建议不要将node_modules上传到App Engine。

相反,本地构建应用程序,并仅将捆绑文件上传到Google App Engine,而不要在App Engine本身执行构建。


8

如果您正在使用angular cli的新版本,请使用ng build --prod

这将创建一个dist文件夹,其中包含较少的文件,并且项目的速度会增加。

此外,为了在本地进行最佳性能测试,您可以使用ng serve --prod


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接