关于angular2:Angular单运行时多项目共享依赖方案

ngx-center一个核心,多个...... 应用介绍(视频) 这是什么?一个 Angular 单运行时多我的项目共享依赖的解决方案只启动一个 Angular 平台(PlatformRef),其余子项目进行导出(类 es6 module),通过资源文件清单(或独自 js 文件)进行申请加载性能反对子项目在开发时代码变更的刷新反对子项目调用主我的项目导出的命名(export * from 'xxx')反对子项目及主我的项目的 splitChunks(包含懒加载等...)反对懒加载路由的子项目申请及其他动静模块的申请反对可信的近程子项目开发不须要理解各种概念,因为导出导入解决齐全遵循动静import的类解决计划子模块构建速度极快,且在大多数工夫不须要向 node 申请内存实践上子项目同时能够加载子项目,也就是能够存在多层级子项目的加载能够通过子项目嵌套其余框架反对的调用通过在编译时构建形成关系,对源代码无侵入性,不须要过多革新依赖Angular10 Angular11 Angular12node12+原理依赖共享也就是node_modules中的依赖变成 dll(动态链接库),主,子利用都应用这个 dll 保障实例的一致性命名共享主我的项目的命名会导出,供子项目用,实现子项目调用主我的项目的组件/模块/服务/管道等 ng 与非 ng 的导出子项目资源启动主我的项目通过启动子我的项目的资源文件/资源配置,来加载子项目资源,并且在加载后实现主动取得子项目的导出,能够作为懒加载路由,懒加载模块等动静应用的中央调用应用办法本我的项目依赖的是 Angular 的ng generate命令,疾速生成开发骨架相干插件可在在webpack-ng-dll-plugin,'webpack-bootstrap-assets-plugin查看,或者可手动配置文件倡议先在新我的项目中应用,待理解实现后,再应用到已有我的项目中主我的项目初始化运行npx ng g ngx-center:main-init配置/** * 主我的项目初始化 */declare interface MainInitSchematics { /** * 链接库(lib)名称,默认dll */ dllName?: string; /** * 主我的项目的名字(为空读取默认值) */ projectName?: string; /** * 应用裸露webpack配置的形式(交互) */ webpackMode?: string; /** * 将webpack晋升到根依赖(yarn会默认晋升) */ webpackPromotion?: boolean;}除了webpackMode外,其余配置均为静默设置,除非应用-xxx yyy显式设置运行实现后,能够先执行npm run build:center-dll生成 dll 库,再运行npm run start:center-main启动主我的项目 ...

June 9, 2021 · 2 min · jiezi

关于angular2:在-Angular-项目中如何为项目单独创建路由文件

应用 Angular Cli 创立一个我的项目时,如果不加任何的后缀参数,那么生成的我的项目默认是没有路由模块的。那么,如何让创立的 Angular 我的项目有路由模块/路由文件呢? 两个方法: 1 在最开始创立我的项目的时候,带上参数: --routing=true|false 2 如果曾经创立好了我的项目,不想删除已有我的项目,从新创立我的项目的话,应用生成 module 的命令来创立路由文件,不过要加上一些参数: ng generate module app-routing --flat --module=app 其中:--flat 示意将生成的文件放到我的项目的顶层,而不是独自创立一个目录;—module=app 是通知 CLI 把创立的这个路由文件注册到 AppModule 根模块中,行将路由文件的类的名字放到 AppModule 的 imports 数组中。 参考:https://www.jianshu.com/p/7619ab2cadd7 https://angular.cn/cli/generate#module

March 1, 2021 · 1 min · jiezi

发布angualr2模块到npm社区

angualr2项目在本地正常运行后,有个公共模块部分我想抽离出来单独发布到npm上供项目使用,在网上找了些资料,没想到发不到npm比maven也省事的多,本文重点记录将自己的angualr2模块发布到npm的主要步骤。 一、注册账号在NPM网站注册一个账号,这个账号会被添加到npm本地的配置中,用来发布module用。 npm adduser Username: your namePassword: your passwordEmail: xxx@gmail.com二、登录账号npm loginUsername: fuzhutechPassword: fuzhutechEmail: (this IS public) fuzhutech@163.com三、查看当前用户npm whoami四、初始化项目npm init执行“npm init”可以根据提示生成简单的“package.json”,这个这个文件包含了module的所有信息,比如名称、版本、描述、依赖、作者、license等。npm init创建的“package.json”文件只包含了基本的信息,我使用angualr-cli命令创建项目,然后把“package.json”作比对,添加一些缺失的信息。 ng new ng2-fuzhutech-common五、版本管理npm社区版本号,语义版本号分为X.Y.Z三位,即主版号.次版号.修订号。当代码变更时,版本递增规则如下: 主版号:当你做了不相容的 API 修改,例如有大的变动,向下不兼容,需要更新X位; 次版号:当你做了向下相容的功能性新增,例如新增了功能,但是向下兼容,需要更新Y位; 修订号:当你做了向下相容的问题修正,例如只是修复bug,需要更新Z位; 先行版号及版本编译资讯可以加到「主版号.次版号.修订号」的后面,作为延伸。六、发布模块npm publish以上完成之后,我们终于可以发布自己的module了。 七、忽略文件.npmignore“.npmignore”文件用来定义哪些文件会被 npm 给忽略,npm 默认使用 gitignore 来忽略文件。存在 npmignore 的话 gitignore 的配置就会被覆盖。 八、安装模块npm install --save ng2-fuzhutech-common九、取消发布npm unpublish <package>@<version>已发布的版本号并不会被真正的取消,而是被占用,再次发布时需要更改新的版本号,而且npm只能允许撤销24小时以内的发布。

April 22, 2019 · 1 min · jiezi

Angular2+ 自定义Tree组件(参考Angular-material的CdkTree)

为了方便, 本文所有的Angular均表示Angula2及以上版本,对于使用Angular1/Angular.js的读者可作为参考前言目前正在写一个Angular的Markdown编辑器,需要一个树形组件来写文件系统。刚好之前用过Angular Material的树形组件,就想照着写一个。毕竟直接把Angular Material引进来会多出其他用不到的组件,而且自己实现还能更深入学习Angular。介绍在写之前我百度了一通,发现大部分文章的Tree组件实现都是把节点模板直接写在了组件里,类似下面<!–Tree组件–><tree> <tree-node></tree-node></tree><!–TreeNode组件–><tree-node> <!–本节点内容–> {{ nodeName }} <!–子节点–> <tree-node *ngIf=“hasChildren”> </tree-node><tree-node>说明一下: Tree组件里面包含TreeNode组件,TreeNode组件内部实现了递归子节点的逻辑。 其实这样的结构已经足够满足我的需求了,但是(因为强迫症)这样的可重用性几乎是没有,因为节点的内容已经写死在TreeNode组件里了。 然后我想到了Angular Material的CdkTree。他的结构如下<tree dataSource=“ds”> <tree-node> <!–本节点内容–> {{ nodeName }} <!–子节点出口–> <outlet></outlet> </tree-node></tree>说明: 简单的说就是CdkTree把<tree-node>里的内容作为一个模板保存起来,然后根据数据源递归渲染出来。这样我们就可以在不修改Tree和TreeNode组件前提下改变其内容。实现在实现之前需要理解Angular的几个装饰器,学过Angular的应该都不会陌生。@ViewChild - 在视图中查询匹配的第一个元素@ViewChildren - 在视图中查询匹配的所有元素@ContentChild - 在组件标签包裹的内容中查询匹配的第一个元素@ContentChildren - 在组件标签包裹的内容中查询匹配的所有元素View和Content的区别 View: 在组件的模板中定义的内容,即我们手动写在xxx.component.html里的内容Content: 在Host元素的<opening>和<closeing>标签中的内容概览在Tree组件中有四个比较重要的类@Component: TreeComponent@Component: TreeNodeComponent@Directive: TreeNodeOutletDirective@Directive: TreeNodeDefDirectiveTreeComponent该组件就是我们要是实现的Tree组件,用于包裹TreeNodeTreeNodeComponent树节点组件,我们自定义的模板就写在这里面TreeNodeOutletDirective这个指令设置了子节点的出口位置TreeNodeDefDirective这个指令用来定义树节点所需的数据,即我们使用这个指令让模板可以使用每个树节点对应的数据实现我们先看一下完成后的样子<nb-tree [dataSource]=“fileTree”> <nb-tree-node *nbTreeNodeDef=“let data = data”> <li> <span>{{ data.title }}</span> </li> <ul> <ng-container nbTreeNodeOutlet></ng-container> </ul> </nb-tree-node></nb-tree>(标签前面的nb请忽略,这只是默认的前缀)上面是完成后的简易版。我们可以看到在tree组件上设置了dataSource。然后在treeNodeDef指令中我们导出了数据对象data。然后在模板中使用了它<span>{{ data.title }}</span>。最后我们在<ng-container>上用treeNodeOutlet指令设置了子节点的出口。懒得详细写实习了。。。有空再写吧。本文主要提供一个通用树形组件的思路。想看代码的,看结尾。有一个不是很完善的tree组件,我用在正在写的Markdown编辑器上了。结尾Github: tree组件链接

April 13, 2019 · 1 min · jiezi

angular2.0 笔记 - 02

angular2.0 笔记1.angular-cli 之 angular.json 配置表参数说明简单创建一个demo项目ng new project-demo{ “$schema”: “./node_modules/@angular/cli/lib/config/schema.json”, “version”: 1, “newProjectRoot”: “projects”, “projects”: { “project-demo”: { “root”: “”, “sourceRoot”: “src”, “projectType”: “application”, “prefix”: “app”, “schematics”: {}, “architect”: { “build”: {}, “serve”: {}, “extract-i18n”: {}, “test”: {}, “lint”: {} } }, “project-name-test”: { “root”: “”, “sourceRoot”: “src”, “projectType”: “application”, “prefix”: “app”, “schematics”: {}, “architect”: { “build”: {}, “serve”: {}, “extract-i18n”: {}, “test”: {}, “lint”: {} } } }, “defaultProject”: “project-demo”}上面的json是一个删除了部分内容的angular.json仅用于讲解使用,后面会给出完整json参数作用$schema关联了JSON Schema在angular CLI 的执行config.json文件version项目版本newProjectRoot这个属性定义了CLI创建的新的内部应用和库放置的位置,默认值为’projects’projects这个属性,个人觉得有必要认真讲一下。此属性包含了本项目中所有的子项目的配置信息。稍后单独拿这个属性详细讲解其注意点。defaultProject属性表示该项目的名字2.projects 下一级属性名 是子项目的名称子项目名称的作用,可以用于ng 命令执行 比如上面的json有一个子项目名字 project-name-test如果想单独运行某个子项目时,可以执行 ng serve project-name-test如果子项目不在projects内,执行 ng serve [project-name] 就会包一个错The serve command requires to be run in an Angular project, but a project definition could not be found.创建一个子项目,可以执行ng generate application project-name而且,每创建一个子项目,都会有一个[project-name]-e2e的子项目在projects里面3.projects 子项目 里面的 属性 说明属性作用root指定了子项目文件的根文件夹,可能是空值sourceRoot子项目源文件目录位置projectType子项目类型, application 或 libraryprefix创建子项目时,用这个属性来区分当前子项目是 component、directive、lib,或其他,当cli创建时会确定schematicsSchematics packages 配置(本人暂时还不知道其具体作用)architect此属性包含了项目的一些命令,比如 build/serve/test/lint 或者自定义命令 extract-i18n以上部分属性内容参考自Alfred的 angular.json参数详解项目例子 json{ “$schema”: “./node_modules/@angular/cli/lib/config/schema.json”, “version”: 1, “newProjectRoot”: “projects”, “projects”: { “project-demo”: { “root”: “”, “sourceRoot”: “src”, “projectType”: “application”, “prefix”: “app”, “schematics”: {}, “architect”: { “build”: { “builder”: “@angular-devkit/build-angular:browser”, “options”: { “outputPath”: “dist/project-demo”, “index”: “src/index.html”, “main”: “src/main.ts”, “polyfills”: “src/polyfills.ts”, “tsConfig”: “src/tsconfig.app.json”, “assets”: [ “src/favicon.ico”, “src/assets” ], “styles”: [ “src/styles.css” ], “scripts”: [], “es5BrowserSupport”: true }, “configurations”: { “production”: { “fileReplacements”: [ { “replace”: “src/environments/environment.ts”, “with”: “src/environments/environment.prod.ts” } ], “optimization”: true, “outputHashing”: “all”, “sourceMap”: false, “extractCss”: true, “namedChunks”: false, “aot”: true, “extractLicenses”: true, “vendorChunk”: false, “buildOptimizer”: true, “budgets”: [ { “type”: “initial”, “maximumWarning”: “2mb”, “maximumError”: “5mb” } ] } } }, “serve”: { “builder”: “@angular-devkit/build-angular:dev-server”, “options”: { “browserTarget”: “project-demo:build” }, “configurations”: { “production”: { “browserTarget”: “project-demo:build:production” } } }, “extract-i18n”: { “builder”: “@angular-devkit/build-angular:extract-i18n”, “options”: { “browserTarget”: “project-demo:build” } }, “test”: { “builder”: “@angular-devkit/build-angular:karma”, “options”: { “main”: “src/test.ts”, “polyfills”: “src/polyfills.ts”, “tsConfig”: “src/tsconfig.spec.json”, “karmaConfig”: “src/karma.conf.js”, “styles”: [ “src/styles.css” ], “scripts”: [], “assets”: [ “src/favicon.ico”, “src/assets” ] } }, “lint”: { “builder”: “@angular-devkit/build-angular:tslint”, “options”: { “tsConfig”: [ “src/tsconfig.app.json”, “src/tsconfig.spec.json” ], “exclude”: [ “/node_modules/” ] } } } }, “project-demo-e2e”: { “root”: “e2e/”, “projectType”: “application”, “prefix”: “”, “architect”: { “e2e”: { “builder”: “@angular-devkit/build-angular:protractor”, “options”: { “protractorConfig”: “e2e/protractor.conf.js”, “devServerTarget”: “project-demo:serve” }, “configurations”: { “production”: { “devServerTarget”: “project-demo:serve:production” } } }, “lint”: { “builder”: “@angular-devkit/build-angular:tslint”, “options”: { “tsConfig”: “e2e/tsconfig.e2e.json”, “exclude”: [ “/node_modules/” ] } } } }, “project-demo-two”: { “root”: “projects/project-demo-two/”, “sourceRoot”: “projects/project-demo-two/src”, “projectType”: “application”, “prefix”: “app”, “schematics”: {}, “architect”: { “build”: { “builder”: “@angular-devkit/build-angular:browser”, “options”: { “outputPath”: “dist/project-demo-two”, “index”: “projects/project-demo-two/src/index.html”, “main”: “projects/project-demo-two/src/main.ts”, “polyfills”: “projects/project-demo-two/src/polyfills.ts”, “tsConfig”: “projects/project-demo-two/tsconfig.app.json”, “assets”: [ “projects/project-demo-two/src/favicon.ico”, “projects/project-demo-two/src/assets” ], “styles”: [ “projects/project-demo-two/src/styles.css” ], “scripts”: [], “es5BrowserSupport”: true }, “configurations”: { “production”: { “fileReplacements”: [ { “replace”: “projects/project-demo-two/src/environments/environment.ts”, “with”: “projects/project-demo-two/src/environments/environment.prod.ts” } ], “optimization”: true, “outputHashing”: “all”, “sourceMap”: false, “extractCss”: true, “namedChunks”: false, “aot”: true, “extractLicenses”: true, “vendorChunk”: false, “buildOptimizer”: true, “budgets”: [ { “type”: “initial”, “maximumWarning”: “2mb”, “maximumError”: “5mb” } ] } } }, “serve”: { “builder”: “@angular-devkit/build-angular:dev-server”, “options”: { “browserTarget”: “project-demo-two:build” }, “configurations”: { “production”: { “browserTarget”: “project-demo-two:build:production” } } }, “extract-i18n”: { “builder”: “@angular-devkit/build-angular:extract-i18n”, “options”: { “browserTarget”: “project-demo-two:build” } }, “test”: { “builder”: “@angular-devkit/build-angular:karma”, “options”: { “main”: “projects/project-demo-two/src/test.ts”, “polyfills”: “projects/project-demo-two/src/polyfills.ts”, “tsConfig”: “projects/project-demo-two/tsconfig.spec.json”, “karmaConfig”: “projects/project-demo-two/karma.conf.js”, “styles”: [ “projects/project-demo-two/src/styles.css” ], “scripts”: [], “assets”: [ “projects/project-demo-two/src/favicon.ico”, “projects/project-demo-two/src/assets” ] } }, “lint”: { “builder”: “@angular-devkit/build-angular:tslint”, “options”: { “tsConfig”: [ “projects/project-demo-two/tsconfig.app.json”, “projects/project-demo-two/tsconfig.spec.json” ], “exclude”: [ “/node_modules/” ] } } } }, “project-demo-two-e2e”: { “root”: “projects/project-demo-two-e2e/”, “projectType”: “application”, “prefix”: “”, “architect”: { “e2e”: { “builder”: “@angular-devkit/build-angular:protractor”, “options”: { “protractorConfig”: “projects/project-demo-two-e2e/protractor.conf.js”, “devServerTarget”: “project-demo-two:serve” }, “configurations”: { “production”: { “devServerTarget”: “project-demo-two:serve:production” } } }, “lint”: { “builder”: “@angular-devkit/build-angular:tslint”, “options”: { “tsConfig”: “projects/project-demo-two-e2e/tsconfig.e2e.json”, “exclude”: [ “/node_modules/” ] } } } } }, “defaultProject”: “project-demo”} ...

April 9, 2019 · 3 min · jiezi

Angular脚手架开发

简介写一份自定义的angular脚手架吧写之前我们先解析一下antd的脚手架前提先把 Angular Schematic这篇文章读一遍,确保了解了collection等基础antd脚手架克隆项目git clone https://github.com/NG-ZORRO/ng-zorro-antd.git开始打开项目在schematics下的collection.json为入口,查看内容一共定了了4个schematic,每个schema分别指向了各文件夹的子schema.json,factory指向了函数入口,index.tsng-add/schema.json{ // 指定schema.json的验证模式 “$schema”: “http://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: https://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: https://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.tsimport { 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对象增加一个安装包的任务,然后拿到了任务idconst 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/http’};// 加入必须依赖模块export function addRequiredModules(options: Schema): Rule { return (host: Tree) => { // 获取tree下的工作目录 const workspace = getWorkspace(host); // 获取项目 const project = getProjectFromWorkspace(workspace, options.project); // 获取app.module的路径 const appModulePath = getAppModulePath(host, getProjectMainFile(project)); // 循环字典 for (const module in modulesMap) { // 调用下面的函数,意思就是:给appModule引一些模块,好吧,传入了tree,字典key(模块名称),字典value(模块所在包),project对象,appModule的路径,Schema配置项 addModuleImportToApptModule(host, module, modulesMap[ module ], project, appModulePath, options); } // 将构建好的tree返回给上层函数 return host; };}function addModuleImportToApptModule(host: Tree, moduleName: string, src: string, project: WorkspaceProject, appModulePath: string, options: Schema): void { if (hasNgModuleImport(host, appModulePath, moduleName)) { console.log(chalk.yellow(Could not set up "${chalk.blue(moduleName)}" + because "${chalk.blue(moduleName)}" is already imported. Please manually + check "${chalk.blue(appModulePath)}" file.)); return; } addModuleImportToRootModule(host, moduleName, src, project);}未完待续 ...

April 8, 2019 · 4 min · jiezi

Ionic start(4.x版本)发生bad status code 400错误以及离线创建新项目的解决方法

使用ionic start创建新项目,出现错误:Error: Encountered bad status code (400) forhttps://d2ql0qc7j8u4b2.cloudfront.net/angular-official-tabs.tar.gzThis could mean the server is experiencing difficulties right now–please tryagain later. at Request.req.on.res(C:\Users\xxx\AppData\Roaming\npm\node_modules\ionic\lib\utils\http.js:68:28) at emitOne (events.js:116:13) at Request.emit (events.js:211:7) at Request._emitResponse(C:\Users\xxx\AppData\Roaming\npm\node_modules\ionic\node_modules\superagent\lib\node\index.js:862:8) at ClientRequest.req.once.res(C:\Users\xxx\AppData\Roaming\npm\node_modules\ionic\node_modules\superagent\lib\node\index.js:412:10) at Object.onceWrapper (events.js:315:30) at emitOne (events.js:121:20) at ClientRequest.emit (events.js:211:7) at HTTPParser.parserOnIncomingClient (_http_client.js:543:21)| Downloading and extracting tabs starter (100.00%)然后就一直卡在Downloading and extracting tabs starter不动。直接原因是ionic cli无法下载ionic的template文件angular-official-tabs.tar.gz,从url看这个文件没有放在npm库中,所以使用淘宝npm镜像不能解决这个问题。在网上搜了很多文章都无法解决这个问题。后来在Ionic官网上看到,Ionic新项目模板(starter)作为一个开源项目托管在github上,于是尝试去找到starter template的源码,然后直接从starter template手工创建新项目。在github上搜索ionic-team,发现ionic-team/starters项目,这就是要找的模板源码项目。地址是:https://github.com/ionic-team/starters然后打包下载这个项目的所有源码。根目录下,有三个文件夹angular、ionic-angular和ionic1三个文件夹,显然分别对应三种ionic4项目的starter模板。angular是ionic4.x的angular项目;ionic-angular是ionic2.x/3.x的项目;ionic1是ionic1.x项目。我需要创建的是ionic4.x的项目,所以进入angular文件夹,里面有base和official两个文件夹,从前面错误信息看到下载文件名为angular-official-tabs.tar.gz,所以显然这个模板应该放在official文件夹中。打开official文件夹,里面果然有一个tabs的文件夹,里面有src和e2e两个文件夹,应该就是模板的源文件。但是angular/official/tabs文件夹下没有包含完整的ionic/angular的项目文件,显然,angular.json、package.json文件都没有。然后查找其他文件夹,发现angular/base文件夹下,有这些缺失的文件。于是做以下尝试:a.新建一个文件夹作为我们自己的项目文件夹,假设是testv4。b.把angular/base下的所有文件复制到testv4中。c.把angular/official/tabs文件夹下所有文件复制到testv4中,提示有同名文件,全部覆盖。d.打开testv4/package.json文件,修改前面几行内容为自己的应用名称等: “name”: “ionic-app-base”, “version”: “0.0.0”, “author”: “Ionic Framework”, “homepage”: “https://ionicframework.com/",e.在testv4文件夹上执行npm install,中间可能会出现错误,如果出错则删除node_module文件夹然后再次运行npm install,直到成功。f.执行npm run start,启动浏览器打开localhost:4200,成功。这个方法也可以实现不联网状态下,离线创建Ionic新项目,当然你可以说离线创建新项目没有意义,因为npm install一样需要联网,但如果能够手工建立node_module文件夹,离线创建ionic项目也是有意义的。 ...

March 25, 2019 · 1 min · jiezi