// 看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/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 { // 如果app.module引入了NgZorroAntdModule等字典中的模块 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); }
addAnimationsModule 内容差不多,略过
registerLocale
不怕多,一点一点看,这里主要做的工作就是i18n本地化啥的
先上一张图片,记得脑子里哦
接下来的函数都是为了做上面这个工作