? 重磅推荐!这份文档 + 课程 = 王炸组合 ? 双倍知识,双倍快乐,带你起飞~ ? (ง •_•)ง
准备:
- 安装 Node.js ;
- 安装 VS Code ;
- 创建文件夹 angular-cli-source-learn;
- 安装 Angular CLI
npm install @angular/cli
;
开发时一般全局安装
npm install -g @angular/cli
,为了方便研究源码,使用本地安装。
环境:
- Node.js 22.13.1;
- Angular CLI 19.1.5。
一、ng --help 源码分析
程序入口
重要文件
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
.vscode/launch.json
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.m**icr*osoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Launch Program", "skipFiles": [ "<node_internals>/**" ], "program": "${workspaceFolder}\node_modules\@angular\cli\bin\ng.js", "args": ["--help"] } ]}
逗号运算符
可选链运算符
Yargs
yargs-demo.js
const yargs = require('yargs')// const argv = yargs.parse()// console.log(process.argv);// console.log(argv);yargs .command({ command: 'add', describe: '添加笔记', handler: function () { console.log('正在添加笔记……'); } }) .command({ command: 'edit <file>', describe: '编辑笔记', handler: function (argv) { console.log('正在编辑笔记…… ' + argv.file); } }) .scriptName('note') .epilogue('欢迎使用笔记命令行工具。') .parse()
node .demo.js create student --name=zhouhuajian --age=18
ng --help --json-help
二、ng new 源码分析
重要文件
- [email protected]
- node_modules@angularclisrccommand-builderschematics-command-module.js
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- node_modules@angular-devkitschematicstaskspackage-managerexecutor.js
- angular-app2node_modules@angular-devkitschematicstasksrepo-initexecutor.js
创建工作区/项目
ng new angular-app
ng new [name] Creates a new Angular workspace.
.vscode/launch.json
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.m**icr*osoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Launch Program", "skipFiles": [ "<node_internals>/**" ], "program": "${workspaceFolder}\node_modules\@angular\cli\bin\ng.js", // "args": ["--help"] "args": ["new", "angular-app2"] } ]}
条件断点
cmd.command == 'new [name]'
Angular Schematics
npm install -g @angular-devkit/schematics-cli
本地安装,方便研究
npm install @angular-devkit/schematics-cli
schematics blank --name hello-worldcd hello-worldschematics blank --name hello-angular# 修改项目名为 schematics-democd ../schematics-demoschematics blank --name hello-both
// schematics-demosrchello-worldindex.tsexport function helloWorld(_options: any): Rule { return (tree: Tree, _context: SchematicContext) => { tree.create('hello-world', '123') return tree; };}// schematics-demosrchello-angularindex.tsexport function helloAngular(_options: any): Rule { return mergeWith(url('./files'));}// schematics-demosrchello-bothindex.tsexport function helloBoth(_options: any): Rule { // return chain([schematic('hello-world', {}), schematic('hello-angular', {})]) // /hello-world.txt // /hello-angular.txt return chain([ mergeWith(apply(empty(), [schematic('hello-world', {}), schematic('hello-angular', {})])) ])}
npm run buildschematics .:hello-worldschematics .:hello-angular# 删除 已生成的 两个文件schematics .:hello-bothcd ..schematics ./schematics-demo:hello-both
三、ng generate 源码分析
重要文件
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- angular-appnode_modules@schematicsangularcomponentfiles_name@dasherize@if-flat__name@dasherize_.type@dasherize.ts.template
.vscode/launch.json
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.m**icr*osoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Launch Program", "skipFiles": [ "<node_internals>/**" ], "program": "${workspaceFolder}\node_modules\@angular\cli\bin\ng.js", "args": ["generate", "component", "home"], "cwd": "${workspaceFolder}\angular-app" } ]}
Schematic
schematics-demosrchello-somebody
// 创建 hello-somebodycd .schematics-demoschematics blank --name hello-somebody// 运行 hello-somebodycd ..schematics ./schematics-demo:hello-somebody --name XiaoMing --flat --debug false// schema.json{ "properties": { "name": { "type": "string" }, "flat": { "type": "boolean" } }}// files/__name@dasherize@if-flat__/__name__.txt.template<%= name %><% if (name=='XiaoMing') {%>Hello<%}%>
// index.tsimport { Rule, apply, applyTemplates, mergeWith, url, strings, move } from '@angular-devkit/schematics';export function helloSomebody(_options: any): Rule { // /__name@dasherize@if-flat__/__name__.txt.template // 虚拟的树 // name: XiaoMing // /__name__/__name__.txt.template console.log(_options); // /xiao-ming/XiaoMing.txt // C:UserszhouhuajianDesktopangular-cli-source-learn/hello/somebody/XiaoMing.txt let source = apply(url('./files'), [ applyTemplates({ ..._options, ...strings, 'if-flat': (dirname: string) => (_options.flat ? '' : dirname) }), move("hello/somebody") ]) return mergeWith(source)}
四、ng build 源码分析
重要文件
- angular-appnode_modules@angularclisrccommand-builderarchitect-command-module.js
- angular-appnode_modules@angularclisrccommand-builderarchitect-base-command-module.js
- angular-appnode_modules@angularbuildsrcbuildersapplicationindex.js
- angular-appnode_modules@angularbuildsrcbuildersapplicationbuild-action.js
- angular-appnode_modules@angularbuildsrcbuildersapplicationexecute-build.js
- angular-appnode_modules@angularbuildsrctoolsesbuildbundler-context.js
.vscode/launch.json
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.m**icr*osoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Launch Program", "skipFiles": [ "<node_internals>/**" ], "program": "${workspaceFolder}\node_modules\@angular\cli\bin\ng.js", "args": ["build"], "cwd": "${workspaceFolder}\angular-app" } ]}
Architect
esbuild 打包器
angular-appesbuild-demoesbuild-demo.js
const esbuild = require('esbuild')esbuild.build({ entryPoints: { main: "./src/main.ts" }, outdir: "./dist", bundle: true, minifyIdentifiers: true, minifySyntax: true, minifyWhitespace: true, entryNames: '[name]-[hash]', write: false}).then(buildResult => { console.log(buildResult); console.log(buildResult.outputFiles[0].text);})
angular-appesbuild-demosrcmain.ts
angular-appesbuild-demosrcutils.ts
// main.tsrequire('./utils').sayHello()console.log(123);// utils.tsexports.sayHello = () => console.log("hello");
五、ng serve 源码分析
重要文件
- angular-appnode_modules@angularclisrccommand-builderarchitect-command-module.js
- angular-appnode_modules@angularclisrccommand-builderarchitect-base-command-module.js
- angular-appnode_modules@angular-devkitbuild-angularsrcbuildersdev-serverindex.js
- angular-appnode_modules@angular-devkitbuild-angularsrcbuildersdev-serverbuilder.js
- angular-appnode_modules@angularbuildsrcbuildersdev-servervite-server.js
- angular-appnode_modules@angularbuildsrctoolsvitepluginssetup-middlewares-plugin.js
- angular-appnode_modules@angularbuildsrctoolsvitemiddlewareshtml-fallback-middleware.js
- angular-appnode_modules@angularbuildsrctoolsvitemiddlewaresindex-html-middleware.js
.vscode/launch.json
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.m**icr*osoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Launch Program", "skipFiles": [ "<node_internals>/**" ], "program": "${workspaceFolder}\node_modules\@angular\cli\bin\ng.js", "args": ["serve"], "cwd": "${workspaceFolder}\angular-app" } ]}
Vite 构建工具
angular-appvite-demovite-demo.js
import { createServer } from "vite";const indexHtml = `<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> This is a home page in memory.</body></html>`const server = await createServer({ server: { host: 'localhost', port: 3000 }, root: './src', plugins: [{ name: 'plugin-demo', configureServer: async (server) => { // request response server.middlewares.use((req, res, next) => { if (req.url == '/') { req.url = '/index.html' } next() }) server.middlewares.use((req, res, next) => { console.log(req.url) // http://l*ocal*host:*3000/ // if (req.url == '/index.html' || req.url == '/') { if (req.url == '/index.html') { res.statusCode = 200 res.end(indexHtml) } else { res.statusCode = 404 res.end() } // console.log(req.method) // res.write("Hello") // res.write(" World") // res.end("!") }) return async () => { server.middlewares.use((req, res, next) => { }) console.log(server.middlewares.stack); } } }]})await server.listen() // http://l*ocal*host:*3000/index.htmlserver.printUrls()server.bindCLIShortcuts({ print: true})
angular-appvite-demosrcindex.html
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> This is a home page. </body></html>