如何通过Angular脚手架完成从零到一的全流程项目开发?

2026-04-09 03:491阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1467个文字,预计阅读时间需要6分钟。

如何通过Angular脚手架完成从零到一的全流程项目开发?

简介:撰写一篇关于自定义Angular脚手架的文章。在撰写之前,我们先解析一下antd的脚手架。首先,先提出antd,再提及。先阅读Angular+Schematic这篇文章,确保理解了collection等基础知识。克隆antd项目:git clone https://github.com/N

简介

写一份自定义的angular脚手架吧
写之前我们先解析一下antd的脚手架

前提

先把 Angular Schematic这篇文章读一遍,确保了解了collection等基础

antd脚手架

克隆项目

git clone github.com/NG-ZORRO/ng-zorro-antd.git

开始

打开项目

在schematics下的collection.json为入口,查看内容

一共定了了4个schematic,每个schema分别指向了各文件夹的子schema.json,factory指向了函数入口,index.ts

ng-add/schema.json

如何通过Angular脚手架完成从零到一的全流程项目开发?

{ // 指定schema.json的验证模式 "$schema": "json-schema.org/schema", "id": "nz-ng-add", "title": "Ant Design of Angular(NG-ZORRO) ng-add schematic", "type": "object", // 包含的属性 "properties": { "project": { "type": "string", "description": "Name of the project.", "$default": { "$source": "projectName" } }, // 是否跳过package.json的安装属性 "skipPackageJson": { // 类型为布尔 "type": "boolean", // 默认值为false "default": false, // 这是个描述,可以看到,如果在ng add ng-zorro-antd时不希望自动安装可以加入--skipPackageJson配置项 "description": "Do not add ng-zorro-antd dependencies to package.json (e.g., --skipPackageJson)" }, // 开始页面 "bootPage": { // 布尔 "type": "boolean", // 默认为true "default": true, // 不指定--bootPage=false的话,你的app.html将会被覆盖成antd的图标页 "description": "Set up boot page." }, // 图标配置 "dynamicIcon": { "type": "boolean", "default": false, "description": "Whether icon assets should be add.", "x-prompt": "Add icon assets [ Detail: ng.ant.design/components/icon/en ]" }, // 主题配置 "theme": { "type": "boolean", "default": false, "description": "Whether custom theme file should be set up.", "x-prompt": "Set up custom theme file [ Detail: ng.ant.design/docs/customize-theme/en ]" }, // i18n配置,当你ng add ng-antd-zorro 的时候有没有让你选择这个选项呢? "i18n": { "type": "string", "default": "en_US", "enum": [ "ar_EG", "bg_BG", "ca_ES", "cs_CZ", "da_DK", "de_DE", "el_GR", "en_GB", "en_US", "es_ES", "et_EE", "fa_IR", "fi_FI", "fr_BE", "fr_FR", "is_IS", "it_IT", "ja_JP", "ko_KR", "nb_NO", "nl_BE", "nl_NL", "pl_PL", "pt_BR", "pt_PT", "sk_SK", "sr_RS", "sv_SE", "th_TH", "tr_TR", "ru_RU", "uk_UA", "vi_VN", "zh_CN", "zh_TW" ], "description": "add locale code to module (e.g., --locale=en_US)" }, "locale": { "type": "string", "description": "Add locale code to module (e.g., --locale=en_US)", "default": "en_US", "x-prompt": { "message": "Choose your locale code:", "type": "list", "items": [ "en_US", "zh_CN", "ar_EG", "bg_BG", "ca_ES", "cs_CZ", "de_DE", "el_GR", "en_GB", "es_ES", "et_EE", "fa_IR", "fi_FI", "fr_BE", "fr_FR", "is_IS", "it_IT", "ja_JP", "ko_KR", "nb_NO", "nl_BE", "nl_NL", "pl_PL", "pt_BR", "pt_PT", "sk_SK", "sr_RS", "sv_SE", "th_TH", "tr_TR", "ru_RU", "uk_UA", "vi_VN", "zh_TW" ] } }, "gestures": { "type": "boolean", "default": false, "description": "Whether gesture support should be set up." }, "animations": { "type": "boolean", "default": true, "description": "Whether Angular browser animations should be set up." } }, "required": [] }

schema.ts

当你进入index.ts时首先看到的是一个带options:Schema的函数,options指向的类型是Schema interface,而这个interface 恰好是schema.json中的properties,也就是cli的传入参数类.

我们可以通过自定义传入参数类来完成我们需要的操作.

export type Locale = | 'ar_EG' | 'bg_BG' | 'ca_ES' | 'cs_CZ' | 'da_DK' | 'de_DE' | 'el_GR' | 'en_GB' | 'en_US' | 'es_ES' | 'et_EE' | 'fa_IR' | 'fi_FI' | 'fr_BE' | 'fr_FR' | 'is_IS' | 'it_IT' | 'ja_JP' | 'ko_KR' | 'nb_NO' | 'nl_BE' | 'nl_NL' | 'pl_PL' | 'pt_BR' | 'pt_PT' | 'sk_SK' | 'sr_RS' | 'sv_SE' | 'th_TH' | 'tr_TR' | 'ru_RU' | 'uk_UA' | 'vi_VN' | 'zh_CN' | 'zh_TW'; export interface Schema { bootPage?: boolean; /** Name of the project to target. */ project?: string; /** Whether to skip package.json install. */ skipPackageJson?: boolean; dynamicIcon?: boolean; theme?: boolean; gestures?: boolean; animations?: boolean; locale?: Locale; i18n?: Locale; }

ng-add/index.ts

import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; import { NodePackageInstallTask, RunSchematicTask } from '@angular-devkit/schematics/tasks'; import { addPackageToPackageJson } from '../utils/package-config'; import { hammerjsVersion, zorroVersion } from '../utils/version-names'; import { Schema } from './schema'; // factory指向的index.ts必须实现这个函数,一行一行看代码 // 我们的函数是一个更高阶的函数,这意味着它接受或返回一个函数引用。 // 在这种情况下,我们的函数返回一个接受Tree和SchematicContext对象的函数。 // options:Schema上面提到了 export default function(options: Schema): Rule { // tree:虚拟文件系统:用于更改的暂存区域,包含原始文件系统以及要应用于其的更改列表。 // rule:A Rule是一个将动作应用于Tree给定的函数SchematicContext。 return (host: Tree, context: SchematicContext) => { // 如果需要安装包,也就是--skipPackageJson=false if (!options.skipPackageJson) { // 调用addPackageToPackageJson,传入,tree文件树,包名,包版本 addPackageToPackageJson(host, 'ng-zorro-antd', zorroVersion); // hmr模式包 if (options.gestures) { addPackageToPackageJson(host, 'hammerjs', hammerjsVersion); } } const installTaskId = context.addTask(new NodePackageInstallTask()); context.addTask(new RunSchematicTask('ng-add-setup-project', options), [installTaskId]); if (options.bootPage) { context.addTask(new RunSchematicTask('boot-page', options)); } }; }

addPackageToPackageJson

// 看function名字就知道这是下载依赖的函数 // @host:Tree 文件树 // @pkg:string 包名 // @vserion:string 包版本 // @return Tree 返回了一个修改完成后的文件树 export function addPackageToPackageJson(host: Tree, pkg: string, version: string): Tree { // 如果文件树里包含package.json文件 if (host.exists('package.json')) { // 读取package.json的内容用utf-8编码 const sourceText = host.read('package.json').toString('utf-8'); // 然后把package.json转化为对象,转为对象,转为对象 const json = JSON.parse(sourceText); // 如果package.json对象里没有dependencies属性 if (!json.dependencies) { // 给package对象加入dependencies属性 json.dependencies = {}; } // 如果package对象中没有 pkg(包名),也就是说:如果当前项目没有安装antd if (!json.dependencies[pkg]) { // 那么package的dependencies属性中加入 antd:version json.dependencies[pkg] = version; // 排个序 json.dependencies = sortObjectByKeys(json.dependencies); } // 重写tree下的package.json内容为(刚才不是有package.json对象吗,现在在转回去) host.overwrite('package.json', JSON.stringify(json, null, 2)); } // 把操作好的tree返回给上一级函数 return host; }

现在在回过头去看 ng-add/index.ts

// 给context对象增加一个安装包的任务,然后拿到了任务id const installTaskId = context.addTask(new NodePackageInstallTask()); // context增加另一个任务,然后传入了一个RunSchematicTask对象,和一个id集合 context.addTask(new RunSchematicTask('ng-add-setup-project', options), [installTaskId]);

RunSchematicTask('ng-add-setup-project')

任务ng-add-setup-project定义在了schematic最外层的collection.json里,记住如下4个schematic,后文不再提及

{ "$schema": "./node_modules/@angular-devkit/schematics/collection-schema.json", "schematics": { "ng-add": { "description": "add NG-ZORRO", "factory": "./ng-add/index", "schema": "./ng-add/schema.json" }, // 在这里 "ng-add-setup-project": { "description": "Sets up the specified project after the ng-add dependencies have been installed.", "private": true, // 这个任务的函数指向 "factory": "./ng-add/setup-project/index", // 任务配置项 "schema": "./ng-add/schema.json" }, "boot-page": { "description": "Set up boot page", "private": true, "factory": "./ng-generate/boot-page/index", "schema": "./ng-generate/boot-page/schema.json" }, "add-icon-assets": { "description": "Add icon assets into CLI config", "factory": "./ng-add/setup-project/add-icon-assets#addIconToAssets", "schema": "./ng-generate/boot-page/schema.json", "aliases": ["fix-icon"] } } }

ng-add/setup-project

// 刚才的index一样,实现了一个函数 export default function (options: Schema): Rule { // 这里其实就是调用各种函数的一个集合.options是上面的index.ts中传过来的,配置项在上文有提及 return chain([ addRequiredModules(options), addAnimationsModule(options), registerLocale(options), addThemeToAppStyles(options), options.dynamicIcon ? addIconToAssets(options) : noop(), options.gestures ? hammerjsImport(options) : noop() ]); }

addRequiredModules

// 模块字典 const modulesMap = { NgZorroAntdModule: 'ng-zorro-antd', FormsModule : '@angular/forms', HttpClientModule : '@angular/common/www.kevinschuchard.com/blog/2018-07-17-jest-schematic/
Schematic:brianflove.com/2018/12/11/angular-schematics-tutorial/
Ng add:brianflove.com/2018/12/15/ng-add-schematic/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。

本文共计1467个文字,预计阅读时间需要6分钟。

如何通过Angular脚手架完成从零到一的全流程项目开发?

简介:撰写一篇关于自定义Angular脚手架的文章。在撰写之前,我们先解析一下antd的脚手架。首先,先提出antd,再提及。先阅读Angular+Schematic这篇文章,确保理解了collection等基础知识。克隆antd项目:git clone https://github.com/N

简介

写一份自定义的angular脚手架吧
写之前我们先解析一下antd的脚手架

前提

先把 Angular Schematic这篇文章读一遍,确保了解了collection等基础

antd脚手架

克隆项目

git clone github.com/NG-ZORRO/ng-zorro-antd.git

开始

打开项目

在schematics下的collection.json为入口,查看内容

一共定了了4个schematic,每个schema分别指向了各文件夹的子schema.json,factory指向了函数入口,index.ts

ng-add/schema.json

如何通过Angular脚手架完成从零到一的全流程项目开发?

{ // 指定schema.json的验证模式 "$schema": "json-schema.org/schema", "id": "nz-ng-add", "title": "Ant Design of Angular(NG-ZORRO) ng-add schematic", "type": "object", // 包含的属性 "properties": { "project": { "type": "string", "description": "Name of the project.", "$default": { "$source": "projectName" } }, // 是否跳过package.json的安装属性 "skipPackageJson": { // 类型为布尔 "type": "boolean", // 默认值为false "default": false, // 这是个描述,可以看到,如果在ng add ng-zorro-antd时不希望自动安装可以加入--skipPackageJson配置项 "description": "Do not add ng-zorro-antd dependencies to package.json (e.g., --skipPackageJson)" }, // 开始页面 "bootPage": { // 布尔 "type": "boolean", // 默认为true "default": true, // 不指定--bootPage=false的话,你的app.html将会被覆盖成antd的图标页 "description": "Set up boot page." }, // 图标配置 "dynamicIcon": { "type": "boolean", "default": false, "description": "Whether icon assets should be add.", "x-prompt": "Add icon assets [ Detail: ng.ant.design/components/icon/en ]" }, // 主题配置 "theme": { "type": "boolean", "default": false, "description": "Whether custom theme file should be set up.", "x-prompt": "Set up custom theme file [ Detail: ng.ant.design/docs/customize-theme/en ]" }, // i18n配置,当你ng add ng-antd-zorro 的时候有没有让你选择这个选项呢? "i18n": { "type": "string", "default": "en_US", "enum": [ "ar_EG", "bg_BG", "ca_ES", "cs_CZ", "da_DK", "de_DE", "el_GR", "en_GB", "en_US", "es_ES", "et_EE", "fa_IR", "fi_FI", "fr_BE", "fr_FR", "is_IS", "it_IT", "ja_JP", "ko_KR", "nb_NO", "nl_BE", "nl_NL", "pl_PL", "pt_BR", "pt_PT", "sk_SK", "sr_RS", "sv_SE", "th_TH", "tr_TR", "ru_RU", "uk_UA", "vi_VN", "zh_CN", "zh_TW" ], "description": "add locale code to module (e.g., --locale=en_US)" }, "locale": { "type": "string", "description": "Add locale code to module (e.g., --locale=en_US)", "default": "en_US", "x-prompt": { "message": "Choose your locale code:", "type": "list", "items": [ "en_US", "zh_CN", "ar_EG", "bg_BG", "ca_ES", "cs_CZ", "de_DE", "el_GR", "en_GB", "es_ES", "et_EE", "fa_IR", "fi_FI", "fr_BE", "fr_FR", "is_IS", "it_IT", "ja_JP", "ko_KR", "nb_NO", "nl_BE", "nl_NL", "pl_PL", "pt_BR", "pt_PT", "sk_SK", "sr_RS", "sv_SE", "th_TH", "tr_TR", "ru_RU", "uk_UA", "vi_VN", "zh_TW" ] } }, "gestures": { "type": "boolean", "default": false, "description": "Whether gesture support should be set up." }, "animations": { "type": "boolean", "default": true, "description": "Whether Angular browser animations should be set up." } }, "required": [] }

schema.ts

当你进入index.ts时首先看到的是一个带options:Schema的函数,options指向的类型是Schema interface,而这个interface 恰好是schema.json中的properties,也就是cli的传入参数类.

我们可以通过自定义传入参数类来完成我们需要的操作.

export type Locale = | 'ar_EG' | 'bg_BG' | 'ca_ES' | 'cs_CZ' | 'da_DK' | 'de_DE' | 'el_GR' | 'en_GB' | 'en_US' | 'es_ES' | 'et_EE' | 'fa_IR' | 'fi_FI' | 'fr_BE' | 'fr_FR' | 'is_IS' | 'it_IT' | 'ja_JP' | 'ko_KR' | 'nb_NO' | 'nl_BE' | 'nl_NL' | 'pl_PL' | 'pt_BR' | 'pt_PT' | 'sk_SK' | 'sr_RS' | 'sv_SE' | 'th_TH' | 'tr_TR' | 'ru_RU' | 'uk_UA' | 'vi_VN' | 'zh_CN' | 'zh_TW'; export interface Schema { bootPage?: boolean; /** Name of the project to target. */ project?: string; /** Whether to skip package.json install. */ skipPackageJson?: boolean; dynamicIcon?: boolean; theme?: boolean; gestures?: boolean; animations?: boolean; locale?: Locale; i18n?: Locale; }

ng-add/index.ts

import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; import { NodePackageInstallTask, RunSchematicTask } from '@angular-devkit/schematics/tasks'; import { addPackageToPackageJson } from '../utils/package-config'; import { hammerjsVersion, zorroVersion } from '../utils/version-names'; import { Schema } from './schema'; // factory指向的index.ts必须实现这个函数,一行一行看代码 // 我们的函数是一个更高阶的函数,这意味着它接受或返回一个函数引用。 // 在这种情况下,我们的函数返回一个接受Tree和SchematicContext对象的函数。 // options:Schema上面提到了 export default function(options: Schema): Rule { // tree:虚拟文件系统:用于更改的暂存区域,包含原始文件系统以及要应用于其的更改列表。 // rule:A Rule是一个将动作应用于Tree给定的函数SchematicContext。 return (host: Tree, context: SchematicContext) => { // 如果需要安装包,也就是--skipPackageJson=false if (!options.skipPackageJson) { // 调用addPackageToPackageJson,传入,tree文件树,包名,包版本 addPackageToPackageJson(host, 'ng-zorro-antd', zorroVersion); // hmr模式包 if (options.gestures) { addPackageToPackageJson(host, 'hammerjs', hammerjsVersion); } } const installTaskId = context.addTask(new NodePackageInstallTask()); context.addTask(new RunSchematicTask('ng-add-setup-project', options), [installTaskId]); if (options.bootPage) { context.addTask(new RunSchematicTask('boot-page', options)); } }; }

addPackageToPackageJson

// 看function名字就知道这是下载依赖的函数 // @host:Tree 文件树 // @pkg:string 包名 // @vserion:string 包版本 // @return Tree 返回了一个修改完成后的文件树 export function addPackageToPackageJson(host: Tree, pkg: string, version: string): Tree { // 如果文件树里包含package.json文件 if (host.exists('package.json')) { // 读取package.json的内容用utf-8编码 const sourceText = host.read('package.json').toString('utf-8'); // 然后把package.json转化为对象,转为对象,转为对象 const json = JSON.parse(sourceText); // 如果package.json对象里没有dependencies属性 if (!json.dependencies) { // 给package对象加入dependencies属性 json.dependencies = {}; } // 如果package对象中没有 pkg(包名),也就是说:如果当前项目没有安装antd if (!json.dependencies[pkg]) { // 那么package的dependencies属性中加入 antd:version json.dependencies[pkg] = version; // 排个序 json.dependencies = sortObjectByKeys(json.dependencies); } // 重写tree下的package.json内容为(刚才不是有package.json对象吗,现在在转回去) host.overwrite('package.json', JSON.stringify(json, null, 2)); } // 把操作好的tree返回给上一级函数 return host; }

现在在回过头去看 ng-add/index.ts

// 给context对象增加一个安装包的任务,然后拿到了任务id const installTaskId = context.addTask(new NodePackageInstallTask()); // context增加另一个任务,然后传入了一个RunSchematicTask对象,和一个id集合 context.addTask(new RunSchematicTask('ng-add-setup-project', options), [installTaskId]);

RunSchematicTask('ng-add-setup-project')

任务ng-add-setup-project定义在了schematic最外层的collection.json里,记住如下4个schematic,后文不再提及

{ "$schema": "./node_modules/@angular-devkit/schematics/collection-schema.json", "schematics": { "ng-add": { "description": "add NG-ZORRO", "factory": "./ng-add/index", "schema": "./ng-add/schema.json" }, // 在这里 "ng-add-setup-project": { "description": "Sets up the specified project after the ng-add dependencies have been installed.", "private": true, // 这个任务的函数指向 "factory": "./ng-add/setup-project/index", // 任务配置项 "schema": "./ng-add/schema.json" }, "boot-page": { "description": "Set up boot page", "private": true, "factory": "./ng-generate/boot-page/index", "schema": "./ng-generate/boot-page/schema.json" }, "add-icon-assets": { "description": "Add icon assets into CLI config", "factory": "./ng-add/setup-project/add-icon-assets#addIconToAssets", "schema": "./ng-generate/boot-page/schema.json", "aliases": ["fix-icon"] } } }

ng-add/setup-project

// 刚才的index一样,实现了一个函数 export default function (options: Schema): Rule { // 这里其实就是调用各种函数的一个集合.options是上面的index.ts中传过来的,配置项在上文有提及 return chain([ addRequiredModules(options), addAnimationsModule(options), registerLocale(options), addThemeToAppStyles(options), options.dynamicIcon ? addIconToAssets(options) : noop(), options.gestures ? hammerjsImport(options) : noop() ]); }

addRequiredModules

// 模块字典 const modulesMap = { NgZorroAntdModule: 'ng-zorro-antd', FormsModule : '@angular/forms', HttpClientModule : '@angular/common/www.kevinschuchard.com/blog/2018-07-17-jest-schematic/
Schematic:brianflove.com/2018/12/11/angular-schematics-tutorial/
Ng add:brianflove.com/2018/12/15/ng-add-schematic/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。