{"id":15893913,"url":"https://github.com/chinanf-boy/explain-node-prune","last_synced_at":"2025-04-02T18:16:34.414Z","repository":{"id":90548236,"uuid":"118107104","full_name":"chinanf-boy/explain-node-prune","owner":"chinanf-boy","description":"explain : node-prune { Remove unnecessary files from node_modules (.md, .ts, ...) } 清除 不必要 文件 在 node_modules","archived":false,"fork":false,"pushed_at":"2018-01-27T09:14:52.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-08T08:47:15.446Z","etag":null,"topics":["go","node-module","node-prune"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chinanf-boy.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-19T09:45:43.000Z","updated_at":"2018-01-19T14:51:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"ecc2300e-7f30-408e-b82e-4b6d6755fc67","html_url":"https://github.com/chinanf-boy/explain-node-prune","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fexplain-node-prune","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fexplain-node-prune/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fexplain-node-prune/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinanf-boy%2Fexplain-node-prune/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chinanf-boy","download_url":"https://codeload.github.com/chinanf-boy/explain-node-prune/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246866100,"owners_count":20846496,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","node-module","node-prune"],"created_at":"2024-10-06T08:14:04.178Z","updated_at":"2025-04-02T18:16:34.394Z","avatar_url":"https://github.com/chinanf-boy.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"## node-prune\n\n[![explain](http://llever.com/explain.svg)](https://github.com/chinanf-boy/Source-Explain)\n\n\u003e 清除 不必要 文件 在 node_modules (.md, .ts, ...) 中\n\n\nExplanation\n\n\u003e \"version\": \"1.0.1\"\n\n[github source](https://github.com/tj/node-prune)\n\n~~[english](./README.en.md)~~\n\n---\n\n## 本目录\n\n- [import-库的导入](#import-库的导入)\n\n- [go-运行-or-说明](#go-运行-or-说明)\n\n- [init-初始化](#init-初始化)\n\n- [main-命令分析](#main-命令分析)\n\n- [prune-新建](#prune-新建)\n\n- [output-详细信息](#output-详细信息)\n\n\n---\n\n## 命令行 node-prune\n\ngo 语言中，一个库能被命令方式使用，必然需要 \n\n[node-prune/cmd/node-prune/main.go](./node-prune/cmd/node-prune/main.go)\n\n``` go\npackage main // 作为编译-命令-程序的入口\n```\n\n我们就从 `main.go` 开始\n\n---\n\n## import-库的导入\n\n代码 1-12\n\n``` go\npackage main\n\nimport (\n\t\"flag\" // 原生-命令解析 :\u003e $ node-prune --help\n\t\"fmt\"  // 原生-终端屏幕输出 :\u003e 就像 js{console} py{print()}\n\t\"time\" // 原生-时间 :\u003e\n\n\t\"github.com/apex/log\" // 作者所写，日志记录\n\t\"github.com/apex/log/handlers/cli\"\n\t\"github.com/dustin/go-humanize\"\n\n\t\"github.com/tj/node-prune\" // 引入-node-prune-主库\n)\n```\n\n### go-运行-or-说明\n\n- go 语言在，库与库之间的应用上\n\n- 决心，铲除异己，一个库只能存在一个版本\n\n- 而 所有库都存放在，`GOPATH` 的 环境变量路径中，\n\n- 这就决定了，库的`唯一版本`且存放的`体积`, 而不是 `node_modules` 的无尽深渊\n\n-\n\n如果 .zshrc | .bashrc\n\n``` zsh\nexport GOPATH='path/to/gopath/ \n```\n\n-\n\n那么 \t`\"github.com/apex/log\"` 就在\n\n``` go\nGOPATH/src/github.com/apex/log //中\n// 类推\n//\"github.com/apex/log/handlers/cli\"\nGOPATH/src/github.com/apex/log/handlers/cli\n// ...\n```\n\n\u003e 当然，GOPATH 的可以是多个路径，一个路径一个集体\n\n---\n\n❕下文，有些例子，那么你需要 `clone` 这 `explain` 到你的 `GOPATH`\n\n```\ngo get -v github.com/chinanf-boy/explain-node-prune\n```\n---\n\n## init-初始化\n\n代码 15-17\n\n``` go\nfunc init() {\n\tlog.SetHandler(cli.Default)\n\tlog.SetLevel(log.WarnLevel)\n}\n```\n\n1. log\n\n\u003e 很明显, `log` 从哪里来, 那么我们需要看下去👀\n\n``` go\nimport (\n    // ...\n    \"github.com/apex/log\"\n    // ...\n)\n```\n\n- ❓ 这样的导入, 意味着什么\n\n- ℹ️ 意味着- `import` -\u003e 导入 `package log` -\u003e 🉐️`log`\n\n- ㊙️ 这个 `log` 代表了，整个库的内容，不过只有 `开头大写` 才是公有的\n\n``` go\nlog.SetHandler(cli.Default) // S 大写\n```\n\n2. log.SetHandler(cli.Default)\n\n\u003e 日志设置出口\n\ncli.go\n\n``` go\nvar Default = New(os.Stderr)  //写入标准错误以防止混乱和崩溃\n```\n\n3. log.SetLevel(log.WarnLevel)\n\n\u003e 日志设置等级\n\n- log.WarnLevel\n\n``` go\nconst (\n    InvalidLevel Level = iota - 1 // iota==0\n    // 用一次 + 1\n\tDebugLevel // 0\n\tInfoLevel // 1\n\tWarnLevel // 2\n\tErrorLevel // 3\n\tFatalLevel // 4\n)\n```\n\n\u003e [`log`库点到为止-更多内容](#apex-log)\n\n---\n\n## main-命令分析\n\n\u003e 使用 `flag` 对 用户的输出解析\n\n代码 20-35\n\n``` go\nfunc main() {\n    debug := flag.Bool(\"verbose\", false, \"Verbose log output.\")\n    // 在所有flag都注册之后\n\tflag.Parse() // 来解析命令行参数写入注册的flag里。\n\tdir := flag.Arg(0) // 第一个命令选项\n\n\tstart := time.Now() // 现在时间\n    // : 2009-11-10 23:00:00 +0000 UTC m=+0.000000001\n\n\tif *debug {\n\t\tlog.SetLevel(log.DebugLevel)\n\t}\n\n\tvar options []prune.Option\n    // 一个 特定-容器\n\n\tif dir != \"\" {\n\t\toptions = append(options, prune.WithDir(dir))\n    }\n    // prune.WithDir(dir) 返回 一个 特定-结构 被 特定容器装下\n\n    // append : options-数组-\u003e推入-\u003e prune.WithDir(dir)-数值\n```\n\n1. flag.Bool(a,b,c)\n    \n- a == `verbose`\n\n``` zsh\n$node-prune verbose # 触发\n```\n\n- b == `false`\n\n\u003e 默认值\n\n- c == \"Verbose log output.\"\n\n\u003e$node-prune --help \n\n```\nUsage of node-prune:\n  -verbose\n        Verbose log output.\n```\n\n---\n\n2. prune.WithDir(dir)\n\n``` go\nfunc WithDir(s string) Option {\n\treturn func(v *Pruner) {\n\t\tv.dir = s\n\t}\n}\n```\n\n\u003e go 语言的类型与接口是固定程序的强大工具\n\n\u003e 但是，一般不熟悉，相关类型与接口的，却可以说疲于奔命\n\n``` go\ntype Pruner struct {\n\tdir   string\n\tlog   log.Interface\n\tdirs  map[string]struct{}\n\texts  map[string]struct{}\n\tfiles map[string]struct{}\n\tch    chan func()\n\twg    sync.WaitGroup\n}\n\n// Option function.\ntype Option func(*Pruner)\n```\n\n在这一段，说明白对谁都好👀\n\n- `func WithDir(s string) Option `\n\n    - `s string` | s-函数变量名, 变量类型-string\n\n    - `Option` | 返回 Option 类型\n\n- `type Option func(*Pruner) `\n\n    - `type` | 定义类型-关键字\n\n    - `Option` | 类型名字\n\n    - `func(*Pruner)` | 对应类型 - 函数 - 其中变量需要是`*Pruner`\n\n- `type Pruner struct `\n\n    \u003e 如果说上面的类型-只不过是**一对一**指代关系\n\n    - `\bstruct` | 那么 struct 就是**一对多**的关系\n\n    - 这里就需要称 `Pruner` 为 `结构` 啦\n\n``` go\ntype Pruner struct { // Pruner 结构\n\tdir   string // dir-类型名， string-类型\n\tlog   log.Interface\n\tdirs  map[string]struct{}\n\texts  map[string]struct{}\n\tfiles map[string]struct{}\n\tch    chan func()\n\twg    sync.WaitGroup\n}\n```\n\n#### prune.WithDir(dir) 小结\n\n``` go\nfunc WithDir(s string) Option {\n\treturn func(v *Pruner) {\n\t\tv.dir = s\n\t}\n}\n```\n\n- `prune.WithDir(dir)`返回一个 函数类型 `Option`\n\n- 又因为 `type Option func(*Pruner)`\n\n- 所以其实 `Option` == `func(*Pruner)`\n\n- `func(*Pruner)`函数的变量是 `Pruner` 结构\n\n- `Pruner` 结构中成分- `*Pruner.dir` = `dir`\n\n\u003e  `dir` 作为第一层`WithDir`的变量`s`, 附值给第二层**func**`的`变量`v *Prune`中的结构成分-`v.dir`\n\n---\n\n🦊 真累啊, 想不到怎么难说 😢 , 继续前进吧\n\n---\n\n## prune-新建\n\n\u003e 新建 `prune` 实例并运行\n\n代码 37-42\n\n``` go\n\tp := prune.New(options...)\n\n\tstats, err := p.Prune()\n\tif err != nil {\n\t\tlog.Fatalf(\"error: %s\", err)\n\t}\n\n```\n\n\u003e[ 因为 `prune`库 太长，请移步-prune.readme.md](./prune.readme.md)\n\n---\n\n## output-详细信息\n\n\u003e 展示运行后数据\n\n代码 44-56\n\n``` go\n\tprintln() \n\tdefer println() // 1\n\n\toutput(\"files total\", humanize.Comma(stats.FilesTotal))\n\toutput(\"files removed\", humanize.Comma(stats.FilesRemoved))\n\toutput(\"size removed\", humanize.Bytes(uint64(stats.SizeRemoved)))\n\toutput(\"duration\", tim·e.Since(start).Round(time.Millisecond).String())\n}\n\nfunc output(name, val string) {\n\tfmt.Printf(\"\\x1b[1m%20s\\x1b[0m %s\\n\", name, val)\n}\n\n```\n\n- `defer` : 总是在函数退出前运行\n\n\u003e 可用来，数据库的断开，文件关闭，等等\n\n- `humanize`\n\n\u003e 转类型\n\n---\n\n## 其他\n\n### apex-log\n\n[apex/log tj大神的组织公司-apex](https://github.com/apex/log)\n\n### flag\n\n[flag-中文 go原生命令解析](https://studygolang.com/pkgdoc)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinanf-boy%2Fexplain-node-prune","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchinanf-boy%2Fexplain-node-prune","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinanf-boy%2Fexplain-node-prune/lists"}