• ng Schematics


    Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.

    什么是Angular Schematics

    Angular Schematics 是基于模板(Template-based)的,Angular 特有的代码生成器,当然它不仅仅是生成代码

    • 安装

      npm install -g @angular-devkit/schematics-cli
      
    • 创建项目

      1. // 安装完成之后新建一个schematics项目
      2. schematics blank --name=ng-schematics
      1. ng-schematics
      2. ┣ src
      3. ┃ ┣ ng-schematics
      4. ┃ ┃ ┣ index.ts
      5. ┃ ┃ ┗ index_spec.ts
      6. ┃ ┗ collection.json // 定义你的相关命令
      7. ┣ .gitignore
      8. ┣ .npmignore
      9. ┣ README.md
      10. ┣ package-lock.json
      11. ┣ package.json
      12. ┗ tsconfig.json // 主要与项目打包编译相关

      collection.json

      1. {
      2. "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
      3. "schematics": {
      4. "ng-schematics": { // 命令的名字 ng g ng-schematics:ng-schematics
      5. "description": "A blank schematic.", // 对该条命令的描述
      6. "factory": "./ng-schematics/index#ngSchematics" // 命令执行的入口函数
      7. }
      8. }
      9. }

      index.ts

      1. import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
      2. // You don't have to export the function as default. You can also have more than one rule factory
      3. // per file.
      4. export function ngSchematics(_options: any): Rule {
      5. return (tree: Tree, _context: SchematicContext) => {
      6. return tree;
      7. };
      8. }
      9. // tree:在这里你可以将 tree 理解为我们整个的 angular 项目,你可以通过 tree 新增文件,修改文件,以及删除文件。
      10. // _context:该参数为 schematics 运行的上下文,比如你可以通过 context 执行 npm install。
      11. // Rule:为我们制定的操作逻辑。
    • 新增ng-add指令

      1. ng-add
      2. ┣ files
      3. ┃ ┣ app.component.html.template
      4. ┃ ┣ app.component.scss.template
      5. ┃ ┗ app.component.ts.template
      6. ┣ index.ts
      7. ┣ schema.json
      8. ┗ schema.ts
      1. // app.component.html.template
      2. <div class="my-app">
      3. <% if (defaultLanguage === 'zh-cn') { %>你好,Angular Schematics!<% } else { %>Hello, My First Angular Schematics!<% } %>
      4. <h1>{{ title }}</h1>
      5. </div>
      1. // app.component.scss.template
      2. .app {
      3. display: flex;
      4. justify-content: center;
      5. align-items: center;
      6. }
      1. // app.component.ts.template
      2. import { Component } from '@angular/core';
      3. @Component({
      4. selector: 'app-root',
      5. templateUrl: './app.component.html',
      6. styleUrls: ['./app.component.scss']
      7. })
      8. export class AppComponent {
      9. title = <% if (defaultLanguage === 'zh-cn') { %>'你好'<% } else { %>'Hello'<% } %>;
      10. }
      1. // schema.json:在该文件中定义与用户的交互
      2. {
      3. "$schema": "",
      4. "id": "SchematicsDevUI",
      5. "title": "DevUI Options Schema",
      6. "type": "object",
      7. "properties": {
      8. "defaultLanguage": {
      9. "type": "string",
      10. "description": "Choose the default language",
      11. "default": "zh-cn",
      12. "x-prompt": {
      13. "message": "Please choose the default language you want to use: ",
      14. "type": "list",
      15. "items": [
      16. {
      17. "value": "zh-cn",
      18. "label": "简体中文 (zh-ch)"
      19. },
      20. {
      21. "value": "en-us",
      22. "label": "English (en-us)"
      23. }
      24. ]
      25. }
      26. },
      27. "i18n": {
      28. "type": "boolean",
      29. "default": true,
      30. "description": "Config i18n for the project",
      31. "x-prompt": "Would you like to add i18n? (default: Y)"
      32. }
      33. },
      34. "required": []
      35. }
      36. // 命令将会接收两个参数分别为 defaultLanguage,i18n
      37. // defaultLanguage
      38. // type 代表该参数的类型是 string
      39. // default 为该参数的默认值为 zh-cn。
      40. // x-prompt 定义与用户的交互,message 为我们对用户进行的相关提问,在这里我们的 type 为 list 代表我们会为用户提供 items 中列出的选项供用户进行选择。
      1. // schema.ts:在该文件中定义我们接收到的参数类型
      2. export interface Schema {
      3. defaultLanguage: string;
      4. i18n: boolean;
      5. }
      1. // index.ts:在该文件中实现我们的操作逻辑,假设在此次 ng-add 操作中,
      2. // 我们根据用户输入的 defaultLanguage, i18n 来对用户的项目进行相应的更改,并且插入相关的 npm 包,再进行安装。
      3. import { apply, applyTemplates, chain, mergeWith, move, Rule, SchematicContext, SchematicsException, Tree, url } from '@angular-devkit/schematics';
      4. import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
      5. import { Schema as AddOptions } from './schema';
      6. let projectWorkspace: {
      7. root: string;
      8. sourceRoot: string;
      9. defaultProject: string;
      10. };
      11. export type packgeType = 'dependencies' | 'devDependencies' | 'scripts';
      12. export const PACKAGES_I18N = ['@devui-design/icons@^1.2.0', '@ngx-translate/core@^13.0.0', '@ngx-translate/http-loader@^6.0.0', 'ng-devui@^11.1.0'];
      13. export const PACKAGES = ['@devui-design/icons@^1.2.0', 'ng-devui@^11.1.0'];
      14. export const PACKAGE_JSON_PATH = 'package.json';
      15. export const ANGULAR_JSON_PATH = 'angular.json';
      16. export default function (options: AddOptions): Rule {
      17. return (tree: Tree, context: SchematicContext) => {
      18. // 获取项目空间中我们需要的相关变量
      19. getWorkSpace(tree);
      20. // 根据是否选择i18n插入不同的packages
      21. const packages = options.i18n ? PACKAGES_I18N : PACKAGES;
      22. addPackage(tree, packages, 'dependencies');
      23. // 执行 npm install
      24. context.addTask(new NodePackageInstallTask());
      25. // 自定义的一系列 Rules
      26. return chain([removeOriginalFiles(), addSourceFiles(options)]);
      27. };
      28. }
      29. // getWorkSpace
      30. function getWorkSpace(tree: Tree) {
      31. let angularJSON;
      32. let buffer = tree.read(ANGULAR_JSON_PATH);
      33. if (buffer) {
      34. angularJSON = JSON.parse(buffer.toString());
      35. } else {
      36. throw new SchematicsException('Please make sure the project is an Angular project.');
      37. }
      38. let defaultProject = angularJSON.defaultProject;
      39. projectWorkspace = {
      40. root: '/',
      41. sourceRoot: angularJSON.projects[defaultProject].sourceRoot,
      42. defaultProject,
      43. };
      44. return projectWorkspace;
      45. }
      46. // removeOriginalFiles
      47. // 根据自己的需要选择需要删除的文件
      48. function removeOriginalFiles() {
      49. return (tree: Tree) => {
      50. [
      51. `${projectWorkspace.sourceRoot}/app/app.component.ts`,
      52. `${projectWorkspace.sourceRoot}/app/app.component.html`,
      53. `${projectWorkspace.sourceRoot}/app/app.component.scss`,
      54. `${projectWorkspace.sourceRoot}/app/app.component.css`,
      55. ]
      56. .filter((f) => tree.exists(f))
      57. .forEach((f) => tree.delete(f));
      58. };
      59. }
      60. // 将 files 下的文件拷贝到指定的路径下,chain, mergeWith, apply, template 的详细使用方法可以参考 Schematics
      61. // addSourceFiles
      62. function addSourceFiles(options: AddOptions): Rule {
      63. return chain([
      64. mergeWith(
      65. apply(url('./files'), [
      66. applyTemplates({
      67. defaultLanguage: options.defaultLanguage,
      68. }),
      69. move(`${projectWorkspace.sourceRoot}/app`),
      70. ])
      71. ),
      72. ]);
      73. }
      74. // readJson
      75. function readJson(tree: Tree, file: string, type?: string): any {
      76. if (!tree.exists(file)) {
      77. return null;
      78. }
      79. const sourceFile = tree.read(file)!.toString('utf-8');
      80. try {
      81. const json = JSON.parse(sourceFile);
      82. if (type && !json[type]) {
      83. json[type] = {};
      84. }
      85. return json;
      86. } catch (error) {
      87. console.log(`Failed when parsing file ${file}.`);
      88. throw error;
      89. }
      90. }
      91. // writeJson
      92. export function writeJson(tree: Tree, file: string, source: any): void {
      93. tree.overwrite(file, JSON.stringify(source, null, 2));
      94. }
      95. // readPackageJson
      96. function readPackageJson(tree: Tree, type?: string): any {
      97. return readJson(tree, PACKAGE_JSON_PATH, type);
      98. }
      99. // writePackageJson
      100. function writePackageJson(tree: Tree, json: any): any {
      101. return writeJson(tree, PACKAGE_JSON_PATH, json);
      102. }
      103. // addPackage
      104. function addPackage(tree: Tree, packages: string | string[], type: packgeType = 'dependencies'): Tree {
      105. const packageJson = readPackageJson(tree, type);
      106. if (packageJson == null) {
      107. return tree;
      108. }
      109. if (!Array.isArray(packages)) {
      110. packages = [packages];
      111. }
      112. packages.forEach((pck) => {
      113. const splitPosition = pck.lastIndexOf('@');
      114. packageJson[type][pck.substr(0, splitPosition)] = pck.substr(splitPosition + 1);
      115. });
      116. writePackageJson(tree, packageJson);
      117. return tree;
      118. }
    • 测试

      1. ng new name // 新建ng项目
      2. npm link schematics // link到schematics项目
      3. npm bulid // schematics项目bulid
      ng add ng-schematics
      

    EJS

    GitHub - SeriousLose/schematics-study

    Schematics的介绍

    NG Schematics

  • 相关阅读:
    # 02 初识Verilog HDL
    17_c/c++开源库 easylogging日志库
    算法笔试ACM模式如何输入
    JMeter分布式压测及4种参数化方式,转发收藏
    【牛客】SQL139 近三个月未完成试卷数为0的用户完成情况-窗口函数
    SPFA算法详解
    java计算机毕业设计ssm信息科技知识交流学习平台
    二维码解码文字或者链接怎么做?二维码分解内容的方法
    SpringCloud笔记之Rest环境搭建
    Acwing 907. 区间覆盖
  • 原文地址:https://blog.csdn.net/SeriousLose/article/details/128087362