Просмотр исходного кода

feat: add initial chunk module analysis and update null-loader rules for server-only packages

Yuki Takei 1 месяц назад
Родитель
Сommit
64e187c863

+ 2 - 1
.kiro/specs/reduce-modules-loaded/analysis-ledger.md

@@ -24,7 +24,8 @@ Measured via `ChunkModuleStatsPlugin` in `next.config.utils.js`. The `initial` c
 |------|------|---------|------------|-------|------------------|------|
 | **Baseline (no Phase 2 changes)** | 8.1 | **2,704** | 4,146 | 6,850 | 10,068 | 2026-02-20 |
 | + MermaidViewer dynamic + date-fns subpath | 8.3 | **2,128** | 4,717 | 6,845 | 10,058 | 2026-02-20 |
-| + date-fns locale subpath imports | 8.N | **1,630** | 4,717 | 6,347 | 9,062 | 2026-02-20 |
+| + date-fns locale subpath imports | 8.4 | **1,630** | 4,717 | 6,347 | 9,062 | 2026-02-20 |
+| + null-loader: i18next-fs-backend, bunyan, bunyan-format | 8.N | **1,572** | 4,720 | 6,292 | 9,007 | 2026-02-20 |
 
 > **Note**: Originally reported baseline was 51.5s, but automated measurement on the same machine consistently shows ~31s. The 51.5s figure may reflect cold cache, different system load, or an earlier codebase state.
 

+ 6 - 0
.kiro/specs/reduce-modules-loaded/tasks.md

@@ -181,6 +181,12 @@ The following loop repeats until the user declares completion:
   - date-fns: 560 → 62 modules in initial chunks
   - _Requirements: 4.1, 6.1_
 
+- [x] 8.5 Loop iteration 3: null-loader expansion for server-only package leaks
+  - Added null-loader rules for `i18next-fs-backend` (server-only filesystem translation backend leaking via next-i18next), `bunyan` (server-only logging; client uses browser-bunyan via universal-bunyan), and `bunyan-format` (server-only log formatter)
+  - Null-loading bunyan eliminated its entire transitive dependency tree: mv, ncp, mkdirp, rimraf, glob, source-map, source-map-support, and other Node.js utilities
+  - Result: initial: 1,572 (-58, -3.6%) / async-only: 4,720 / total: 6,292 / compiled: 9,007
+  - _Requirements: 3.1, 3.2, 6.1_
+
 - [ ] 8.N Loop iteration N: (next iteration — measure, analyze, propose, implement)
 
 ## Phase 3: Next.js Version Upgrade Evaluation (Deferred)

+ 253 - 0
apps/app/initial-modules-analysis.md

@@ -0,0 +1,253 @@
+# Initial Chunk Module Analysis
+
+Total initial modules: 1572
+App modules (non-node_modules): 24
+node_modules packages: 218
+
+## Top Packages by Module Count
+| # | Package | Modules |
+|---|---------|---------|
+| 1 | next | 417 |
+| 2 | core-js | 216 |
+| 3 | source-map-loader | 95 |
+| 4 | katex | 63 |
+| 5 | date-fns | 62 |
+| 6 | axios | 50 |
+| 7 | mdast-util-to-markdown | 46 |
+| 8 | @babel/runtime | 40 |
+| 9 | mdast-util-to-hast | 29 |
+| 10 | micromark-core-commonmark | 23 |
+| 11 | next-superjson | 21 |
+| 12 | property-information | 18 |
+| 13 | next-i18next | 16 |
+| 14 | react-i18next | 15 |
+| 15 | parse5 | 14 |
+| 16 | superjson | 11 |
+| 17 | hast-util-select | 11 |
+| 18 | micromark | 11 |
+| 19 | swr | 9 |
+| 20 | micromark-extension-directive | 9 |
+| 21 | stringify-entities | 9 |
+| 22 | css-selector-parser | 8 |
+| 23 | math-intrinsics | 8 |
+| 24 | jotai | 7 |
+| 25 | es-errors | 7 |
+| 26 | react | 6 |
+| 27 | i18next-hmr | 6 |
+| 28 | vfile | 6 |
+| 29 | call-bind-apply-helpers | 5 |
+| 30 | entities | 5 |
+| 31 | micromark-extension-gfm-table | 5 |
+| 32 | micromark-extension-math | 5 |
+| 33 | micromark-util-symbol | 5 |
+| 34 | qs | 5 |
+| 35 | i18next-http-backend | 4 |
+| 36 | universal-bunyan | 4 |
+| 37 | @ungap/structured-clone | 4 |
+| 38 | hastscript | 4 |
+| 39 | micromark-extension-frontmatter | 4 |
+| 40 | @swc/helpers | 3 |
+| 41 | react-dom | 3 |
+| 42 | get-proto | 3 |
+| 43 | hast-util-sanitize | 3 |
+| 44 | micromark-extension-gfm-autolink-literal | 3 |
+| 45 | micromark-extension-gfm-footnote | 3 |
+| 46 | micromark-extension-gfm-strikethrough | 3 |
+| 47 | micromark-extension-gfm-task-list-item | 3 |
+| 48 | nth-check | 3 |
+| 49 | unified | 3 |
+| 50 | unist-util-visit-parents | 3 |
+| 51 | scheduler | 2 |
+| 52 | dequal | 2 |
+| 53 | escape-string-regexp | 2 |
+| 54 | i18next | 2 |
+| 55 | react-is | 2 |
+| 56 | styled-jsx | 2 |
+| 57 | use-sync-external-store | 2 |
+| 58 | debug | 2 |
+| 59 | estree-util-is-identifier-name | 2 |
+| 60 | function-bind | 2 |
+| 61 | github-slugger | 2 |
+| 62 | gopd | 2 |
+| 63 | has-symbols | 2 |
+| 64 | hast-util-from-dom | 2 |
+| 65 | hast-util-from-parse5 | 2 |
+| 66 | hast-util-has-property | 2 |
+| 67 | hast-util-heading-rank | 2 |
+| 68 | hast-util-is-element | 2 |
+| 69 | hast-util-parse-selector | 2 |
+| 70 | hast-util-raw | 2 |
+| 71 | hast-util-to-jsx-runtime | 2 |
+| 72 | hast-util-to-parse5 | 2 |
+| 73 | hast-util-to-string | 2 |
+| 74 | hast-util-to-text | 2 |
+| 75 | hast-util-whitespace | 2 |
+| 76 | html-url-attributes | 2 |
+| 77 | mdast-util-directive | 2 |
+| 78 | mdast-util-find-and-replace | 2 |
+| 79 | mdast-util-from-markdown | 2 |
+| 80 | mdast-util-frontmatter | 2 |
+| 81 | mdast-util-gfm-autolink-literal | 2 |
+| 82 | mdast-util-gfm-footnote | 2 |
+| 83 | mdast-util-gfm-strikethrough | 2 |
+| 84 | mdast-util-gfm-table | 2 |
+| 85 | mdast-util-gfm-task-list-item | 2 |
+| 86 | mdast-util-gfm | 2 |
+| 87 | mdast-util-math | 2 |
+| 88 | mdast-util-newline-to-break | 2 |
+| 89 | mdast-util-phrasing | 2 |
+| 90 | mdast-util-to-string | 2 |
+| 91 | micromark-extension-gfm-tagfilter | 2 |
+| 92 | micromark-util-subtokenize | 2 |
+| 93 | parse-entities | 2 |
+| 94 | react-markdown | 2 |
+| 95 | rehype-katex | 2 |
+| 96 | rehype-raw | 2 |
+| 97 | rehype-sanitize | 2 |
+| 98 | rehype-slug | 2 |
+| 99 | remark-breaks | 2 |
+| 100 | remark-directive | 2 |
+| 101 | remark-frontmatter | 2 |
+| 102 | remark-gfm | 2 |
+| 103 | remark-math | 2 |
+| 104 | remark-parse | 2 |
+| 105 | remark-rehype | 2 |
+| 106 | style-to-object | 2 |
+| 107 | unist-util-find-after | 2 |
+| 108 | unist-util-is | 2 |
+| 109 | unist-util-position | 2 |
+| 110 | unist-util-stringify-position | 2 |
+| 111 | unist-util-visit | 2 |
+| 112 | uvu | 2 |
+| 113 | vfile-location | 2 |
+| 114 | vfile-message | 2 |
+| 115 | @browser-bunyan/console-formatted-stream | 1 |
+| 116 | @browser-bunyan/levels | 1 |
+| 117 | balanced-match | 1 |
+| 118 | base64-js | 1 |
+| 119 | brace-expansion | 1 |
+| 120 | browser-bunyan | 1 |
+| 121 | bson-objectid | 1 |
+| 122 | buffer | 1 |
+| 123 | bunyan-format | 1 |
+| 124 | bunyan | 1 |
+| 125 | concat-map | 1 |
+| 126 | copy-anything | 1 |
+| 127 | cross-fetch | 1 |
+| 128 | hoist-non-react-statics | 1 |
+| 129 | html-parse-stringify | 1 |
+| 130 | i18next-chained-backend | 1 |
+| 131 | i18next-fs-backend | 1 |
+| 132 | i18next-localstorage-backend | 1 |
+| 133 | ieee754 | 1 |
+| 134 | is-what | 1 |
+| 135 | js-cookie | 1 |
+| 136 | minimatch | 1 |
+| 137 | mongoose | 1 |
+| 138 | next-superjson-plugin | 1 |
+| 139 | void-elements | 1 |
+| 140 | @emoji-mart/data | 1 |
+| 141 | ansi-regex | 1 |
+| 142 | bail | 1 |
+| 143 | bcp-47-match | 1 |
+| 144 | boolbase | 1 |
+| 145 | call-bound | 1 |
+| 146 | ccount | 1 |
+| 147 | character-entities-html4 | 1 |
+| 148 | character-entities-legacy | 1 |
+| 149 | character-reference-invalid | 1 |
+| 150 | comma-separated-tokens | 1 |
+| 151 | csv-to-markdown-table | 1 |
+| 152 | decode-named-character-reference | 1 |
+| 153 | devlop | 1 |
+| 154 | diff | 1 |
+| 155 | direction | 1 |
+| 156 | dunder-proto | 1 |
+| 157 | emoji-regex | 1 |
+| 158 | es-define-property | 1 |
+| 159 | es-object-atoms | 1 |
+| 160 | extend | 1 |
+| 161 | fault | 1 |
+| 162 | format | 1 |
+| 163 | get-intrinsic | 1 |
+| 164 | hasown | 1 |
+| 165 | hast-util-from-html-isomorphic | 1 |
+| 166 | html-void-elements | 1 |
+| 167 | inline-style-parser | 1 |
+| 168 | is-absolute-url | 1 |
+| 169 | is-alphabetical | 1 |
+| 170 | is-alphanumerical | 1 |
+| 171 | is-decimal | 1 |
+| 172 | is-fullwidth-code-point | 1 |
+| 173 | is-hexadecimal | 1 |
+| 174 | is-plain-obj | 1 |
+| 175 | kleur | 1 |
+| 176 | lodash.debounce | 1 |
+| 177 | longest-streak | 1 |
+| 178 | markdown-table | 1 |
+| 179 | mdast-util-wiki-link | 1 |
+| 180 | micromark-extension-gfm | 1 |
+| 181 | micromark-extension-wiki-link | 1 |
+| 182 | micromark-factory-destination | 1 |
+| 183 | micromark-factory-label | 1 |
+| 184 | micromark-factory-space | 1 |
+| 185 | micromark-factory-title | 1 |
+| 186 | micromark-factory-whitespace | 1 |
+| 187 | micromark-util-character | 1 |
+| 188 | micromark-util-chunked | 1 |
+| 189 | micromark-util-classify-character | 1 |
+| 190 | micromark-util-combine-extensions | 1 |
+| 191 | micromark-util-decode-numeric-character-reference | 1 |
+| 192 | micromark-util-decode-string | 1 |
+| 193 | micromark-util-encode | 1 |
+| 194 | micromark-util-html-tag-name | 1 |
+| 195 | micromark-util-normalize-identifier | 1 |
+| 196 | micromark-util-resolve-all | 1 |
+| 197 | micromark-util-sanitize-uri | 1 |
+| 198 | ms | 1 |
+| 199 | next-dynamic-loading-props | 1 |
+| 200 | next-themes | 1 |
+| 201 | object-inspect | 1 |
+| 202 | react-error-boundary | 1 |
+| 203 | side-channel-list | 1 |
+| 204 | side-channel-map | 1 |
+| 205 | side-channel-weakmap | 1 |
+| 206 | side-channel | 1 |
+| 207 | space-separated-tokens | 1 |
+| 208 | string-width | 1 |
+| 209 | strip-ansi | 1 |
+| 210 | throttle-debounce | 1 |
+| 211 | trim-lines | 1 |
+| 212 | trough | 1 |
+| 213 | ts-deepmerge | 1 |
+| 214 | url-join | 1 |
+| 215 | usehooks-ts | 1 |
+| 216 | web-namespaces | 1 |
+| 217 | zwitch | 1 |
+| 218 | object-inspect|. | 1 |
+
+## App Modules (first 200)
+- json|/workspace/growi-reduce-modules-loaded/apps/app/package.json
+- webpack/runtime/react refresh
+- webpack/runtime/hot module replacement
+- webpack/runtime/compat
+- webpack/runtime/trusted types script
+- webpack/runtime/jsonp chunk loading
+- webpack/runtime/chunk loaded
+- webpack/runtime/make namespace object
+- webpack/runtime/define property getters
+- webpack/runtime/publicPath
+- webpack/runtime/node module decorator
+- webpack/runtime/global
+- webpack/runtime/getFullHash
+- webpack/runtime/compat get default export
+- webpack/runtime/ensure chunk
+- webpack/runtime/create fake namespace object
+- webpack/runtime/nonce
+- webpack/runtime/hasOwnProperty shorthand
+- webpack/runtime/trusted types policy
+- webpack/runtime/get update manifest filename
+- webpack/runtime/load script
+- webpack/runtime/get javascript update chunk filename
+- webpack/runtime/get javascript chunk filename
+- webpack/runtime/trusted types script url

+ 3 - 0
apps/app/next.config.js

@@ -127,6 +127,9 @@ module.exports = (phase) => {
             /dtrace-provider/,
             /mongoose/,
             /mathjax-full/, // required from marp
+            /i18next-fs-backend/, // server-only filesystem translation backend (leaks via next-i18next)
+            /\/bunyan\//, // server-only logging (client uses browser-bunyan via universal-bunyan)
+            /bunyan-format/, // server-only log formatter (client uses @browser-bunyan/console-formatted-stream)
           ].map((packageRegExp) => {
             return {
               test: packageRegExp,