@icebreakers/monorepo 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/assets/package.json +1 -1
  2. package/dist/{chunk-EBATUF3S.js → chunk-J3UQM7T4.js} +1 -1
  3. package/dist/cli.cjs +1 -1
  4. package/dist/cli.js +1 -1
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.js +1 -1
  7. package/package.json +2 -2
  8. package/templates/apps/cli/bin/index.js +2 -0
  9. package/templates/apps/cli/dev/index.ts +2 -0
  10. package/templates/apps/cli/package.json +32 -0
  11. package/templates/apps/cli/src/cli.ts +3 -0
  12. package/templates/apps/cli/src/index.ts +0 -0
  13. package/templates/apps/cli/tsconfig.json +7 -0
  14. package/templates/apps/cli/tsup.config.ts +13 -0
  15. package/templates/apps/client/eslint.config.js +12 -0
  16. package/templates/apps/client/index.html +13 -0
  17. package/templates/apps/client/package.json +43 -0
  18. package/templates/apps/client/public/vite.svg +1 -0
  19. package/templates/apps/client/src/App.vue +9 -0
  20. package/templates/apps/client/src/main.ts +14 -0
  21. package/templates/apps/client/src/pages/index.vue +67 -0
  22. package/templates/apps/client/src/router/index.ts +13 -0
  23. package/templates/apps/client/src/stores/i18n.ts +23 -0
  24. package/templates/apps/client/src/stores/index.ts +15 -0
  25. package/templates/apps/client/src/style.css +1 -0
  26. package/templates/apps/client/src/trpc/index.ts +10 -0
  27. package/templates/apps/client/src/vite-env.d.ts +2 -0
  28. package/templates/apps/client/tsconfig.app.json +28 -0
  29. package/templates/apps/client/tsconfig.json +8 -0
  30. package/templates/apps/client/tsconfig.node.json +25 -0
  31. package/templates/apps/client/tsconfig.worker.json +11 -0
  32. package/templates/apps/client/vite.config.ts +38 -0
  33. package/templates/apps/client/worker/app.ts +24 -0
  34. package/templates/apps/client/worker/config.ts +1 -0
  35. package/templates/apps/client/worker/fetch-entry.ts +5 -0
  36. package/templates/apps/client/worker/node-entry.ts +12 -0
  37. package/templates/apps/client/worker/trpc-router.ts +24 -0
  38. package/templates/apps/client/worker-configuration.d.ts +7688 -0
  39. package/templates/apps/client/wrangler.jsonc +21 -0
  40. package/templates/apps/server/package.json +58 -0
  41. package/templates/apps/server/src/app.ts +191 -0
  42. package/templates/apps/server/src/config.ts +1 -0
  43. package/templates/apps/server/src/fetch-entry.ts +5 -0
  44. package/templates/apps/server/src/node-entry.ts +12 -0
  45. package/templates/apps/server/test/index.test.ts +14 -0
  46. package/templates/apps/server/tsconfig.json +24 -0
  47. package/templates/apps/server/tsup.config.ts +13 -0
  48. package/templates/apps/server/vitest.config.ts +15 -0
  49. package/templates/apps/server/worker-configuration.d.ts +7688 -0
  50. package/templates/apps/server/wrangler.jsonc +18 -0
  51. package/templates/apps/website/.vitepress/config.ts +93 -0
  52. package/templates/apps/website/.vitepress/theme/index.ts +4 -0
  53. package/templates/apps/website/.vitepress/theme/tailwind.css +1 -0
  54. package/templates/apps/website/index.md +151 -0
  55. package/templates/apps/website/monorepo/index.md +68 -0
  56. package/templates/apps/website/monorepo/manage.md +60 -0
  57. package/templates/apps/website/monorepo/publish.md +189 -0
  58. package/templates/apps/website/package.json +34 -0
  59. package/templates/apps/website/public/logo.jpg +0 -0
  60. package/templates/apps/website/thinking.md +88 -0
  61. package/templates/apps/website/tools/changeset.md +87 -0
  62. package/templates/apps/website/tools/husky.md +108 -0
  63. package/templates/apps/website/tools/lint-staged.md +79 -0
  64. package/templates/apps/website/tools/pnpm.md +100 -0
  65. package/templates/apps/website/tools/renovate.md +91 -0
  66. package/templates/apps/website/tools/turborepo.md +149 -0
  67. package/templates/apps/website/why/assets/npm-dt.svg +15 -0
  68. package/templates/apps/website/why/assets/npm-ts.svg +19 -0
  69. package/templates/apps/website/why/examples/0.npm-basic-package/index.js +9 -0
  70. package/templates/apps/website/why/examples/0.npm-basic-package/package.json +11 -0
  71. package/templates/apps/website/why/examples/1.npm-basic-package/index.cjs +11 -0
  72. package/templates/apps/website/why/examples/1.npm-basic-package/index.d.ts +1 -0
  73. package/templates/apps/website/why/examples/1.npm-basic-package/index.js +7 -0
  74. package/templates/apps/website/why/examples/1.npm-basic-package/package.json +19 -0
  75. package/templates/apps/website/why/examples/2.npm-basic-package/README.md +1 -0
  76. package/templates/apps/website/why/examples/2.npm-basic-package/package-lock.json +30 -0
  77. package/templates/apps/website/why/examples/2.npm-basic-package/package.json +35 -0
  78. package/templates/apps/website/why/examples/2.npm-basic-package/rename-ext.js +24 -0
  79. package/templates/apps/website/why/examples/2.npm-basic-package/src/index.ts +7 -0
  80. package/templates/apps/website/why/examples/2.npm-basic-package/tsconfig.cjs.json +8 -0
  81. package/templates/apps/website/why/examples/2.npm-basic-package/tsconfig.esm.json +7 -0
  82. package/templates/apps/website/why/examples/2.npm-basic-package/tsconfig.json +18 -0
  83. package/templates/apps/website/why/examples/3.npm-basic-package/README.md +1 -0
  84. package/templates/apps/website/why/examples/3.npm-basic-package/build.config.ts +24 -0
  85. package/templates/apps/website/why/examples/3.npm-basic-package/package-lock.json +3661 -0
  86. package/templates/apps/website/why/examples/3.npm-basic-package/package.json +32 -0
  87. package/templates/apps/website/why/examples/3.npm-basic-package/src/index.ts +7 -0
  88. package/templates/apps/website/why/examples/3.npm-basic-package/tsconfig.json +16 -0
  89. package/templates/apps/website/why/examples/3.npm-basic-package/tsup.config.ts +16 -0
  90. package/templates/apps/website/why/examples/usage-cjs/cjs.cjs +3 -0
  91. package/templates/apps/website/why/examples/usage-cjs/esm.mjs +3 -0
  92. package/templates/apps/website/why/examples/usage-cjs/index.js +11 -0
  93. package/templates/apps/website/why/examples/usage-cjs/package-lock.json +42 -0
  94. package/templates/apps/website/why/examples/usage-cjs/package.json +20 -0
  95. package/templates/apps/website/why/examples/usage-esm/cjs.cjs +3 -0
  96. package/templates/apps/website/why/examples/usage-esm/createRequire.js +7 -0
  97. package/templates/apps/website/why/examples/usage-esm/esm.mjs +3 -0
  98. package/templates/apps/website/why/examples/usage-esm/index.js +7 -0
  99. package/templates/apps/website/why/examples/usage-esm/package-lock.json +42 -0
  100. package/templates/apps/website/why/examples/usage-esm/package.json +21 -0
  101. package/templates/apps/website/why/how-to-reuse-js-code.md +250 -0
  102. package/templates/apps/website/why/index.md +1 -0
  103. package/templates/apps/website/why/js-cjs-mjs.md +99 -0
  104. package/templates/apps/website/why/js-keywords.md +132 -0
  105. package/templates/apps/website/why/modern/bundlers.md +79 -0
  106. package/templates/apps/website/why/modern/dts.md +95 -0
  107. package/templates/apps/website/why/modern/esm-vs-cjs.md +84 -0
  108. package/templates/apps/website/why/modern/index.md +55 -0
  109. package/templates/apps/website/why/modern/package-entry-points.md +128 -0
  110. package/templates/apps/website/why/modern/typescript.md +155 -0
  111. package/templates/apps/website/why/publish-basic-npm-package.md +146 -0
  112. package/templates/apps/website/why/what-is-npm-package.md +162 -0
  113. package/templates/packages/tsup-template/build.config.ts +24 -0
  114. package/templates/packages/tsup-template/package.json +42 -0
  115. package/templates/packages/tsup-template/src/index.ts +12 -0
  116. package/templates/packages/tsup-template/test/index.test.ts +7 -0
  117. package/templates/packages/tsup-template/tsconfig.json +15 -0
  118. package/templates/packages/tsup-template/tsup.config.ts +18 -0
  119. package/templates/packages/tsup-template/vitest.config.ts +15 -0
  120. package/templates/packages/unbuild-template/build.config.ts +24 -0
  121. package/templates/packages/unbuild-template/package.json +42 -0
  122. package/templates/packages/unbuild-template/src/index.ts +9 -0
  123. package/templates/packages/unbuild-template/src/utils.ts +3 -0
  124. package/templates/packages/unbuild-template/test/index.test.ts +7 -0
  125. package/templates/packages/unbuild-template/tsconfig.json +15 -0
  126. package/templates/packages/unbuild-template/vitest.config.ts +15 -0
  127. package/templates/packages/vue-lib-template/eslint.config.js +12 -0
  128. package/templates/packages/vue-lib-template/index.html +13 -0
  129. package/templates/packages/vue-lib-template/lib/HelloWorld.vue +21 -0
  130. package/templates/packages/vue-lib-template/lib/index.ts +3 -0
  131. package/templates/packages/vue-lib-template/package.json +61 -0
  132. package/templates/packages/vue-lib-template/src/App.vue +9 -0
  133. package/templates/packages/vue-lib-template/src/main.ts +8 -0
  134. package/templates/packages/vue-lib-template/src/pages/index.vue +7 -0
  135. package/templates/packages/vue-lib-template/src/router/index.ts +11 -0
  136. package/templates/packages/vue-lib-template/src/style.css +1 -0
  137. package/templates/packages/vue-lib-template/src/vite-env.d.ts +2 -0
  138. package/templates/packages/vue-lib-template/test/index.test.ts +13 -0
  139. package/templates/packages/vue-lib-template/tsconfig.app.json +30 -0
  140. package/templates/packages/vue-lib-template/tsconfig.json +14 -0
  141. package/templates/packages/vue-lib-template/tsconfig.node.json +25 -0
  142. package/templates/packages/vue-lib-template/tsconfig.test.json +40 -0
  143. package/templates/packages/vue-lib-template/vite.config.ts +47 -0
  144. package/templates/packages/vue-lib-template/vite.shared.config.ts +13 -0
  145. package/templates/packages/vue-lib-template/vitest.config.ts +13 -0
@@ -0,0 +1,132 @@
1
+ # CJS 和 ESM 关键字/全局变量对比
2
+
3
+ ## 📦 CommonJS (CJS)
4
+
5
+ CJS 是 Node.js 默认的老模块系统,使用 `require` 和 `module.exports`。
6
+
7
+ ### 核心关键字 / 全局变量
8
+
9
+ - **`require`**
10
+ 用于导入模块,例如:`const fs = require("fs")`
11
+ - **`module.exports`**
12
+ 导出一个模块的接口对象。
13
+ - **`exports`**
14
+ 是 `module.exports` 的引用,常用于简写导出。
15
+ - **`__filename`**
16
+ 当前模块的绝对路径(包含文件名)。
17
+ - **`__dirname`**
18
+ 当前模块所在目录的绝对路径。
19
+ - **`arguments`**
20
+ 在函数中依然可用,但不是模块特有的(ESM 中的顶层不再支持)。
21
+
22
+ ### 特点
23
+
24
+ - 模块加载是 **同步的**(`require` 立即执行)。
25
+ - 每个文件就是一个模块,作用域隔离。
26
+ - Node.js 原生支持。
27
+
28
+ ## 🌐 ECMAScript Modules (ESM)
29
+
30
+ ESM 是 JavaScript 官方标准,现代浏览器和 Node.js 都支持(需要 `.mjs` 或 `package.json` 配置 `"type": "module"`)。
31
+
32
+ ### 核心关键字 / 特性
33
+
34
+ - **`import`**
35
+ 用于引入模块:
36
+ - `import fs from "fs"`
37
+ - `import { readFile } from "fs"`
38
+
39
+ - **`export`**
40
+ 导出模块:
41
+ - `export default function() {}`
42
+ - `export const x = 1`
43
+
44
+ - **`import.meta`**
45
+ 提供关于当前模块的元信息(例如:`import.meta.url` 获取模块的文件路径 URL)。
46
+ - **`top-level await`**
47
+ 在 ESM 顶层作用域中可以直接使用 `await`。
48
+
49
+ ### 特点
50
+
51
+ - 模块加载是 **异步的**。
52
+ - 静态结构,编译时可确定依赖关系。
53
+ - 更加标准化,支持 Tree-shaking(构建时优化)。
54
+
55
+ ## 🚧 差异对照表
56
+
57
+ | 特性 | CommonJS (CJS) | ECMAScript Modules (ESM) |
58
+ | ---------------- | ---------------------------- | --------------------------------- |
59
+ | 导入 | `require()` | `import` |
60
+ | 导出 | `module.exports` / `exports` | `export` / `export default` |
61
+ | 文件扩展名 | `.cjs` / `.js` | `.mjs` / `.js` |
62
+ | 文件路径变量 | `__filename`, `__dirname` | ❌(可用 `import.meta.url` 替代) |
63
+ | 模块元信息 | ❌ | `import.meta` |
64
+ | 异步顶层 `await` | ❌ | ✅ |
65
+ | 加载方式 | 同步 | 异步 |
66
+
67
+ ---
68
+
69
+ 👉 例如,ESM 中没有 `__filename` 和 `__dirname`,你需要用以下方式替代:
70
+
71
+ ```js
72
+ import { dirname } from 'node:path'
73
+ // ESM 中获取 __dirname 效果
74
+ import { fileURLToPath } from 'node:url'
75
+
76
+ const __filename = fileURLToPath(import.meta.url)
77
+ const __dirname = dirname(__filename)
78
+ ```
79
+
80
+ ## 📦 CommonJS (CJS) — 清除模块缓存
81
+
82
+ CJS 使用 `require()` 加载模块时,**会把模块对象缓存在 `require.cache` 里**。如果想清除缓存,可以操作这个对象。
83
+
84
+ ### 关键方式
85
+
86
+ ```js
87
+ // 加载模块
88
+ const mod = require('./foo.js')
89
+
90
+ // 清除缓存
91
+ delete require.cache[require.resolve('./foo.js')]
92
+
93
+ // 重新加载
94
+ const freshMod = require('./foo.js')
95
+ ```
96
+
97
+ - `require.resolve()` 会返回模块的绝对路径,用它作为 key 来删除缓存。
98
+ - 删除后,再次 `require()` 会重新执行模块代码。
99
+
100
+ ⚠️ 注意:
101
+
102
+ - 如果模块被多个文件引用,删除缓存只影响 **当前模块**,依赖树中的引用关系可能导致“旧对象”仍在内存中。
103
+ - 所以要真正“重载”模块,有时需要递归删除依赖树的缓存。
104
+
105
+ ## 🌐 ECMAScript Modules (ESM) — 清除模块缓存
106
+
107
+ ESM 的模块缓存存放在 **`import` 的内部 Module Map** 中,规范里没有暴露直接操作缓存的方法。
108
+ 不过在 **Node.js 环境** 中,可以通过 **动态导入 (`import()`)** + **带查询参数** 或 **利用 `vm` / Loader Hooks** 来实现类似效果。
109
+
110
+ ### 常用方式 1:加查询参数绕缓存
111
+
112
+ ```js
113
+ const mod1 = await import(`./foo.js?update=${Date.now()}`)
114
+ const mod2 = await import(`./foo.js?update=${Date.now()}`)
115
+ ```
116
+
117
+ - 每次加上不同的 querystring,就会绕过缓存,强制重新加载。
118
+
119
+ ### 常用方式 2:使用 `import()` + `Module.createRequire`
120
+
121
+ 在 Node.js 18+ 里,可以通过 `vm` 的上下文重新加载模块,不过相对复杂。一般开发调试时用 **动态 `import()` 加 query** 就够了。
122
+
123
+ ## 🚧 对比总结
124
+
125
+ | 功能 | CommonJS (CJS) | ECMAScript Modules (ESM) |
126
+ | ------------------ | ----------------------------------------- | ----------------------------------- |
127
+ | 缓存位置 | `require.cache` | 内部 **Module Map**(不可直接访问) |
128
+ | 清除缓存方法 | `delete require.cache[require.resolve()]` | ❌ 无官方 API |
129
+ | 实际可行的清除方法 | 直接删除缓存并重新 `require()` | 动态 `import()` 加唯一参数绕过缓存 |
130
+ | 典型应用场景 | 热重载、插件系统 | 热重载、调试时强制刷新模块 |
131
+
132
+ <!-- 👉 要不要我帮你写一个 **CJS + ESM 通用的“热重载工具函数”**,比如 `reloadModule(path)`,可以自动检测当前运行环境,然后清除缓存并重新加载?这样你写代码时可以直接用,而不用区分 require/import。 -->
@@ -0,0 +1,79 @@
1
+ # 使用打包器
2
+
3
+ ## 选择打包器
4
+
5
+ 一般来说,在不同场景下,需要使用不同的打包器,以下是我的选择:
6
+
7
+ - `webpack` 我不用,因为打出来的产物代码丑,配置复杂
8
+ - `rollup` 我最早用的就是这个,现在不用因为要装的包太多了,而且需要你对打包器有一定的理解,在打包复杂需要高度自定义的场景下使用
9
+ - `esbuild` 用的少,直接用不是很方便,但是可以基于它做高度自定义(写插件)
10
+ - `tsup` 基于 `esbuild` 的傻瓜无脑式的打包器,非常好用
11
+ - `unbuild` 基于 `rollup` 的傻瓜无脑式的打包器,众多 `vite plugin` 源代码的御用打包器,还有基于 `jiti` 的 `stub` 模式,非常好用
12
+ - `vite` 基于 `rollup` 的打包器,假如你需要构建前端组件,这个就是首选,毕竟你也懒得去自己处理各种各样的样式文件吧,比如打包新版本 `vue` 组件,只能使用这个的库模式进行打包。
13
+ - `rolldown`/`tsdown` 暂时不太稳定,等出正式版本再观望一段时间
14
+
15
+ 所以本篇文章,主要介绍 `tsup` 和 `unbuild` 这两个通用打包器的使用和配置方式,以及 `vite` 库模式进行打包 `vue` 组件,其他的请自行查看对应的文档。
16
+
17
+ ## tsup
18
+
19
+ 本项目的模板之一 [tsup-template](https://github.com/sonofmagic/monorepo-template/tree/main/packages/tsup-template)
20
+
21
+ :::code-group
22
+
23
+ ```ts [tsup.config.ts]
24
+ import { defineConfig } from 'tsup'
25
+
26
+ export default defineConfig({
27
+ entry: ['src/index.ts'], // , 'src/cli.ts'],
28
+ shims: true,
29
+ format: ['cjs', 'esm'],
30
+ clean: true,
31
+ dts: true,
32
+ cjsInterop: true,
33
+ splitting: true,
34
+ outExtension({ format }) {
35
+ return {
36
+ js: `.${format === 'esm' ? 'mjs' : 'cjs'}`,
37
+ }
38
+ },
39
+ })
40
+ ```
41
+
42
+ :::
43
+
44
+ ## unbuild
45
+
46
+ 本项目的模板之一 [unbuild-template](https://github.com/sonofmagic/monorepo-template/tree/main/packages/unbuild-template)
47
+
48
+ :::code-group
49
+
50
+ ```ts [build.config.ts]
51
+ import path from 'node:path'
52
+ import { defineBuildConfig } from 'unbuild'
53
+
54
+ export default defineBuildConfig({
55
+ entries: ['./src/index'],
56
+ rollup: {
57
+ inlineDependencies: true,
58
+ emitCJS: true,
59
+ cjsBridge: true,
60
+ dts: {
61
+ respectExternal: false,
62
+ },
63
+ },
64
+ alias: {
65
+ '@': path.resolve(__dirname, './src'),
66
+ },
67
+ declaration: true,
68
+ })
69
+ ```
70
+
71
+ :::
72
+
73
+ ## vite
74
+
75
+ 本项目的模板之一 [vue-lib-template](https://github.com/sonofmagic/monorepo-template/tree/main/packages/vue-lib-template)
76
+
77
+ 你可以在 [`vite` 库模式官方文档](https://vite.dev/guide/build.html#library-mode) 来查看打包 `vue` 组件的方式
78
+
79
+ 当然这些都已经被配置在 [vue-lib-template](https://github.com/sonofmagic/monorepo-template/tree/main/packages/vue-lib-template) 中了
@@ -0,0 +1,95 @@
1
+ # 添加 dts
2
+
3
+ ## `.d.ts` 文件是什么
4
+
5
+ 在 TypeScript 中,`.d.ts` 文件是 **类型声明文件**,全称是 **"declaration file"**。它的主要作用是为 JavaScript 代码或没有类型定义的 TypeScript 代码提供类型信息。
6
+
7
+ 你安装使用刚刚自己发的包的时候,有没有注意到,你的 `IDE` 没有出现任何的智能提示
8
+
9
+ 这是因为你没有为你的包提供任何的 `dts`, 也就是 `xxx.d.ts` 文件
10
+
11
+ 下面这 2 个标志想必大家在 `npmjs` 进行搜索的时候都见到过。
12
+
13
+ <img width="40" src="../assets/npm-ts.svg" />
14
+
15
+ 这个标志代表这个包发布的时候,本身包里面就自己提供了 `dts`,这个需要在打包生成出 `dts` 之后,在 `package.json` 中,通过 `types` 字段指定了 `dts` 的位置
16
+
17
+ 比如我发的所有包 [weapp-tailwindcss](https://www.npmjs.com/package/weapp-tailwindcss), [weapp-vite](https://www.npmjs.com/package/weapp-vite), [modern-ahocorasick](https://www.npmjs.com/package/modern-ahocorasick) 等等...
18
+
19
+ <img width="40" src="../assets/npm-dt.svg" />
20
+
21
+ 这个标志代表这个包发布的时候,本身包里面没有 `dts`,但是有好心人给他写了 `dts`,并发布到了 `@types/*` 这个作用域下了,所以这个包等同于也有 `dts`,而且 `vscode` 也在发现你安装了这样的包之后,也会去下载 `@types/*` 这样的包,当然更好的方式是你要显式安装 `@types` 包
22
+
23
+ 举个例子,比如 [lodash](https://www.npmjs.com/package/lodash) 和 [@types/lodash](https://www.npmjs.com/package/@types/lodash),点击 [lodash](https://www.npmjs.com/package/lodash) `npm` 主页面的这个标志,就直接跳转到 [@types/lodash](https://www.npmjs.com/package/@types/lodash)
24
+
25
+ > [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) 这个是微软的仓库,用于发布管理所有的 `@types` 包
26
+
27
+ 这里就需要提到包的质量判断标准,一般来说呈现下面的趋势:
28
+
29
+ <div class="flex justify-center">
30
+ <div class="flex items-center border p-6">
31
+
32
+ <img class="w-12" src="../assets/npm-ts.svg" />
33
+ <div class="text-5xl mx-5">></div>
34
+ <img class="w-12" src="../assets/npm-dt.svg" />
35
+ <div class="text-5xl mx-5">></div>
36
+ <div>什么标志都没有的包</div>
37
+ </div>
38
+ </div>
39
+
40
+ ---
41
+
42
+ ### `.d.ts` 文件的作用
43
+
44
+ - **描述模块或库的类型结构**,使 TypeScript 可以进行类型检查和代码补全。
45
+ - **为 JavaScript 库提供类型支持**,例如 jQuery、Lodash、React 等第三方库。
46
+ - **声明全局变量、模块、类、接口、函数等**,而不提供实际实现。
47
+
48
+ ---
49
+
50
+ ### 举个简单例子
51
+
52
+ 假设你有一个 JavaScript 文件 `math.js`:
53
+
54
+ ```js
55
+ // math.js
56
+ function add(a, b) {
57
+ return a + b
58
+ }
59
+ ```
60
+
61
+ 你可以写一个 `.d.ts` 文件来告诉 TypeScript 这个模块的类型:
62
+
63
+ ```ts
64
+ // math.d.ts
65
+ declare function add(a: number, b: number): number
66
+ ```
67
+
68
+ 这样你在 TypeScript 中使用 `add` 函数时就能获得类型检查和智能提示了。
69
+
70
+ ---
71
+
72
+ ### 使用场景
73
+
74
+ 1. **第三方库没有内置类型定义时**
75
+
76
+ - 可以使用 DefinitelyTyped 的类型库(安装例如 `@types/lodash`);
77
+ - 或者自己写 `.d.ts` 文件。
78
+
79
+ 2. **为已有的 JS 代码添加类型支持**
80
+
81
+ - 特别是在从 JS 项目逐步迁移到 TS 时。
82
+
83
+ 3. **定义公共 API 接口或模块类型**
84
+ - 比如声明一个共享的接口模块 `types.d.ts`,全项目通用。
85
+
86
+ ---
87
+
88
+ ### 类型声明的获取方式
89
+
90
+ - 手动编写 `.d.ts`
91
+ - 自动生成(例如通过 `tsc --declaration`)
92
+ - 安装类型定义包:
93
+ ```
94
+ npm install --save-dev @types/express
95
+ ```
@@ -0,0 +1,84 @@
1
+ # ESM vs CJS
2
+
3
+ 在 Node.js 中,ESM(ECMAScript Modules)和 CJS(CommonJS)是两种模块系统。ESM 是 JavaScript 官方标准的模块系统,而 CJS 是 Node.js 最初采用的模块系统。
4
+
5
+ ## ESM 相对 CJS 的优势
6
+
7
+ ### 1. **官方标准化**
8
+
9
+ - **ESM 是 ECMAScript 的官方模块规范**,跨平台和跨环境(如浏览器、Deno)都支持。
10
+ - 更有利于代码的可移植性和与未来标准兼容。
11
+
12
+ ### 2. **静态分析能力更强**
13
+
14
+ - ESM 使用 `import` / `export`,**在解析阶段即可确定依赖关系**,这让:
15
+ - Tree Shaking(去除无用代码)成为可能。
16
+ - 更好地进行工具分析(如 Webpack、Rollup)。
17
+
18
+ ### 3. **支持异步加载**
19
+
20
+ - ESM 模块加载是**异步的**,允许更灵活的模块加载策略(尤其适合在浏览器环境或网络环境下)。
21
+ - 支持 `import()` 动态导入,可以实现按需加载。
22
+
23
+ ### 4. **更好的模块作用域**
24
+
25
+ - 每个 ESM 模块都有自己的作用域,**默认是严格模式**(`use strict`),无需显式声明。
26
+ - 避免了 CJS 中的某些副作用或全局变量污染问题。
27
+
28
+ ### 5. **顶层 `await` 支持**
29
+
30
+ - 在支持的环境下,ESM 模块可以使用**顶层 await**,这在处理异步初始化逻辑时非常方便。
31
+
32
+ ### 6. **统一生态趋势**
33
+
34
+ - 越来越多的现代 JavaScript 项目和库采用 ESM,比如 Vite、ESBuild、Deno 等工具链优先支持 ESM。
35
+
36
+ ---
37
+
38
+ ## 对比小结
39
+
40
+ | 特性 | ESM | CommonJS (CJS) |
41
+ | ----------------- | --------------------- | ---------------------------- |
42
+ | 模块语法 | `import` / `export` | `require` / `module.exports` |
43
+ | 加载方式 | 静态分析 + 异步加载 | 运行时同步加载 |
44
+ | 标准化 | 是(ECMAScript 标准) | 否(Node.js 专有) |
45
+ | Tree Shaking 支持 | ✅ | ❌ |
46
+ | 顶层 await 支持 | ✅(Node.js ≥ 14.8) | ❌ |
47
+ | 浏览器支持 | ✅ | ❌ |
48
+ | 动态导入 | `import()` | `require()` |
49
+
50
+ ---
51
+
52
+ ## 使用 ESM 的注意事项(在 Node.js 中)
53
+
54
+ - `package.json` 中需要设置 `"type": "module"`。
55
+ - 文件扩展名必须为 `.mjs` 或 `.js`(视 `type` 而定)。
56
+ - `__filename`、`__dirname` 等 Node.js CJS 特有变量不可直接使用(需 `import.meta.url` 代替, 高版本 `Nodejs` 可以使用 `import.meta.dirname` 和 `import.meta.filename`)。
57
+
58
+ ---
59
+
60
+ ## 适合使用 ESM 的场景
61
+
62
+ - 对于新项目,不论是前端还是服务端,你应该始终使用 `ESM`。
63
+ - 需要兼容浏览器或打包工具的项目
64
+ - 有 `Tree Shaking` 需求的库开发
65
+
66
+ ## esm 中使用 require
67
+
68
+ 在 `esm` 格式中的 `js` 中使用 `require` 会报错
69
+
70
+ ```sh
71
+ ReferenceError: require is not defined in ES module scope, you can use import instead
72
+ ```
73
+
74
+ 另外也有一种适用于 `nodejs` 的 `esm` 中使用 `require` 做法:
75
+
76
+ ```js
77
+ import { createRequire } from 'node:module'
78
+
79
+ const require = createRequire(import.meta.filename)
80
+
81
+ const { sayHello } = require('icebreaker-npm-basic-package')
82
+
83
+ sayHello()
84
+ ```
@@ -0,0 +1,55 @@
1
+ ---
2
+ outline: [2, 4]
3
+ ---
4
+
5
+ # 改进并发布现代 npm 包
6
+
7
+ 刚刚我们发布了一个低质量的 `npm` 包,因为它
8
+
9
+ 1. 没有类型提示
10
+ 2. 使用了落后的 CJS 语法
11
+ 3. 没有使用打包器进行构建,导致无法做语法降级,这可能在低版本的浏览器/Nodejs中出现问题
12
+ 4. 没有写 README 别人根本不知道怎么用
13
+ 5. 没有单元测试,导致出现问题修改时,容易把原先好的case改坏等等。
14
+
15
+ 为此我们需要提升包的质量,具体的手段如下
16
+
17
+ 此代码的演变用例见 [examples](https://github.com/sonofmagic/monorepo-template/tree/main/apps/website/why/examples)
18
+
19
+ ## 确定包的模块入口点
20
+
21
+ 详见 [package-entry-points](./package-entry-points)
22
+
23
+ ## 添加 DTS
24
+
25
+ 类型提示其实就是最好的文档,为了让使用者,能在IDE里面直接点出来方法,类型和枚举,我们需要添加它
26
+
27
+ 详见 [DTS](./dts.md)
28
+
29
+ ## 更改为 ESM 格式优先
30
+
31
+ 优先 ESM 格式符合我们面向未来编程的原则。
32
+
33
+ 详见 [ESM vs CJS](./esm-vs-cjs.md)
34
+
35
+ ## 使用 TypeScript 进行编写
36
+
37
+ 既然我们都要使用一份代码,去生成 `cjs` / `esm` / `dts`,那么我们当然可以完全使用 `TypeScript` 进行编写,去生成对应的产物即可
38
+
39
+ 详见 [使用 TypeScript 编写代码](./typescript)
40
+
41
+ ## 使用打包器
42
+
43
+ `TypeScript` 自带的 `tsc` 功能太弱了,当我们要进行一些前端工程化的改造时候,光使用 `tsc` + `script脚本` 的方式已经满足不了我们的需求
44
+
45
+ 所有我们这时候需要引入打包器,来和 `TypeScript` 一起协作
46
+
47
+ 详见 [使用打包器](./bundlers)
48
+
49
+ ## 写一份可读的 README
50
+
51
+ 假如你写的 `npm` 包已经复杂到一个 `README.md` 文档无法解决开发者的遇到的问题了,那么就准备一个文档网站
52
+
53
+ ## 添加单元测试(额外)
54
+
55
+ 本模板使用的就是 `vitest`,具体使用方式见 `vitest` 文档
@@ -0,0 +1,128 @@
1
+ ---
2
+ outline: [2, 4]
3
+ ---
4
+
5
+ # package.json 中的 entry point 字段
6
+
7
+ 在 `package.json` 中,定义模块的入口点 (`entry point`) 字段是及其重要的
8
+
9
+ ## package.json 代码示例
10
+
11
+ ```jsonc
12
+ {
13
+ "name": "icebreaker-npm-basic-package",
14
+ "version": "1.0.0",
15
+ "type": "module",
16
+ "main": "./index.cjs", // CommonJS 主入口(用于 Node require)
17
+ "module": "./index.mjs", // 非标准,但很多构建工具支持(ESM)
18
+ "types": "./index.d.ts", // TypeScript 类型定义
19
+ "exports": {
20
+ ".": {
21
+ "types": "./index.d.ts", // TypeScript 类型定义
22
+ "require": "./index.cjs", // Node require 使用 CommonJS
23
+ "import": "./index.mjs" // Node import 使用 ESM
24
+ }
25
+ }
26
+ }
27
+ ```
28
+
29
+ ### 📝 字段说明:
30
+
31
+ | 字段 | 说明 |
32
+ | ------------------ | ------------------------------------------------ |
33
+ | `"type": "module"` | 默认将 `.js` 文件视为 ESM |
34
+ | `"main"` | Node 中 `require('pkg')` 会使用 CommonJS 文件 |
35
+ | `"module"` | 给打包工具提供 ESM 入口,非标准,但有用 |
36
+ | `"exports"` | 更现代且明确的方式,指明模块格式,兼容 Node >=12 |
37
+ | `"types"` | 给 TypeScript 指明类型定义文件的位置 |
38
+
39
+ ---
40
+
41
+ 官方文档: [package-entry-points](https://nodejs.org/api/packages.html#package-entry-points)
42
+
43
+ ## 为什么说 module 是非标准的?
44
+
45
+ 在 `package.json` 中,`"module"` 字段是一个 **非标准的字段**,但在现代前端工具(如 Webpack、Rollup、Vite 等)中被广泛使用,用于指向 **ES Module 格式的入口文件**,以便这些工具能够做更好的静态分析与 tree-shaking。
46
+
47
+ 下面是不同工具/环境下可能会读取 `"module"` 字段的情况:
48
+
49
+ ---
50
+
51
+ ### ✅ **什么情况下会加载 `"module"` 字段?**
52
+
53
+ #### **打包工具(Webpack、Rollup、Vite、Snowpack, Parcel 等)**
54
+
55
+ - 当你使用这些工具打包代码时,它们会优先尝试读取:
56
+ 1. `"exports"` 字段(如果存在,优先于其他字段)
57
+ 2. `"module"` 字段(通常表示 ESM 格式)
58
+ 3. `"main"` 字段(通常表示 CommonJS 格式)
59
+
60
+ 示例:
61
+
62
+ ```js
63
+ // 在 Webpack 中引入某个 npm 包时,如果该包的 package.json 有 module 字段
64
+ // Webpack 会优先使用这个字段所指向的 ESM 文件
65
+ import foo from 'icebreaker-npm-basic-package'
66
+ ```
67
+
68
+ > `Vite、Snowpack, Parcel` 这些工具天生以 ESM 为主,会优先读取 `"module"` 字段。
69
+
70
+ ---
71
+
72
+ ### 🚫 **不会加载 `"module"` 字段的情况**
73
+
74
+ #### **Node.js 本身**
75
+
76
+ - Node.js 并不识别 `"module"` 字段,加载模块时它依赖的是:
77
+ - `"type"` 字段(决定是否为 ESM 模式)
78
+ - `"main"` 字段(默认入口)
79
+ - 或者直接通过 `"exports"` 字段(推荐现代做法)
80
+
81
+ 例如,在你的 `package.json` 中:
82
+
83
+ ```json
84
+ {
85
+ "type": "module",
86
+ "main": "index.cjs",
87
+ "module": "index.js"
88
+ }
89
+ ```
90
+
91
+ - 你运行 `node .` 时,Node 会根据 `"main"` 加载 `index.cjs`
92
+ - 如果你运行 `node index.js`,它会根据文件扩展名和 `"type": "module"` 以 ESM 模式运行,但并不会自动从 `"module"` 字段寻找入口
93
+
94
+ ---
95
+
96
+ ### 推荐现代做法(如要兼容多种环境):
97
+
98
+ 可以使用 `exports` 字段更明确地配置入口文件:
99
+
100
+ ```jsonc
101
+ {
102
+ "exports": {
103
+ ".": {
104
+ "types": "./index.d.ts",
105
+ "require": "./index.cjs",
106
+ "import": "./index.js"
107
+ },
108
+ "./xxx": {
109
+ "types": "./xxx.d.ts",
110
+ "require": "./xxx.cjs",
111
+ "import": "./xxx.js"
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ 这样,Node.js 和打包工具都能正确识别和区分 ESM 和 CommonJS。
118
+
119
+ ---
120
+
121
+ ### 总结:
122
+
123
+ | 环境/工具 | 是否使用 `"module"` 字段 | 说明 |
124
+ | -------------- | ------------------------ | ----------------------------- |
125
+ | Node.js | ❌ 不会使用 | 使用 `"main"` 或 `"exports"` |
126
+ | Webpack/Rollup | ✅ 会使用 | 优先用来加载 ESM 版本 |
127
+ | Vite/Snowpack | ✅ 会使用 | 用于选择 ESM 格式 |
128
+ | TypeScript | ❌ 不直接使用 | 会用 `"types"` 字段找类型声明 |