NG添加示意图
学习如何构建一个Angular原理图来添加一个库。
入门教程
如果你是Angular原理图的新手,那么我建议你从我的角度原理图教程。
Angularfire原理图
- 使用NPM或YARN安装两个Firebase.和@angular /火模块。
- 将Firebase项目的配置添加到Angular中环境文件。
- 将AngularFire模块导入根模块。
虽然这是一个简单的安装路径,但我认为解决所有这一切的原理图,它会很有趣,包括提示您的Firebase配置。
ng补充道
试试看:
$ ng new demo $光盘演示$ NG.加角火原理图
演示
下载
目标
我的目标是让你们学到:
- 如何创建一个将库添加到Angular项目(应用程序或库)的原理图。
- 使用TypeScript抽象语法树(AST)的开始。
- 如何将文件更新提交到文件中的文件
树
。
我们的目标是建立可以使用Angular CLI添加的示意图。
创建原理图集合
如果您尚未安装原理图CLI,则通过NPM或YARN执行此操作:
$npm安装- g @angular-devkit / schematics-cli $纱加-g @ Angular-devkit / schematics-cli
第一步是使用使用的创建新的原理图集合空白示意图:
$ schicatics空白--name=角火原理图
这将创建一个新的角火原理图目录,添加必要的文件和文件夹以构建原理图,然后安装必要的依赖项。
让我们为我们的项目初始化一个Git仓库:
$光盘棱角 - 原理图数$git在里面
继续并在您喜欢的编辑器或IDE中打开项目。我将使用VS Code:
代码angular-fire-schematics美元
创建ng-add目录
让我们把我们的SRC.目录真实快速:
$rm-RF SRC / Angular-Fire-Schematics $MKDIR.src / ng-add美元触摸src / ng-add / schema.json $触摸src / ng-add / index.ts
将Schematic添加到集合中
打开src / collection.json.文件,并添加ng-add
作品集示意图:
{“美元模式”:“. . / node_modules / @angular-devkit /图表/ collection-schema.json”那“图表”:{“ng-add”:{“描述”:把Angular的Firebase添加到应用中,而不影响任何模板那“厂”:”。/ ng-add指数”那“架构”:“./ng-add/schema.json”那“别名”:[“安装”]}}}
我指定了以下属性:
- 该
描述
的示意图。 - 该
工厂
函数,该函数将作为示意图的“入口”点执行。在本例中,我导出了一个默认函数src / ng-add / index.js文件。 - 该
架构
的示意图。 - 该
别名
为我们的原理图声明别名的数组。这就是使用Angular CLI时使用速记“C”可以生成组件的原因。
注意,如果你不导出默认函数,你可以使用下面的语法,在#符号后面指定要调用的函数:“工厂”:“./ng-add/index#functionname
。
定义原理图架构
接下来,定义ng-add原理图的模式。模式将包括newx-prompt
属性,在v7中引入。这将提示用户输入Firebase配置。
创建一个新文件src / ng-add / schema.json:
{“美元模式”:“http://json-schema.org/schema”那“id”:“angular-firebase-schematic-ng-add”那“标题”:“Angular Firebase NG-Add原理图”那“类型”:“对象”那“属性”:{“项目”:{“类型”:“串”那“描述”:“项目名称。”那“$默认”:{“$源”:“项目名”}}那“apikey”:{“类型”:“串”那“默认”:“那“描述”:“你的Firebase API键”那“x-xpert”:“你的项目是什么?”}那“authDomain”:{“类型”:“串”那“默认”:“那“描述”:“你的Firebase域”那“x-xpert”:“你的项目的authDomain是什么?”}那“databaseURL”:{“类型”:“串”那“默认”:“那“描述”:"您的Firebase数据库URL"那“x-xpert”:“你的项目的databaseURL是什么?”}那“projectId”:{“类型”:“串”那“默认”:“那“描述”:“你的Firebase项目ID”那“x-xpert”:“你项目的id是什么?”}那“storagebucket”:{“类型”:“串”那“默认”:“那“描述”:“你的Firebase存储桶”那“x-xpert”:“你的项目的存储空间是什么?”}那“messagingsenderid”:{“类型”:“串”那“默认”:“那“描述”:"您的Firebase消息发送者ID"那“x-xpert”:“你的项目的消息人员是什么?”}}那“需要”:[]那“additionalProperties”:假}
对于每个选项,我们指定:
- 类型签字
类型
。 - 一种
默认的
价值。 - 该
描述
。 - 该
x-prompt
值的文本,当命令行上没有指定该选项时提示用户
定义架构
我喜欢强烈键入用户可以指定的选项。这为我提供了在使用时的类型安全性选项
我原理图的进入函数的论证。
创建一个新的src / app / schema.ts文件和导出模式
接口:
出口接口模式{/ ** Firebase API键。* /apikey.:字符串;/ ** Firebase授权域名。* /Authdomain.:字符串;/ ** Firebase DB URL。* /DataberUrl.:字符串;/ **项目的名称为目标。* /项目:字符串;/ ** Firebase项目ID。* /ProjectId.:字符串;/ ** Firebase存储桶。* /存储空间:字符串;/** Firebase消息发送者ID. */messagingSenderId:字符串;}
创建默认功能
脚手架脚手架的最后一步是创建我常用的内容作为“条目”函数。这是执行原理图时调用的函数。如果你记得,我们将我们指定了路径src / index.js.文件在collection.json文件。
将以下默认功能添加到src / ng-add / index.ts文件:
出口默认的功能(选项:模式):规则{返回(树:树那_Context.:示意图)= >{返回树;};}
构建和运行
虽然我们目前只是一个空的壳,让我们建立并运行原理图来验证到目前为止我们创建的内容:
$纱构建$ schematics
沙盒测试
虽然示意图应包括单位测试套件,以提供必要的覆盖,以便验证原理图的质量,我喜欢使用沙箱测试方法,视觉上差异为执行示意图所做的变化。
我从同事Kevin Schuchard那里学到了这个技巧,他是一位非常聪明的工程师。看看他的帖子是关于使用沙盒来开发角度示意图。
首先,使用ng新
命令。我将为应用程序提供名称“sandbox”:
$ ng新的沙盒
为了避免在我们的沙箱应用程序中嵌入git存储库,请删除.git.目录内沙箱目录中。然后,让我们创建一个新的提交与我们项目的所有更改。
$rm射频沙箱/。git美元git加- $gitcommit - m“初步提交”
然后,让我们用Angular CLI定义一些脚本,在Angular沙箱应用的上下文中链接、清理和测试我们的原理图:
{“脚本”:{“构建”:“tsc - p tsconfig.json”那“清洁”:git checkout HEAD—sandbox && git clean -f -d sandbox那“链接:示意图”:“纱线链接&& CD沙箱&&纱线链接\”Angular-Fire-schematics \“”那“沙箱:ng-add”:“CD沙箱&& ng v Angular-fire-schematics:ng-add”那“测试”:“纱线清洁&&纱线沙箱:NG-Add && Yarn测试:沙箱”那“测试:单位”:“yarn build && jasmine src/**/*_spec.js”那“测试:沙箱”:《cd沙箱&&纱线lint &&纱线测试&&纱线构建》}}
最后,链接角火原理图通过执行以下命令将包打包到沙箱中:
$纱链接:原理图
我们现在准备使用我们的沙箱应用程序中的角CLI构建和执行我们的原理图。
公用事业公司
我们将使用许多公用事业职能提供@angular /图表和@angular / cdk模块。大多数功能都位于一个效用目录中。这些工具将使我们实现:
- 更新项目包中的依赖项.json文件,
- 安装依赖关系,
- 确定Angular项目的工作区配置,
- 更新角度模块,
- 和更多。
让我们使用NPM或YARN安装两个模块:
$纱加@angular /图表@angular / cdk $npm安装@ Angular / Schematics @ Angular / CDK
我还为此项目带来了几个实用程序功能。这些实用功能从各种来源收集,包括角CLI示意图,CDK原理图,角度材料原理图等。
复制以下文件角火原理图SRC / ill.目录:npmjs.ts那project-configurations.ts那Project-Environment-File.ts和版本-agnostic-typescript.ts。
链规则
我们的第一批任务是构建NG-Add原理图,可以将AngularFire添加到角度项目,是将必要的依赖性添加到package.json.文件。
更新默认功能src / index.ts文件,以使用链()
将函数链接在一起多种规则:
出口默认的功能(选项:模式):规则{返回(树:树那_Context.:示意图)= >{返回链([addPackageJsonDependencies()那installDependencies()那setupProject(选项)])(树那_Context.);};}
然后,声明addpackagejsondependencies()
那installdependencies()
和setupproject()
功能:
功能addPackageJsonDependencies():规则{}功能installDependencies():规则{返回(树:树那_Context.:示意图)= >{返回树;}}功能setupProject(选项:模式):规则{安慰。日志(选项);返回(树:树那_Context.:示意图)= >{返回树;}}
添加依赖项
接下来,我们将实现addpackagejsondependencies()
功能src / index.ts文件:
进口{addPackageJsonDependency那NodeDependency那NodeDependencyType}从“@schematics /角度/工具/依赖”;进口{getlatestnodeversion.那NpmRegistryPackage}从'../util/npmjs';功能addPackageJsonDependencies():规则{返回(树:树那_Context.:示意图):可观测的<树>= >{返回的('firebase'那'@角/火')。管(concatMap(的名字= >getlatestnodeversion.(的名字))那地图((npmregistrypackage.:NpmRegistryPackage)= >{常量重点依赖:NodeDependency={类型:NodeDependencyType。默认那的名字:npmregistrypackage.。的名字那版:npmregistrypackage.。版那覆盖:假};addPackageJsonDependency(树那重点依赖);_Context.。日志记录器。信息(“✅️还说依赖);返回树;}));};}
让我们回顾一下:
- 首先,
addpackagejsondependencies()
是一个返回a的工厂函数规则
,接受树
和示意图
对象。 - 我们创造一个新的
可观测的
使用的()
发出两个通知的函数是字符串:'firebase'和'@角/火'。 - 我用的是效用函数
getlatestnodeversion()
返回一个可观测的
当NpmRegistryPackage
的每个依赖项http://registry.npmjs.orgAPI。 - 我们创造一个新的
NodeDependency
对象,然后调用addpackagejsondendency()
函数。这些类型和函数是从中导入的@schematics /角模块并位于实用程序/附件目录中。 - 该
addpackagejsondendency()
函数完成了向包添加依赖项的繁重工作。json文件。 - 最后,我们使用
示意图
登出指示依赖项已成功添加的info语句。
然后,运行构建和测试脚本:
$纱建立美元纱测试
查看package.json文件的差异:
$git差沙箱/包.JSON.
注意这两种@angular /火和Firebase.沙箱应用程序已经添加了依赖项package.json.文件。
安装依赖关系
使用我们的申请package.json.下一步是安装新的依赖项。
实施installdependencies()
如下:
进口{nodepackageinstalltast.}从'@ Angular-devkit / schematics / tasks';功能installDependencies():规则{返回(树:树那_Context.:示意图)= >{_Context.。addTask(新nodepackageinstalltast.());_Context.。日志记录器。调试(“✅️依赖安装的);返回树;};}
值得庆幸的是,使用nodepackageinstalltast.
从中出口的课程@angular-devkit /图表/任务模块。
让我们再次构建并运行原理图,我们应该观察到,在更新后安装了新的依赖项package.json.文件:
$纱建立美元纱测试
安装原理图
该ng-addschematic添加必要的依赖项并安装它们。下一步是创建一个原理图,为AngularFire执行必要的设置和配置。
打开src / collection.json.文件并定义一个标题的新示意图NG-Add-Setup-Project。完整文件现在应该如下所示:
{“美元模式”:“. . / node_modules / @angular-devkit /图表/ collection-schema.json”那“图表”:{“ng-add”:{“描述”:把Angular的Firebase添加到应用中,而不影响任何模板那“厂”:”。/ ng-add指数”那“架构”:“./ng-add/schema.json”那“别名”:[“安装”]}那“ng-add-setup-project”:{“描述”:"在安装ng-add依赖项后设置指定的项目。"那“私人”:真正那“厂”:“./ng-add/setup-project”那“架构”:“./ng-add/schema.json”}}}
接下来,创建src / ng-add / setup-project.ts文件:
$触摸src / ng-add / setup-project.ts
首先,我们将去除默认函数:
进口{链那规则那示意图那树}从“@angular-devkit /图表”;进口{模式}从'./schema';出口默认的功能(选项:模式):规则{返回(树:树那_Context.:示意图)= >{返回链([addEnvironmentConfig(选项)那importEnvironemntIntoRootModule(选项)那addAngularFireModule(选项)])(树那_Context.);};}功能addEnvironmentConfig(选项:模式):规则{返回(树:树那_Context.:示意图)= >{返回树;};}功能addAngularFireModule(选项:模式):规则{返回(树:树那_Context.:示意图)= >{返回树;};}功能importEnvironemntIntoRootModule(选项:模式):规则{返回(树:树那_Context.:示意图)= >{返回树;};}
该计划是:
- 配置信息添加到环境文件。
- 进口环境文件进入app.module.ts文件。
- 添加
AngularFireModule.InitializeApp()
方法进口
阵列在@NgModule ()
装饰的appmodule.
类。
这似乎非常直接。
runschematictask.
在继续设置之前,我们需要运行新创建的NG-Add-Setup-Project原理图来自ng-add示意图。为了做到这一点,我们将使用runschematictask.
类。
让我们完成实施setupproject()
功能src / ng-add / index.ts文件:
功能setupProject(选项:模式):规则{返回(树:树那_Context.:示意图)= >{常量installTaskId=_Context.。addTask(新nodepackageinstalltast.());_Context.。addTask(新runschematictask.(“ng-add-setup-project”那选项)那[installTaskId]);返回树;};}
回顾:
- 在我们执行任务之前,我们需要等到以前的任务安装节点包依赖项已完成。要做到这一点,我们首先需要得到
installTaskId
我们的新任务所依赖的。 - 接下来我们调用
addtask()
对策示意图
类指定新的runschematictask.
后面跟着依赖的任务标识符数组。 - 请注意,运行另一个原理图时,我们会指定原理图名称以及原理图的选项。我们将传递用户指定的选项ng-add示意图。
更新环境
打开src / setup-project.ts文件并实现AddEnvironmentConfig()
功能:
功能addEnvironmentConfig(选项:模式):规则{返回(树:树那背景:示意图)= >{常量工作空间=getWorkspace.(树);常量项目=getProjectFromWorkspace(工作空间那选项。项目);常量envPath=getProjectEnvironmentFile(项目);/ /验证环境。ts文件存在如果(!!envPath){返回背景。日志记录器。警告(`❌无法找到环境文件:"$ {envPath}“。跳过Firebase配置。`);}//添加到环境的firebase配置。ts文件常量插入=',\ n'+`重火力点:{\ n`+`apikey:'$ {选项。apikey.}' \ n`+`Authdomain:'$ {选项。Authdomain.}' \ n`+`atainisturl:'$ {选项。DataberUrl.}' \ n`+`ProjectID:'$ {选项。ProjectId.}' \ n`+`storageBucket:“$ {选项。存储空间}' \ n`+`messagingSenderId:“$ {选项。messagingSenderId}' \ n`+`}`;常量源文件=readIntoSourceFile(树那envPath);//验证Firebase Config尚不存在常量sourcefiletext.=源文件。getText();如果(sourcefiletext.。包括(插入)){返回;}//从SourceFile获取AST中的顶级节点对象数组常量节点=getsourcenodes.(源文件如任何);常量开始=节点。找(节点= >节点。种类===.ts。syntaxkind.。openbracetoken.)!!;常量结束=节点。找(节点= >节点。种类===.ts。syntaxkind.。Frestfbracetoken.那开始。结束)!!;常量录音机=树。beginUpdate(envPath);录音机。insertLeft(结束。pos那插入);树。commitupdate.(录音机);背景。日志记录器。信息('✅️环境配置');返回树;};}
这是相当长的!
就让我们一探究竟吧:
- 函数提供的一些实用函数@schematics /角模块,位于效用目录中。
- 首先,我们得到了
WorkspaceSchema
使用getWorkspace ()
函数。这包含Angular工作空间的元数据(在Angular Version 6中引入)。 - 接下来我们得到了
WorkspaceProject.
使用getProjectFromWorkspace()
函数。它包含Angular项目(lib或app)的元数据,包括:根目录、默认的组件前缀等。 - 然后我们得到了这个项目的道路环境文件。我们需要知道这一点以更新文件。
- 接下来我们建立
插入
串。这包含用户输入的Firebase配置数据。 - 该
readIntoSourceFile ()
功能很重要,我们接下来会详细介绍它。它返回TypeScript文件的顶级抽象语法树(AST)节点。 - 我们还需要验证firebase配置是否已经存在于环境文件。我们只用
getText()
方法,然后确定插入文本是否已存在。这有点脆,可以使用一些硬化来确保尚不存在Firebase配置。 - 使用
getSourceNodes ()
实用程序功能我们可以检索一个数组节点
对象内源文件
AST。 - 我们将使用它
array.prototype.find()
找到的方法节点
那是一个openbracetoken.
。请记住,环境文件包含单个环境
导出的常量对象。我们正在寻找作为启动环境配置对象的开括号({)的节点。 - 我们也会找到结束
节点
这是关闭支撑(})。 - 使用
tree.beginUpdate ()
方法,我们可以开始记录对树中指定文件的更改。 - 我们将插入
插入
在结束时开始的文字环境
目的。 - 最后,我们注销一些信息,表明环境配置步骤已经成功完成。
什么是AST?
在我们继续之前,让我们快速回顾一下什么是抽象语法树(AST)。
在计算机科学中,抽象语法树(AST),或者仅仅是语法树,是用编程语言编写的源代码的抽象语法结构的树形表示。树的每个节点表示源代码中出现的一个构造。
如您所能猜测Ringscript提供了一个声明文件lib / typescript.d.ts.这包括TypeScript抽象语法树的所有类型定义。
为什么这是重要的?
使用AST,我们可以使用一个可靠的编程接口来修改TypeScript源文件。
访问这一点源文件
一种源文件
是顶级节点
对于Questcript AST。这是与AST一起使用的起点。我们将使用它createSourcefile()
通过类型签字提供的方法来访问源文件
:
功能readIntoSourceFile(主办:树那文档名称:字符串):源文件{常量缓冲=主办。读(文档名称);如果(缓冲===.空值){扔新示意图Xpeption.(`文件$ {文档名称}不存在。`);}返回ts。createSourcefile.(文档名称那缓冲。toString.(“utf - 8”)那ts。scripttarget.。最新那真正);}
首先,我们用读()
对策树
要获取文件缓冲
。然后,我们调动createSourcefile()
方法,提供文件路径和TypeScript文件的内容。
进口环境
回到为AngularFire创建ng-add原理图的任务,我们的原理图的下一步是实现importenvironmontintorootmodule()
函数。此功能负责导入环境恒定对象进入根目录appmodule.
使用标准的es6导入语法。
正如我们之前所做的那样,我们将使用由提供的一些实用程序函数提供@schematics /角模块。
打开src / setup-project.ts和实现importenvironmontintorootmodule()
功能:
功能importEnvironemntIntoRootModule(选项:模式):规则{返回(树:树那背景:示意图)= >{常量IMPORT_IDENTIFIER='环境';常量工作空间=getWorkspace.(树);常量项目=getProjectFromWorkspace(工作空间那选项。项目);常量AppModulepath.=getAppModulepath.(树那getProjectMainFile(项目));常量envPath=getProjectEnvironmentFile(项目);常量源文件=readIntoSourceFile(树那AppModulepath.);如果(Isimported.(源文件如任何那IMPORT_IDENTIFIER那envPath)){背景。日志记录器。信息('✅️环境已经在根模块中导入了');返回树;}常量更改=IslessImport.(源文件如任何那AppModulepath.那IMPORT_IDENTIFIER那envPath。取代(/ \\.TS$ /那''))如insertchange.;常量录音机=树。beginUpdate(AppModulepath.);录音机。insertLeft(更改。pos那更改。toAdd);树。commitupdate.(录音机);背景。日志记录器。信息('✅️导入环境到根模块');返回树;};}
就让我们一探究竟吧:
- 我们将使用一些熟悉的函数来获取关于我们正在其中执行原理图的工作空间和项目的信息。
- 该
getAppModulePath()
对象的路径字符串app.module.tsAngular项目中的文件(lib或app)。 - 使用环境文件和根应用程序模块的信息,我们已经准备好将es6 import语句插入app.module.ts文件。
- 我们首先验证
环境
标识符还没有导入到模块中。如果是,那我们就玩完了。 - 否则,我们需要插入导入。我们将使用它
Insterimport()
函数导出到@angular /图表模块要创建一个新的insertchange.
目的。 - 使用
更改
我们使用的对象启动并提交更新到应用程序模块文件updateRecOrder.
。
导入模块
最后一步是更新@NgModule ()
装饰的appmodule.
导入Firebase模块。
开放src / setup-project.ts和实现addAngularFireModule ()
功能:
功能addAngularFireModule(选项:模式):规则{返回(树:树那背景:示意图)= >{常量MODULE_NAME='AngularFireModule.InitializeApp(环境.Firebase)';常量工作空间=getWorkspace.(树);常量项目=getProjectFromWorkspace(工作空间那选项。项目);常量AppModulepath.=getAppModulepath.(树那getProjectMainFile(项目));//验证模块还没有被导入如果(hasngmoduleimport.(树那AppModulepath.那MODULE_NAME)){返回安慰。警告(红(`无法进口"$ {大胆的(MODULE_NAME)}“因为”$ {大胆的(MODULE_NAME)}已经被引进了。`));}//将ngmodule添加到root ngmodule导入addmoduleimporttorootmodule.(树那MODULE_NAME那'@角/火'那项目);背景。日志记录器。信息('✅️将AngularFireModule进入根模块');返回树;};}
让我们回顾一下:
- 再次,您将注意到,我们正在使用多个实用程序函数来访问工作区和项目的元数据,然后使用此,我们得到的路径app.module.ts文件。
- 首先,我们验证模块是否未使用alredy使用
hasngmoduleimport()
函数。这张是我从@angular / cdk模块,位于原理图/ Utils / AST目录中。 - 然后我们援引
addModuleImportToRootModule ()
命令功能将Firebase模块导入到@NgModule ()
装饰师进口
阵列。
结论
我希望这篇文章对那些有兴趣学习如何为自己的项目或组织构建图表,或者为Angular社区做出贡献的人有所帮助。
我在几个聚会上提出了建筑角度的原理图,我被提出的一个常见问题是:
“你怎么知道在哪里找到这些实用程序功能?”
通过研究这一点角征那角度的材料和角CDK.示意图我了解了这些团队使用的许多实用程序函数来构建原理图。我建议您查看这些原理图的源代码,以帮助您了解如何构建原理图并发现它们提供和使用的许多实用程序功能。