


What should I do if the project is too big? How to split Angular projects reasonably?
Jul 26, 2022 pm 07:18 PMAngularThe project is too large, how to split it reasonably? The following article will introduce to you how to reasonably split Angular projects. I hope it will be helpful to you!
One of the criticisms about Angular is that it is very large after being packaged. If you are not careful, main.js
will become ridiculously large. In fact, when you encounter similar problems Whether the problem is large volume, large data, or large traffic, there is only one idea: splitting. Coupled with the browser's caching mechanism, the project access speed can be optimized. [Recommended related tutorials: "angular tutorial"]
The relevant code for this article is at: https://github.com/Vibing/angular-webpack
Split ideas
The entire project includes: strong dependency library (Angular framework itself), UI component library and third-party library, and business code part;
User behavior dimension: all user access is based on routing, one route is one page;
It can be split from the above two points, based on the first You can package strongly dependent libraries and libraries that rarely change into a vendor_library
, which can contain @angular/common
, @angular/core
, @angular/forms
, @angular/router
and other similar packages, UI component libraries or libraries such as lodash
are not recommended to be packaged together, because we need to use TreeShaking, There is no need to package unused code, otherwise it will only increase the size.
Now that the strong dependency package is done, let’s package the business code based on point 2. We use route-based code spliting
for packaging. The idea is very simple. Whichever page the user visits, the js corresponding to the page is downloaded. There is no need to package the unvisited pages together. This will not only increase the size, but also increase the download time, and the user experience will also deteriorate. .
Custom webpack configuration
If we want to use DLL to import strongly dependent packages into a vendor, we must use the webpack function, which is already embedded in Angular CLI webpack, but these configurations are black boxes to us.
Angular allows us to customize webpack configuration, the steps are as follows
Installation
@angular-builders/custom-webpack
and@angular- devkit/build-angular
Create a new webpack.extra.config.ts for webpack configuration
In angular.json Make the following modifications
... "architect":?{ ??"build":?{ ????"builder":?"@angular-builders/custom-webpack:browser", ????"options":?{ ??????... ??????"customWebpackConfig":?{ ????????//?引用要拓展的?webpack?配置 ????????"path":?"./webpack.extra.config.ts", ????????//?是否替換重復插件 ????????"replaceDuplicatePlugins":?true ??????} ????} ??}, ??"serve":?{ ????"builder":?"@angular-builders/custom-webpack:dev-server", ????"options":?{ ??????"browserTarget":?"angular-webpack:build" ????} ??} ??...
Use DLL
After you can customize the webpack configuration, create a new webpack.dll.js file to write the DLL configuration:
const?path?=?require("path"); const?webpack?=?require("webpack"); module.exports?=?{ ??mode:?"production", ??entry:?{ ????vendor:?[ ??????"@angular/platform-browser", ??????"@angular/platform-browser-dynamic", ??????"@angular/common", ??????"@angular/core", ??????"@angular/forms", ??????"@angular/router" ????], ??}, ??output:?{ ????path:?path.resolve(__dirname,?"./dll"), ????filename:?"[name].dll.js", ????library:?"[name]_library", ??}, ??plugins:?[ ????new?webpack.DllPlugin({ ??????context:?path.resolve(__dirname,?"."), ??????path:?path.join(__dirname,?"./dll",?"[name]-manifest.json"), ??????name:?"[name]_library", ????}), ??], };
Then introduce the dll in webpack.extra.config.ts
import?*?as?path?from?'path'; import?*?as?webpack?from?'webpack'; export?default?{ ??plugins:?[ ????new?webpack.DllReferencePlugin({ ??????manifest:?require('./dll/vendor-manifest.json'), ??????context:?path.resolve(__dirname,?'.'), ????}) ??], }?as?webpack.Configuration;
Finally add a command to package the dll in package.json: "dll": "rm - rf dll && webpack --config webpack.dll.js"
, after executing npm run dll
, there will be a dll folder at the root of the project, which contains the packaged content:
After the packaging is completed, we need to use vendor.dll.js
in the project and configure it in angular.json
:
"architect":?{ ??... ??"build":?{ ????... ????"options":?{ ??????... ???????"scripts":?[ ?????????{ ????????????"input":?"./dll/vendor.dll.js", ????????????"inject":?true, ????????????"bundleName":?"vendor_library" ?????????} ???????] ????} ??} }
After packaging, you can see that vendor_library.js
has been introduced:
The purpose of DLL is to remove strong dependencies that will not be updated frequently. Packages are packaged and merged into a js file, which is generally used to package the Angular framework itself. When the user visits for the first time, the browser will download vendor_library.js
and cache it. Every subsequent visit will be taken directly from the cache. The browser will only download the js of the business code and will not download the framework. The relevant code greatly improves the application loading speed and improves the user experience.
ps: The hash behind vendor_library will only be changed if the code inside is changed during packaging, otherwise it will not change.
Routing-level CodeSpliting
The DLL has managed the code in the framework. Now let’s see how to implement on-demand loading of routing-level pages in Angular.
Let’s take a break here. How to do routing level code splitting in React or Vue? It's probably like this:
{ ??path:'/home', ??component:?()?=>?import('./home') }
The home here points to the corresponding component, but this method cannot be used in Angular. The code can only be split in units of modules:
{ ??path:'/home', ??loadChild:?()=>?import('./home.module').then(m?=>?m.HomeModule) }
Then Use routing in a specific module to access specific components:
import?{?HomeComponent?}?from?'./home.component' { ??path:'', ??component:?HomeComponent }
Although you cannot import()
the component directly in the router, Angular provides dynamic import of components Function:
@Component({ ??selector:?'app-home', ??template:?``, }) export?class?HomeContainerComponent?implements?OnInit?{ ??constructor( ??????private?vcref:?ViewContainerRef, ??????private?cfr:?ComponentFactoryResolver ??){} ?? ??ngOnInit(){ ????this.loadGreetComponent() ??} ??async?loadGreetComponent(){ ??????this.vcref.clear(); ??????//?使用?import()?懶加載組件 ??????const?{?HomeComponent?}?=?await?import('./home.component'); ??????let?createdComponent?=?this.vcref.createComponent( ????????this.cfr.resolveComponentFactory(HomeComponent) ??????);?? ??} }
In this way, when routing to access a certain page, as long as the content of the page being accessed uses import() and dynamically imported with the component, wouldn't it be possible to achieve the effect of lazyLoad on the page? ?
答案是可以的。但是這樣會有一個大問題:被 lazyLoad 的組件中,其內容僅僅是當前組件的代碼,并不包含引用的其他模塊中組件的代碼。
原因是 Angular 應用由多個模塊組成,每個模塊中需要的功能可能來自其他模塊,比如 A 模塊里要用到 table
組件,而 table
需取自于 ng-zorro-antd/table
模塊。打包時 Angular 不像 React 或 Vue 可以把當前組件和用到的其他包一起打包,以 React 為例:在 A 組件引入 table 組件,打包時 table 代碼會打包到 A 組件中。而 Angular 中,在 A 組件中使用 table 組件時,并且使用 imprt()
對 A 組件進行動態(tài)加載,打包出來的 A 組件并不包含 table 的代碼, 而是會把 table 代碼打包到當前模塊中去,如果一個模塊中包含多個頁面,這么多頁面用了不少UI組件,那么打包出來的模塊肯定會很大。
那么就沒有別的方法了嗎?答案是有的,那就是把每個頁面拆成一個 module,每個頁面所用到的其他模塊或組件由當前頁面對應的模塊所承擔。
上圖中 dashboard
作為一個模塊,其下有兩個頁面,分別是 monitor
和 welcome
dashboard.module.ts:
import?{?NgModule?}?from?'@angular/core'; import?{?CommonModule?}?from?'@angular/common'; import?{?RouterModule,?Routes?}?from?'@angular/router'; const?routes:?Routes?=?[ ??{ ????path:?'welcome', ????loadChildren:?()?=>?import('./welcome/welcome.module').then((m)?=>?m.WelcomeModule), ??}, ??{ ????path:?'monitor', ????loadChildren:?()?=>?import('./monitor/monitor.module').then((m)?=>?m.MonitorModule), ??}, ]; @NgModule({ ??imports:?[CommonModule,?RouterModule.forChild(routes)], ??exports:?[RouterModule], ??declarations:?[], }) export?class?DashboardModule?{}
在模塊中使用路由 loadChildren 來 lazyLoad 兩個頁面模塊,現(xiàn)在再看看 WelcomeModule:
import?{?NgModule?}?from?'@angular/core'; import?{?CommonModule?}?from?'@angular/common'; import?{?WelcomeComponent?}?from?'./welcome.component'; import?{?RouterModule,?Routes?}?from?'@angular/router'; const?routes:?Routes?=?[ ??{?path:?'',?component:?WelcomeComponent?} ]; @NgModule({ ??declarations:?[WelcomeComponent], ??imports:?[RouterModule.forChild(routes),?CommonModule] }) export?class?WelcomeModule?{}
就是這么簡單,就把頁面級的 lazyLoad 完成了。當需要使用外部組件時,比如 table 組件,只要在 imports 引入即可:
import?{?NzTableModule?}?from?'ng-zorro-antd/table'; @NgModule({ ??... ??imports:?[...,?NzTableModule] }) export?class?WelcomeModule?{}
題外話:我更喜歡 React 的拆分方式,舉個例子:React 中使用 table 組件,table 組件本身代碼量比較大,如果很多頁面都使用 table,那么每個頁面都會有 table 代碼,造成不必要的浪費。所以可以配合 import()
把 table
組件單拉出來,打包時 table
作為單獨的 js
被瀏覽器下載并提供給需要的頁面使用,所有頁面共享這一份 js
即可。但 Angular 做不到,它無法在模塊的 imports
中使用 import()
的模塊 。
后續(xù)
以上都是對項目代碼做了比較合理的拆分,后續(xù)會對 Angular 性能上做合理的優(yōu)化,主要從編譯模式、變更檢測、ngFor、Worker等角度來闡述。
更多編程相關知識,請訪問:編程視頻??!
The above is the detailed content of What should I do if the project is too big? How to split Angular projects reasonably?. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

WebSocket and JavaScript: Key technologies for realizing real-time monitoring systems Introduction: With the rapid development of Internet technology, real-time monitoring systems have been widely used in various fields. One of the key technologies to achieve real-time monitoring is the combination of WebSocket and JavaScript. This article will introduce the application of WebSocket and JavaScript in real-time monitoring systems, give code examples, and explain their implementation principles in detail. 1. WebSocket technology

Angular.js is a freely accessible JavaScript platform for creating dynamic applications. It allows you to express various aspects of your application quickly and clearly by extending the syntax of HTML as a template language. Angular.js provides a range of tools to help you write, update and test your code. Additionally, it provides many features such as routing and form management. This guide will discuss how to install Angular on Ubuntu24. First, you need to install Node.js. Node.js is a JavaScript running environment based on the ChromeV8 engine that allows you to run JavaScript code on the server side. To be in Ub

How to use WebSocket and JavaScript to implement an online speech recognition system Introduction: With the continuous development of technology, speech recognition technology has become an important part of the field of artificial intelligence. The online speech recognition system based on WebSocket and JavaScript has the characteristics of low latency, real-time and cross-platform, and has become a widely used solution. This article will introduce how to use WebSocket and JavaScript to implement an online speech recognition system.

Introduction to how to use JavaScript and WebSocket to implement a real-time online ordering system: With the popularity of the Internet and the advancement of technology, more and more restaurants have begun to provide online ordering services. In order to implement a real-time online ordering system, we can use JavaScript and WebSocket technology. WebSocket is a full-duplex communication protocol based on the TCP protocol, which can realize real-time two-way communication between the client and the server. In the real-time online ordering system, when the user selects dishes and places an order

JavaScript and WebSocket: Building an efficient real-time weather forecast system Introduction: Today, the accuracy of weather forecasts is of great significance to daily life and decision-making. As technology develops, we can provide more accurate and reliable weather forecasts by obtaining weather data in real time. In this article, we will learn how to use JavaScript and WebSocket technology to build an efficient real-time weather forecast system. This article will demonstrate the implementation process through specific code examples. We

How to use WebSocket and JavaScript to implement an online reservation system. In today's digital era, more and more businesses and services need to provide online reservation functions. It is crucial to implement an efficient and real-time online reservation system. This article will introduce how to use WebSocket and JavaScript to implement an online reservation system, and provide specific code examples. 1. What is WebSocket? WebSocket is a full-duplex method on a single TCP connection.

JavaScript tutorial: How to get HTTP status code, specific code examples are required. Preface: In web development, data interaction with the server is often involved. When communicating with the server, we often need to obtain the returned HTTP status code to determine whether the operation is successful, and perform corresponding processing based on different status codes. This article will teach you how to use JavaScript to obtain HTTP status codes and provide some practical code examples. Using XMLHttpRequest

The default display behavior for components in the Angular framework is not for block-level elements. This design choice promotes encapsulation of component styles and encourages developers to consciously define how each component is displayed. By explicitly setting the CSS property display, the display of Angular components can be fully controlled to achieve the desired layout and responsiveness.
