我已经创建了一个Bootstrap component library for angular沿着一个演示应用程序。然而,在构建应用程序时,主包的大小非常大。更值得注意的是,向库中添加组件,并向加载这些模块的应用程序中添加页面(延迟加载),最近将我的主包大小从650 kB增加到840 kB。
我已经检查了其他问题,如this one,但它没有给予我一个答案。
编辑5
I recreated the project in an angular workspace,用dist/lib-name
参于tsconfig.json
.即使在这里我也可以得出一个非常简单的结论:
- 由于没有引用
AppModule
中的库组件,主包如预期的那样简单明了(328 kB):
- 从我在应用程序中使用一个组件的那一刻起,库中的大量javascript块就被捆绑在主包(928 kB)中。
编辑4
我在一个有Angular 的工作空间中重新创建了我的项目,并得到了预期的结果:
总主束尺寸(js):509 kB。主束仅包含navbar
块
对于具有单个库的NX工作空间:
总主束尺寸(js):695 kB。注意所有不必要的块。我很确定在我的项目中没有索引导入(import {} from '../navbar'
而不是import {} from '../navbar/navbar.module'
)。
编辑3
我似乎发现了一个问题。在逐步重新创建我的工作区时,我看到了以下内容:
当组件x1c4d 1x上没有动画时
这是我的主包
这是通用软件包(延迟加载)*
包含BsListGroup和BsCard
main.xxx.js包中的lib/components块如下所示:
仅包含导航栏
现在让我们在BsAlertComponent
上放一个动画:
指令集
这是我的主包
我的公共包(包含BsListGroup和BsCard)看起来与*
完全相同
然而,main包中的components块看起来像
,并且明显包含整个BsAlertComponent
(我不需要)和项目中其他组件的大量垃圾...
PS.请修复SO文件上传器...
编辑2
我created a minimal angular workspace(即使没有库),我可以看到所有与我在旧问题中描述的相同的行为(见下文)。
该应用包含3个组件,每个组件都有各自的模块,2*2个页面。BsNavbarModule
加载在AppModule
上,因为我在根目录中使用BsNavbarComponent
。
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BsNavbarModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
每个页面加载各自的组件。
转盘1页:
@NgModule({
declarations: [
CarouselOneComponent
],
imports: [
CommonModule,
BsCarouselModule,
CarouselOneRoutingModule
]
})
export class CarouselOneModule { }
画布外1页:
@NgModule({
declarations: [
OffcanvasOneComponent
],
imports: [
CommonModule,
BsOffcanvasModule,
OffcanvasOneRoutingModule
]
})
export class OffcanvasOneModule { }
你希望在这里看到什么?
- 主束
- 应用模块-〉应用组件
- 导航栏模块-〉BsNavbar组件
- 转盘一丛
- 转盘一个模块
- 转盘-双管束
- 转盘双模块
- bs-carousel捆绑包-〉bsCarousel模块
- 帆布单束
- 非平面单模块
- 帆布双束
- 非画布双模块
- bs-offcanvas包-〉bsoffcanvas模块
我们得到了什么?
- 主包-〉导航栏模块
- 与转盘捆绑销售1第页
- 与转盘捆绑销售2第页
- 与Offcanvas捆绑销售1第页
- 与Offcanvas 2捆绑销售第
BsCarouselModule
与BsOffcanvasModule
得一个大通用捆绑包(这不是我所期望得)
- 主要,多边形填充,运行时,样式
为什么所有这些组件都捆绑在一起成为一个单一的捆绑包?当用户访问一个页面时,没有必要下载所有这些组件的js...在这个例子中,它只有大约2个组件,但在我的实际应用程序中,有像30个组件,其中大多数是捆绑在一起没有任何原因。
旧问题
换句话说,页面显然是惰性加载的:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
...
{ path: 'range', loadChildren: () => import('./range/range.module').then(m => m.RangeModule) },
{ path: 'select', loadChildren: () => import('./select/select.module').then(m => m.SelectModule) }
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class BasicRoutingModule { }
我在主包上运行了webpack包分析器,注意到我的库中的所有模块都捆绑在我的主包中,只是因为我在AppModule
中加载了BsNavbarModule
。
npm run build:wba
npm run analyze:wba
红色的Stuff都是主包的一部分,尽管我从来没有在AppModule
中使用import
组件的模块,只在延迟加载的模块中使用。BsNavbarComponent
在AppComponent
上使用,所以另一方面,BsNavbarModule
需要在主包中。我也有这样的印象,因为所有这些,@angular/core
和@angular/common
软件包比实际需要的要大得多。
另一个问题是,我在一些延迟加载的页面中使用了ngx-highlighjs
,而这个库要求您在根级别指定HIGHLIGHT_OPTIONS
。因此,您还可以看到整个ngx-highlightjs库打包在主包中,即使我只在另一个延迟加载的页面上加载模块...
我的库的module
被指定为"esnext"
。
我尝试将"sideEffects": false
添加到package.json
,结果如下:
但还是不能解决我的问题...
如何解决这个问题?为什么AppModule
中没有加载的角模块捆绑在主包中?
编辑
我创建了一个空白的Angular 应用程序:
已安装我的库并添加了全局样式:
并创建了一个页面(ng g module demo --module app --route demo
),并在上面添加了BsNavbarComponent
:
这立即增加了我的主要捆绑大小与50 kB...
1条答案
按热度按时间dsekswqp1#
根据编辑2的答案,而不是旧问题。
为什么将所有这些组件捆绑到一个包中?(common.js块)
这种行为是一种默认的优化技术,您可以通过在angular.json中指定
commonChunk: false
来关闭它。但是,通常最好保持打开,因为通过将跨多个bundle使用的代码放在一个地方(common.js块),可以消除共享代码的重复。我已使用您的minimal angular workspace比较了以下
ng build --source-map
输出:公用块:true(预设值)
ng构建输出(common.js块、更快的后续延迟加载、更小的延迟块)
公用块:假的
ng构建输出(无common.js块、较慢的延迟加载、较大的延迟块)
那么,什么时候在UI中加载公共块呢?
这取决于你的导入。在我看来,如果你在你的主包中导入了一个模块,而这个模块最终出现在了公共块中(因为你也在懒惰模块中导入了这个模块),那么在初始渲染过程中,公共块就会被加载,这可能会影响性能。
基本上,为了防止在初始呈现中加载公共块,您希望尽可能避免在主块和惰性块中导入相同的模块。
这不是你提供的最小工作空间的问题,但我高度怀疑这是你的老问题的情况。
网络选项卡(最小工作空间,
commonChunk: true
)显示初始渲染时未加载公共块:commonChunk: false
在最终发送到客户端的js数量上也有一个小小的折衷。但可以通过实现预加载策略来缓解这种情况(无论如何,您都应该对延迟加载执行此操作,但这超出了本问题的范围)。