在库中使用schematics——ng add与ng update
起步
创建一个angular库
ng new demo --create-application=false
ng g library my-lib
可见如下目录结构
├── node_modules/
├── projects
│   └── my-lib
│       ├── src
│       │   ├── lib
│       │   ├── public-api.ts
│       │   └── test.ts
│       ├── karma.conf.js
│       ├── ng-package.json
│       ├── package.json
│       ├── README.md
│       ├── tsconfig.lib.json
│       ├── tsconfig.lib.prod.json
│       ├── tsconfig.spec.json
│       └── tslint.json
├── README.md
├── package.json
├── .editorconfig
├── angular.json
├── tsconfig.base.json
├── tslint.json
└── tsconfig.json
添加projects/my-lib/schematics/collection.json文件
{
  "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
  "schematics": {
    "ng-add": {
      "description": "Add my library to the project.",
      "factory": "./ng-add/index#ngAdd"
    }
  }
}
修改projects/my-lib/package.json文件
{
  "name": "my-lib",
  "version": "0.0.1",
  "schematics": "./schematics/collection.json",
}
添加projects/my-lib/schematics/ng-add/index.ts文件
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
import { strings } from '@angular-devkit/core';
// Just return the tree
export function ngAdd(options: any): Rule {
  return (tree: Tree, context: SchematicContext) => {
    context.addTask(new NodePackageInstallTask());
     // 如果不是 Angular 项目则抛出错误
    const workspaceConfig = tree.read('angular.json');
    if (!workspaceConfig) {
      throw new SchematicsException('Not an Angular CLI workspace');
    }
     const templateSource = apply(url('./files'), [
      applyTemplates({
        ...strings
      }),
      move(normalize('')),
    ]);
    return chain([mergeWith(templateSource)]);
  };
}
添加projects/my-lib/schematics/ng-add/files 文件
└── files
      └──index.ts
index.ts内容如下
// #docregion template
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
  providedIn: 'root'
})
export class <%= classify(name) %>Service {
  constructor(private http: HttpClient) { }
}
定义依赖类型,在projects/my-lib/package.json中添加
"ng-add": {
  "save": "devDependencies"
}
修改projects/my-lib/tsconfig.schematics.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "lib": [
      "es2018",
      "dom"
    ],
    "declaration": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "noEmitOnError": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "noUnusedParameters": true,
    "noUnusedLocals": true,
    "rootDir": "schematics",
    "outDir": "../../dist/my-lib/schematics",
    "skipDefaultLibCheck": true,
    "skipLibCheck": true,
    "sourceMap": true,
    "strictNullChecks": true,
    "target": "es6",
    "types": [
      "jasmine",
      "node"
    ]
  },
  "include": [
    "schematics/**/*"
  ],
  "exclude": [
    "schematics/*/files/**/*"
  ]
}
| 属性 | 说明 | 
|---|---|
| rootDir | 指出在你的 schematics/ 文件夹中包含要编译的输入文件。 | 
| outDir | 映射到了库的输出目录下。默认情况下,这是工作空间根目录下的 dist/my-lib 文件夹 | 
修改projects/my-lib/package.json
{
  "name": "my-lib",
  "version": "0.0.1",
  "scripts": {
    "build": "../../node_modules/.bin/tsc -p tsconfig.schematics.json",
    "copy:files": "cp --parents -p -r schematics/*/files/** ../../dist/my-lib/",
    "copy:collection": "cp schematics/collection.json ../../dist/my-lib/schematics/collection.json",
    "postbuild":"npm run copy:files && npm run copy:collection"
  },
  "peerDependencies": {
    "@angular/common": "^7.2.0",
    "@angular/core": "^7.2.0"
  },
  "schematics": "./schematics/collection.json",
  "ng-add": {
    "save": "devDependencies"
  }
}
| 属性 | 说明 | 
|---|---|
| build | 脚本使用自定义的 tsconfig.schematics.json 文件来编译你的原理图。 | 
| copy | *语句将已编译的原理图文件复制到库的输出目录下的正确位置,以保持目录的结构。 | 
| postbuild | 脚本会在 build 脚本完成后复制原理图文件。 | 
修改根目录下的package.json,在scripts下加入
 "build": "ng build my-lib --prod && cd ./projects/my-lib && npm run build",
 "publish": "cd ./dist/my-lib && npm publish"
开始发布
npm publish
试一试ng add吧!
使用schematics修改项目
如何使用schematics修改项目中的package.json
| 方法 | 说明 | 
|---|---|
| tree.overwrite() | 重新编排package.json | 
| tree.read() | 读取文件内容 | 
修改projects/my-lib/schematics/ng-add/index.ts
    //读取angular.json的文件内容
    const workspaceConfig = tree.read('angular.json');
    // 如果不是 Angular 项目则抛出错误
   if (!workspaceConfig) {
      throw new SchematicsException('Not an Angular CLI workspace');
    }
    // 读取package.json的文件内容
    const workspaceJson = tree.read('package.json');
    let json=JSON.parse(workspaceJson)
    json.script.hello="print('123')"
    tree.overwrite('./package.json',JSON.stringify(json))
在node_modules添加引入与注入项
| 方法 | 说明 | 
|---|---|
| addImportToModule(source: ts.SourceFile, modulePath: string, classifiedName: string, importPath: string): Change[] | 添加引入到module | 
| ts.createSourFile | 创建资源文件 | 
import * as ts from '@schematics/angular/third_party/github.com/Microsoft/TypeScript/lib/typescript';
import { addImportToModule } from '@schematics/angular/utility/ast-utils';
......
  const modulePath = `/app.module.ts`;
  const sourText = _tree.read(modulePath).toString('utf-8');
  const sourceFile =  ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true);
  const importPath = '@fortawesome/angular-fontawesome';
  const moduleName = 'FontAwesomeModule';  //文件名为驼峰命名
  const declarationChanges = addImportToModule(sourceFile, modulePath, moduleName, importPath);
  const declarationRecorder = _tree.beginUpdate(modulePath);
  for (const change of declarationChanges) {
    if (change instanceof InsertChange) {
        declarationRecorder.insertLeft(change.pos, change.toAdd);
    }
  }
 _tree.commitUpdate(declarationRecorder);
更新文件
| 方法 | 说明 | 
|---|---|
| tree.beginUpdate() | 更新内容 | 
   const htmlPath = `./app/src/app.component.html`;
   const htmlStr = `\n\n`;
   const modulePath = `/app.module.ts`;
   const sourText = _tree.read(htmlPath).toString('utf-8');
   const htmlSourceFile =  ts.createSourceFile(htmlPath, sourceText, ts.ScriptTarget.Latest, true);
   const htmlRecorder = _tree.beginUpdate(htmlPath);
   htmlRecorder.insertLeft(htmlSourceFile.end, htmlStr);
   _tree.commitUpdate(htmlRecorder);
package.json依赖项安装
| 方法 | 说明 | 
|---|---|
| addPackageToPackageJson | 添加依赖支持 | 
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
......
const dependencies = [{ name: '@fortawesome/fontawesome-svg-core', version: '~1.2.25' }],
addPackageToPackageJson(
    _tree,
    dependency.name, //依赖包名
    dependency.version,//版本
);
ng Update使用
在collection.json 同级目录,新建 migration.json 文件,并写入以下内容:
{
    "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
    "schematics": {
        "migration002": {
            "version": "0.0.2",
            "description": "更新angular-schematics-tutorial到0.0.2版本时执行的更新",
            "factory": "./ng-update/index#update"
        }
    }
}
在 package.json 中声明 ug-update 配置
在 package.json 中,添加以下项目:
  "ng-update": {
    "migrations": "./schematics/migration.json"
  },
其作用,就是在执行 ng update 时,能够找到对应的配置文件
在projects/my-lib/schematics/ 目录下新建index.ts
import { Rule, Tree, SchematicContext, SchematicsException } from '@angular-devkit/schematics';
import { buildDefaultPath } from '@schematics/angular/utility/project';
import * as ts from 'typescript';
export function update(): Rule {
    return (_tree: Tree, _context: SchematicContext) => {
        // 解析angular项目
        const workspaceConfigBuffer = _tree.read('angular.json');
        if (!workspaceConfigBuffer) {
            throw new SchematicsException('Not an Angular CLI workspace');
        }
        return tree.create('index.md','我更新了')
      }
}
完结撒花!!
在库中使用schematics——ng add与ng update的更多相关文章
- Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法
		一.前言: 上文中,笔者系统的阐述了1602的两种驱动方式,并简单的提到了Arduino的LiquidCrystal库.本文紧接上文,对以下两个问题进行更加深入的探讨:如何能够使1602对Arduin ... 
- SharePoint 2013 文档库中PPT转换PDF
		通过使用 PowerPoint Automation Services,可以从 PowerPoint 二进制文件格式 (.ppt) 和 PowerPoint Open XML 文件格式 (.pptx) ... 
- 如何扫描出Android系统媒体库中视频文件
		Android系统启动时会去扫描系统文件,并将系统支持的视频文件(mp4,3gp,wmv)扫描到媒体库(MediaStore)中,下面代码演示如何获得这些文件的信息: publicstatic Lis ... 
- 删除本地git版本库中受版本控制的文件
		git乱码解决方案汇总 乱码原因 搜索一番,发现git文件名.log乱码,是普遍问题,这其中有编码的原因,也有跨平台的原因.主要原因是Windows 系统中的Git对中文文件名采用不同的编码保存所致 ... 
- 线程高级应用-心得8-java5线程并发库中同步集合Collections工具类的应用及案例分析
		1. HashSet与HashMap的联系与区别? 区别:前者是单列后者是双列,就是hashmap有键有值,hashset只有键: 联系:HashSet的底层就是HashMap,可以参考HashSe ... 
- 用CAS操作实现Go标准库中的Once
		Go标准库中提供了Sync.Once来实现"只执行一次"的功能.学习了一下源代码,里面用的是经典的双重检查的模式: // Once is an object that will p ... 
- 项目中通过Sorlj获取索引库中的数据
		在开发项目中通过使用Solr所提供的Solrj(java客户端)获取索引库中的数据,这才是真正对项目起实质性作用的功能,提升平台的检索性能及检索结果的精确性 第一步,引入相关依赖的jar包 第二步,根 ... 
- Git添加远程库和从远程库中获取(新手傻瓜式教学)
		一. Git添加远程库 1.在本地新建一个文件夹,在该文件夹使用Git工具,运行$ git init,将该文件夹变为本地Git仓库,同时会生成一个隐藏的.git文件夹. 2.在该文件夹中用Not ... 
- Git添加远程库和从远程库中获取
		一. Git添加远程库 1. 在本地新建一个文件夹,在该文件夹使用Git工具,运行$ git init,将该文件夹变为本地Git仓库,同时会生成一个隐藏的.git文件夹. 2. 在该文件夹中用Note ... 
随机推荐
- Boom 3D的本地音乐播放功能大放送
			众所周知,Boom 3D是一款音效增强软件.但是Boom 3D不仅可以用来增强音效,还可以用作本地音乐播放器,以无与伦比的效果播放本地存储的歌曲,并创建播放列表来整理您的音乐收藏,就像个人音乐播放器应 ... 
- jenkins master/slave模式
			master是主机,只有master装jenkins slave是小弟机无需装jenkins,主要执行master分配的任务 一.新建slave 1.新建slave的方法:点击magian jenki ... 
- kakafka - 为CQRS而生fka - 为CQRS而生
			前段时间跟一个朋友聊起kafka,flint,spark这些是不是某种分布式运算框架.我自认为的分布式运算框架最基础条件是能够把多个集群节点当作一个完整的系统,然后程序好像是在同一台机器的内存里运行一 ... 
- PC 端轮播图的实现
			<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ... 
- 一分钟了解 sync、fsync、fdatasync 系统调用
			目录 一.缓冲 二.延迟写的优缺点 三.sync.fsync.fdatasync 关注送书!<Netty实战>(今晚开奖) Hi,大家好!我是白日梦. 今天我要跟你分享的话题是:" ... 
- CF980C Posterized
			先来吐槽一下这个 sb 翻译,根本就没做过题吧-- 大概就是让你给值域分成连续的几组,每组大小不能超过 \(k\),然后将序列中的值全部替换成其组内的最小值,要使得序列的字典序最小. 因为是字典序,所 ... 
- LeetCode周赛#212
			1631. 最小体力消耗路径 #并查集 #最短路径 题目链接 题意 给定一二维 rows x columns 的地图 heights ,其中 heights[row][col] 表示格子 \((row ... 
- Linux下使用Docker部署nacos-server(单机模式),丧心病狂的我在半夜给UCloud提交了一份工单
			1. 拉取nacos-server镜像 进入 Docker Hub 查看nacos-server最新版本为 nacos-server:1.4.0 配置阿里云镜像加速 sudo mkdir -p /et ... 
- python3 通过 pybind11 使用Eigen加速代码
			python是很容易上手的编程语言,但是有些时候使用python编写的程序并不能保证其运行速度(例如:while 和 for),这个时候我们就需要借助c++等为我们的代码提速.下面是我使用pybind ... 
- 老猿学5G扫盲贴:PDU协议数据单元、PDU连接业务和PDU会话的功能详解
			专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.PDU 关于PDU在百度百科是这样定义的:协议 ... 
