Cách phát triển thư viện Angular tại địa phương
Xin chào ! Trong câu chuyện này, tôi muốn chỉ cho bạn cách làm việc cục bộ với các thư viện Angular và phát triển chúng mà không cần phải liên tục đẩy chúng vào kho lưu trữ từ xa :)
DRY - cách tránh lặp lại mã
Nếu bạn làm việc trong một dự án Angular lớn và phức tạp, tôi chắc chắn rằng bạn sẽ gặp phải vấn đề sao chép mã. Ví dụ: hãy tập trung vào “giao diện” của ứng dụng của bạn - tất cả các trang có thể phải có kiểu nhất quán (bạn không muốn làm người dùng nhầm lẫn và có các nút trông khác nhau trên mỗi trang). Ok, thật dễ dàng - bạn chỉ cần di chuyển các kiểu phổ biến đó vào styles.scss
tệp hoặc sử dụng mẫu 7–1 để thiết kế nó một cách trang nhã.
Nhưng điều gì sẽ xảy ra nếu bạn có một số thành phần chung không chỉ trông giống nhau mà còn hoạt động giống nhau? Nó… vẫn còn dễ dàng! Chỉ cần tạo một mô-đun dùng chung trong ứng dụng của bạn, xác định các thành phần của bạn ở đó và xuất chúng trong định nghĩa mô-đun. Tuyệt quá !
Bây giờ, hãy tập trung vào vấn đề phức tạp hơn. Nếu công ty của bạn có nhiều hơn một ứng dụng Angular thì sao? Và mỗi ứng dụng sẽ trông giống nhau, ví dụ:
- có cùng đầu trang và chân trang
- có cùng kiểu CSS công ty
- có cùng cách hiển thị biểu mẫu, lỗi xác thực và các thông báo khác
tạo thư viện
Tại đây bạn có thể tìm thấy trang tài liệu chính thức về cách tạo thư viện. Hãy làm theo các bước được mô tả ở đó và tạo thư viện của chúng tôi:
ng new my-shared-workspace --no-create-application
cd my-shared-workspace
ng generate library my-buttons
- my-shared-workspace là không gian làm việc chung cho các thư viện của bạn
- my-buttons là một thư viện ví dụ mà bạn có thể sử dụng lại trong các dự án khác
{
"name": "@my-company/my-buttons",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^14.2.0",
"@angular/core": "^14.2.0"
},
"dependencies": {
"tslib": "^2.3.0"
}
}
my-shared-workspace/projects/my-buttons/src/lib> ng g c fancy-button
Thành phần được tạo, vì vậy chúng tôi có thể cập nhật mẫu của nó để hiển thị một nút
<button>fancy-button works!</button>
@NgModule({
declarations: [
MyButtonsComponent,
FancyButtonComponent
],
imports: [
],
exports: [
MyButtonsComponent,
FancyButtonComponent // <-- here
]
})
export class MyButtonsModule { }
/*
* Public API Surface of my-buttons
*/
export * from './lib/my-buttons.service';
export * from './lib/my-buttons.component';
export * from './lib/my-buttons.module';
export * from './lib/fancy-button/fancy-button.component'; // <-- here
Chúng tôi đã tạo thư viện của mình, vì vậy bây giờ là lúc dành cho ứng dụng khách. Tôi sẽ sử dụng CLI góc để tạo nó: ng new my-application
và tôi sẽ thêm @my-company/my-buttons
làm phần phụ thuộc vào phần phụ thuộc của ứng dụng package.json
(phần phụ thuộc cuối cùng, sau zone.js
)
{
"name": "my-application",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "^14.2.0",
"@angular/common": "^14.2.0",
"@angular/compiler": "^14.2.0",
"@angular/core": "^14.2.0",
"@angular/forms": "^14.2.0",
"@angular/platform-browser": "^14.2.0",
"@angular/platform-browser-dynamic": "^14.2.0",
"@angular/router": "^14.2.0",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4",
"@my-company/my-buttons": "0.0.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "^14.2.6",
"@angular/cli": "~14.2.6",
"@angular/compiler-cli": "^14.2.0",
"@types/jasmine": "~4.0.0",
"jasmine-core": "~4.3.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.0.0",
"typescript": "~4.7.2"
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MyButtonsModule } from '@my-company/my-buttons';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
MyButtonsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
<lib-fancy-button></lib-fancy-button>
Error: src/app/app.component.html:1:1 - error NG8001: 'lib-fancy-button' is not a known element:
1. If 'lib-fancy-button' is an Angular component, then verify that it is part of this module.
2. If 'lib-fancy-button' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
1 <lib-fancy-button></lib-fancy-button>
~~~~~~~~~~~~~~~~~~
src/app/app.component.ts:5:16
5 templateUrl: './app.component.html',
~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component AppComponent.
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
Bạn cũng sẽ thấy một số lỗi khác như:
Error: src/app/app.module.ts:3:33 - error TS2307: Cannot find module '@my-company/my-buttons' or its corresponding type declarations.
3 import { MyButtonsModule } from '@my-company/my-buttons';
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/@my-company%2fmy-buttons - Not found
npm ERR! 404
npm ERR! 404 '@my-company/[email protected]' is not in this registry.
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
Npm link to the rescue
Tại đây bạn có thể tìm thấy tài liệu lệnh liên kết npm hoàn chỉnh. Tôi sẽ chỉ cho bạn cách sử dụng lệnh này để phát triển thư viện dùng chung cục bộ, với tính năng tải lại trực tiếp.
Hãy quay lại thư mục my-shared-workspace
, xây dựng my-buttons
thư viện (cờ --watch
chịu trách nhiệm tải lại trực tiếp) và vào thư mục của bản dựng
my-shared-workspace> ng build my-buttons --configuration development --watch
Building Angular Package
------------------------------------------------------------------------------
Building entry point '@my-company/my-buttons'
------------------------------------------------------------------------------
✔ Compiling with Angular sources in Ivy full compilation mode.
✔ Writing FESM bundles
✔ Copying assets
✔ Writing package manifest
✔ Built @my-company/my-buttons
------------------------------------------------------------------------------
Built Angular Package
- from: /Users/<user>/<path>/my-shared-workspace/projects/my-buttons
- to: /Users/<user>/<path>/my-shared-workspace/dist/my-buttons
------------------------------------------------------------------------------
my-shared-workspace> cd dist/my-buttons
my-shared-workspace/dist/my-buttons> npm link
added 1 package, and audited 3 packages in 1s
found 0 vulnerabilities
Trong thư mục my-application
, angular.json
thêm một tùy chọn nữa - bảo quảnSymlinks, tùy chọn này sẽ cho phép chúng tôi sử dụng thư viện được liên kết này.
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"my-application": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/my-application",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"preserveSymlinks": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "my-application:build:production"
},
"development": {
"browserTarget": "my-application:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "my-application:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
}
}
}
}
}
my-application> npm link @my-company/my-buttons
added 1 package, removed 1 package, and audited 918 packages in 2s
121 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Sau đó chạy ng serve
lại:
my-application> ng serve
✔ Browser application bundle generation complete.
Initial Chunk Files | Names | Raw Size
vendor.js | vendor | 3.30 MB |
polyfills.js | polyfills | 318.02 kB |
styles.css, styles.js | styles | 210.56 kB |
main.js | main | 12.32 kB |
runtime.js | runtime | 6.53 kB |
| Initial Total | 3.84 MB
Build at: 2022-11-24T18:27:00.803Z - Hash: 7669daf65ca2f665 - Time: 4598ms
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
✔ Compiled successfully.
Hãy xem kết quả:
![](https://post.nghiatu.com/assets/images/m/max/724/1*cd6q4WSio8rRLNuniQvgJA.png)
Tuyệt quá ! Bây giờ hãy thử thay đổi một cái gì đó trong Fancy-button-component.html
<button>fancy-button works - live reload!</button>
![](https://post.nghiatu.com/assets/images/m/max/724/1*HMqX3E-zHrixTeDku5tJ_g.png)
Bây giờ bạn có thể làm việc trên cả thư viện và ứng dụng mà không gặp bất kỳ sự bất tiện nào :)
xác minh
Để xác minh phiên bản thư viện bạn đang sử dụng, bạn có thể chạy lệnh dưới đây:
npm list -g
/usr/local/lib
├── @angular/[email protected]
├── @my-company/[email protected]+1669314745555 -> ./../../../Users/<user>/<path>/my-shared-workspace/dist/my-buttons
Sau khi bạn hoàn thành các thay đổi cục bộ, bạn có thể ngừng sử dụng thư viện được liên kết trong ứng dụng khách theo cách sau
my-application> npm unlink @my-company/my-buttons --no-save
my-shared-workspace/dist/my-buttons> npm rm -g @my-company/my-buttons
Vật liệu
- Mẫu Sass 7–1
- Tài liệu góc - tạo thư viện
- tài liệu liên kết npm
- https://dgtechboost.com/2022/03/20/test-and-debug-angular-library-using-npm-link/
- https:///@maravondra/angular-component-in-locale-usage-8536d91fc844