vite-plugin-resource-waste 1.2.0 → 1.2.2

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 (2) hide show
  1. package/dist/index.js +7 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import M from'fs';import S from'path';var _={root:"src",reportDir:"resource-waste",wasteThresholdKb:300,failOnThreshold:false,htmlReport:true,scanImportPatterns:true,scanUnusedImports:true,scanUnreachable:true,scanCacheStrategy:true,scanDuplicateDeps:true,include:[],exclude:["**/*.spec.*","**/*.test.*","**/__tests__/**","**/node_modules/**"],silent:false},W=[".ts",".tsx",".js",".jsx",".vue",".svelte"],D=[".js",".css",".woff",".woff2",".ttf",".png",".jpg",".jpeg",".gif",".webp",".svg",".ico"],U=/\.[a-f0-9]{8,}\.(js|css|woff2?|ttf|png|jpe?g|gif|webp|svg|ico)$/i,L=[[/import\s+_\s+from\s+['"]lodash['"]/,"lodash","high",68],[/import\s+\*\s+as\s+\w+\s+from\s+['"]lodash['"]/,"lodash","high",68],[/import\s+\w+\s+from\s+['"]moment['"]/,"moment","high",65],[/import\s+\*\s+as\s+\w+\s+from\s+['"]antd['"]/,"antd","high",200],[/import\s+\*\s+as\s+\w+\s+from\s+['"]@ant-design\/icons['"]/,"@ant-design/icons","medium",80],[/import\s+['"][^'"]+\.css['"]\s*;\s*\/\/\s*unused/i,"css","medium",10]],H={lodash:"\u6539\u4E3A import debounce from 'lodash-es/debounce' \u6216\u6309\u9700\u5BFC\u5165",moment:"\u6539\u7528 dayjs \u6216 date-fns \u6309\u9700\u5BFC\u5165",antd:"\u6539\u7528 antd \u6309\u9700\u5BFC\u5165\u6216 unplugin-vue-components","@ant-design/icons":"\u6539\u4E3A\u6309\u9700\u5BFC\u5165\u5177\u4F53\u56FE\u6807",css:"\u79FB\u9664\u672A\u4F7F\u7528\u7684 CSS \u526F\u4F5C\u7528 import"};function c(e){return e.split(S.sep).join("/")}function R(e){try{return M.readFileSync(e,"utf-8")}catch{return ""}}function E(e){try{let t=M.statSync(e);return Math.round(t.size/1024*100)/100}catch{return 0}}function y(e){return Math.round(e*.45*10)/10}function V(e){let t=c(e),o=t.lastIndexOf("node_modules/");if(o===-1)return null;let s=t.slice(0,o+13),n=t.slice(o+13).split("/");if(n[0]?.startsWith("@")&&n[1]){let i=`${n[0]}/${n[1]}`,a=q(S.join(s,i));return {name:i,version:a}}if(n[0]){let i=n[0],a=q(S.join(s,i));return {name:i,version:a}}return null}function q(e){try{let t=S.join(e,"package.json");return JSON.parse(M.readFileSync(t,"utf-8")).version}catch{return}}function w(e,t){return S.isAbsolute(t)?t:S.resolve(e,t)}function h(e,t){return `${e}-${t}`}function j(e){M.mkdirSync(e,{recursive:true});}function v(e,t){return c(S.relative(e,t))}function G(e){if(!e.options.scanCacheStrategy)return [];let t=[],o=0;for(let s of e.bundleFiles){if(s.type!=="asset")continue;let r=be(s.fileName);if(!D.includes(r))continue;let n=Math.round(s.size/1024*100)/100;if(!U.test(s.fileName)){let a=/\.(woff2?|ttf|otf)$/i.test(s.fileName),u=n>100;t.push({id:h("cache-miss",o++),category:"cache-miss",severity:u||a?"high":"medium",title:"\u4EA7\u7269\u6587\u4EF6\u540D\u7F3A\u5C11 content hash",file:s.fileName,detail:`\u9759\u6001\u8D44\u6E90 ${s.fileName} (${n} KB) \u672A\u5305\u542B content hash\uFF0C\u6D4F\u89C8\u5668\u96BE\u4EE5\u5B89\u5168\u957F\u671F\u7F13\u5B58\uFF0C\u56DE\u8BBF\u7528\u6237\u53EF\u80FD\u91CD\u590D\u4E0B\u8F7D\u3002`,suggestion:a?"\u914D\u7F6E vite build.assetsInlineLimit \u4E0E rollup assetFileNames \u542B [hash]\uFF1BCDN \u8BBE\u7F6E immutable \u7F13\u5B58\u3002":"\u5728 vite.config \u4E2D\u8BBE\u7F6E build.rollupOptions.output.assetFileNames \u5305\u542B [hash] \u5360\u4F4D\u7B26\u3002",cost:{transferKb:n,parseMsEstimate:a?y(n*.1):0,description:u?`\u56DE\u8BBF\u7528\u6237\u53EF\u80FD\u91CD\u590D\u4F20\u8F93 ${n} KB`:"\u7F13\u5B58\u547D\u4E2D\u7387\u4F4E\u5BFC\u81F4\u91CD\u590D\u9A8C\u8BC1\u6210\u672C"},metadata:{sizeKb:n,extension:r,hasContentHash:false}});}}return t}function be(e){let t=e.lastIndexOf(".");return t===-1?"":e.slice(t).toLowerCase()}function J(e){if(!e.options.scanDuplicateDeps)return [];let t=new Map,o=0,s=[];for(let r of e.bundleFiles)if(r.type==="chunk")for(let n of r.modules??[]){let i=V(n);if(!i?.version)continue;t.has(i.name)||t.set(i.name,new Map);let a=t.get(i.name);a.set(i.version,(a.get(i.version)??0)+1);}for(let[r,n]of t){if(n.size<=1)continue;let i=[...n.entries()],a=i.reduce((l,[,m])=>l+m,0),u=Math.max(5,Math.round(a*3));s.push({id:h("duplicate-dep",o++),category:"duplicate-dependency",severity:"medium",title:`\u91CD\u590D\u4F9D\u8D56\u7248\u672C: ${r}`,file:r,detail:`\u4F9D\u8D56 ${r} \u5728\u4EA7\u7269\u4E2D\u51FA\u73B0\u591A\u4E2A\u7248\u672C: ${i.map(([l,m])=>`${l}(${m}\u6B21)`).join(", ")}\u3002`,suggestion:`\u4F7F\u7528 package.json overrides / pnpm.overrides \u7EDF\u4E00 ${r} \u7248\u672C\uFF0C\u907F\u514D\u91CD\u590D\u6253\u5305\u4E0E\u7F13\u5B58\u5931\u6548\u3002`,cost:{transferKb:u,parseMsEstimate:y(u),description:`\u9884\u4F30\u91CD\u590D\u4F20\u8F93\u7EA6 ${u} KB`},metadata:{packageName:r,versions:Object.fromEntries(i)}});}return s}function X(e){let t=[],o=0;for(let[s,r]of e.parsedModules){if(s.includes("node_modules")||s.startsWith("\0")||!r.code)continue;let n=[...r.code.matchAll(/export\s+(?:const|function|class|type|interface)\s+(\w+)/g)];if(n.length!==0&&n.length>=8&&r.importers.size<=1){let i=Math.round(r.code.length/1024*.3);t.push({id:h("unused-export",o++),category:"static-unused-js",severity:"low",title:"\u7591\u4F3C\u8FC7\u591A\u672A\u4F7F\u7528 export",file:s,detail:`${s} \u5BFC\u51FA\u4E86 ${n.length} \u4E2A\u7B26\u53F7\uFF0C\u4F46\u4EC5\u88AB ${r.importers.size} \u4E2A\u6A21\u5757\u5F15\u7528\uFF0C\u53EF\u80FD\u5B58\u5728\u672A\u4F7F\u7528\u7684 export\u3002`,suggestion:"\u4F7F\u7528 Knip \u6216 ESLint \u8FDB\u4E00\u6B65\u786E\u8BA4\uFF0C\u79FB\u9664\u672A\u4F7F\u7528\u7684 export \u4EE5\u6539\u5584 tree-shaking\u3002",cost:{transferKb:i,parseMsEstimate:y(i),description:"\u4FDD\u5B88\u4F30\u8BA1\uFF0C\u9700\u7ED3\u5408\u9759\u6001\u5206\u6790\u5DE5\u5177\u786E\u8BA4"},metadata:{exportCount:n.length,importerCount:r.importers.size}});}}return t}function Z(e,t){let o=c(e);for(let s of t)if(s.includes("*.spec.")&&/\.spec\.(tsx?|jsx?)$/.test(o)||s.includes("*.test.")&&/\.test\.(tsx?|jsx?)$/.test(o)||s.includes("__tests__")&&o.includes("__tests__")||s.includes("node_modules")&&o.includes("node_modules"))return true;return false}function Q(e,t,o){let s=[],r=new Set(t.map(i=>i.toLowerCase()));function n(i){let a;try{a=M.readdirSync(i,{withFileTypes:!0});}catch{return}for(let u of a){let l=S.join(i,u.name),m=c(S.relative(e,l));if(u.isDirectory()){if(Z(m+"/",o))continue;n(l);continue}if(!u.isFile()||Z(m,o))continue;let p=S.extname(u.name).toLowerCase();r.has(p)&&s.push(c(l));}}return n(e),s}async function ee(e){if(!e.options.scanImportPatterns)return [];let t=[],o=0;for(let s of e.sourceFiles){let r=R(s);if(!r)continue;let n=v(e.projectRoot,s);for(let[l,m,p,f]of L){if(!l.test(r))continue;let d=Math.round(f*.35);t.push({id:h("import-pattern",o++),category:"import-pattern",severity:p,title:`\u5168\u91CF/\u4F4E\u6548\u5BFC\u5165: ${m}`,file:n,detail:`${n} \u5B58\u5728\u53EF\u80FD\u5BFC\u81F4 tree-shake \u5931\u6548\u7684\u5BFC\u5165\uFF08${m}\uFF09\u3002`,suggestion:H[m]??"\u6539\u4E3A\u6309\u9700\u5BFC\u5165",cost:{transferKb:d,parseMsEstimate:y(d),description:`\u9884\u4F30 gzip \u540E\u7EA6 ${d} KB`},metadata:{packageName:m}});}let i=/export\s+default/.test(r),a=/export\s+(const|function|class|type|interface|\{)/.test(r);/export\s+\*\s+from/.test(r)&&t.push({id:h("import-pattern",o++),category:"import-pattern",severity:"medium",title:"Barrel \u6587\u4EF6\u53EF\u80FD\u5BFC\u81F4 tree-shake \u5931\u6548",file:n,detail:`${n} \u4F7F\u7528\u4E86 export * from \u6A21\u5F0F\uFF0C\u5BB9\u6613\u5BFC\u81F4\u672A\u4F7F\u7528\u7684\u6A21\u5757\u88AB\u4E00\u5E76\u6253\u5305\u3002`,suggestion:"\u6539\u4E3A\u663E\u5F0F\u5177\u540D\u5BFC\u51FA\uFF0C\u6216\u76F4\u63A5\u4ECE\u6E90\u6587\u4EF6\u6309\u9700\u5BFC\u5165\u3002",cost:{transferKb:15,parseMsEstimate:y(15),description:"Barrel \u6587\u4EF6\u95F4\u63A5\u5F15\u5165\u7684\u5197\u4F59\u4F53\u79EF\u96BE\u4EE5\u7CBE\u786E\u91CF\u5316\uFF0C\u6B64\u4E3A\u4FDD\u5B88\u4F30\u8BA1"}}),!i&&!a&&n.includes("/components/")&&r.trim().length<20&&t.push({id:h("static-unused",o++),category:"static-unused-js",severity:"low",title:"\u7591\u4F3C\u7A7A\u7EC4\u4EF6\u6587\u4EF6",file:n,detail:`${n} \u51E0\u4E4E\u6CA1\u6709\u6709\u6548\u5185\u5BB9\uFF0C\u53EF\u80FD\u662F\u9057\u7559\u6587\u4EF6\u3002`,suggestion:"\u786E\u8BA4\u662F\u5426\u4ECD\u9700\u8981\uFF0C\u4E0D\u9700\u8981\u5219\u5220\u9664\u3002",cost:{transferKb:0,parseMsEstimate:0,description:"\u7EF4\u62A4\u6210\u672C\u6D6A\u8D39"}});}return t}async function A(e){let t=S.resolve(e.projectRoot,e.options.root??"src"),o=[...W,...(e.options.include??[]).map(s=>S.extname(s)).filter(Boolean)];return Q(t,o,e.options.exclude??[])}function te(e){let t=new Set,o=[...e.entries];for(;o.length;){let s=o.shift();if(t.has(s))continue;t.add(s);let r=e.parsedModules.get(s);if(r)for(let n of r.importedIds)t.has(n)||o.push(n);}return t}function xe(e){let t=new Set;for(let o of e.bundleFiles)if(!(o.type!=="chunk"||!o.modules))for(let s of o.modules)t.add(c(s));return t}function ve(e,t){if(t.size===0)return false;let o=c(e);for(let s of t)if(s===o||s.endsWith(o)||o.endsWith(s))return true;return false}function oe(e,t){if(!t.startsWith("."))return null;let o=S.resolve(S.dirname(e),t);if(S.extname(o))return M.existsSync(o)?c(o):null;let s=[".ts",".tsx",".js",".jsx",".vue",".svelte",".mjs",".cjs"];for(let r of s){let n=o+r;if(M.existsSync(n))return c(n)}for(let r of s){let n=S.join(o,"index"+r);if(M.existsSync(n))return c(n)}return null}function Re(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}function re(e){let t=e.match(/<script(?:\s+[^>]*)?>([\s\S]*?)<\/script>/i)?.[1]??"",r=e.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<\/?template[^>]*>/gi,"");return {script:t,template:r}}function ie(e){let t=e.replace(/^\s*import\s+['"][^'"]+['"]\s*;?\s*$/gm,"");return t=t.replace(/import\s+(?:type\s+)?(?:(?!\n\s*import)[\s\S])*?\s+from\s+['"][^'"]+['"]\s*;?/g,""),t}function se(e){return e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")}function we(e){let t=e.trim();if(!t||t.startsWith("type ")||/\bimport\s/.test(t))return [];let o=[],s=t.match(/^\*\s+as\s+(\w+)(?:\s*,\s*(.+))?$/);if(s)return o.push(s[1]),s[2]&&o.push(...ne(s[2])),o.filter(P);let r=t.indexOf("{");if(r===-1){let i=t.replace(/,$/,"").trim();return P(i)&&o.push(i),o}let n=t.slice(0,r).replace(/,$/,"").trim();return P(n)&&o.push(n),o.push(...ne(t.slice(r))),o.filter(P)}function P(e){return /^\w+$/.test(e)}function $e(e){let t=[],o=e.split(`
2
- `),s="",r=false,n=()=>{s.trim()&&t.push(s.trim()),s="",r=false;};for(let i of o){let a=i.trim();if(!r&&a.startsWith("import ")?(r=true,s=i):r&&(s+=`
3
- ${i}`),!!r){if(/^import\s+['"][^'"]+['"]\s*;?\s*$/.test(s.trim())){n();continue}/from\s+['"][^'"]+['"]\s*;?\s*$/.test(a)&&n();}}return r&&s.trim()&&t.push(s.trim()),t}function Me(e){return /^import\s+['"][^'"]+['"]\s*;?\s*$/.test(e.trim())}function ne(e){let t=[],o=e.match(/\{([\s\S]*)\}/)?.[1]??e;for(let s of o.split(",")){let r=s.trim();if(!r||r.startsWith("type "))continue;let n=r.match(/(?:\w+\s+as\s+)?(\w+)\s*$/);n&&t.push(n[1]);}return t}function ae(e){let t=[];for(let o of $e(e)){if(Me(o)||/^\s*import\s+type\s+/.test(o))continue;let s=o.match(/^\s*import\s+(?:type\s+)?([\s\S]+?)\s+from\s+['"]([^'"]+)['"]\s*;?\s*$/);if(!s)continue;let r=s[1].trim(),n=s[2];if(!(!r||r.startsWith("type ")||/\bimport\s/.test(r)))for(let i of we(r))t.push({localName:i,specifier:n});}return t}function ue(e,t,o){let s=se(t),r=new RegExp(`\\b${e}\\b`);if(r.test(s))return true;if(!o)return false;let n=se(o);if(r.test(n))return true;let i=Re(e);return !!(i!==e.toLowerCase()&&new RegExp(`<${i}[\\s/>]`,"i").test(n))}function Ee(e){let t=new Map;for(let o of e.sourceFiles){let s=R(o);if(!s)continue;let r=c(o),n=o.endsWith(".vue"),{script:i,template:a}=n?re(s):{script:s,template:""},u=ie(n?i:s);for(let{localName:l,specifier:m}of ae(i)){if(!m.startsWith(".")||!ue(l,u,a))continue;let p=oe(o,m);if(!p)continue;let f=t.get(r)??new Set;f.add(c(p)),t.set(r,f);}}return t}function Ce(e,t){let o=new Set(e.sourceFiles.map(i=>c(i))),s=new Set,r=[],n=i=>{let a=c(i);o.has(a)&&!s.has(a)&&r.push(a);};for(let i of e.entries){n(i);let a=e.parsedModules.get(c(i));if(a)for(let u of a.importedIds)n(u);}for(let i of e.sourceFiles){let a=c(i);e.parsedModules.get(a)?.isEntry&&n(a);}if(r.length===0)return o;for(;r.length;){let i=r.shift();if(!s.has(i)){s.add(i);for(let a of t.get(i)??[])s.has(a)||r.push(a);}}return s}function Pe(e,t){let o=e.endsWith(".vue"),{script:s,template:r}=o?re(t):{script:t,template:""},n=ie(o?s:t),i=[];for(let{localName:a,specifier:u}of ae(s))u.startsWith(".")&&(ue(a,n,r)||i.push({localName:a,specifier:u,resolved:oe(e,u)}));return i}function ce(e){return /\.(vue|tsx|jsx)$/i.test(e)&&/pages?|views?|components?|routes?/i.test(e)}function Fe(e,t,o){let s=ce(e);return t?"medium":o?"low":s?"medium":"low"}function le(e){if(!e.options.scanUnusedImports)return [];let t=[],o=xe(e),s=o.size>0,r=Ee(e),n=Ce(e,r),i=0;for(let a of e.sourceFiles){let u=c(a);if(!n.has(u))continue;let l=R(a);if(!l)continue;let m=v(e.projectRoot,a),p=Pe(a,l);if(p.length!==0)for(let{localName:f,specifier:d,resolved:g}of p){let I=g?v(e.projectRoot,g):d,b=g?ve(g,o):false,F=Fe(I,b,s),$=g?E(g):0,Ie=b?`${m} \u5F15\u5165\u4E86 \`${I}\`\uFF08\u7ED1\u5B9A \`${f}\`\uFF09\u4F46\u672A\u5728\u6587\u4EF6\u5185\u4F7F\u7528\u3002\u8BE5\u6A21\u5757\u4ECD\u51FA\u73B0\u5728\u6784\u5EFA\u4EA7\u7269\u4E2D\uFF08\u7EA6 ${$} KB\uFF09\u3002`:`${m} \u5F15\u5165\u4E86 \`${I}\`\uFF08\u7ED1\u5B9A \`${f}\`\uFF09\u4F46\u672A\u5728\u6587\u4EF6\u5185\u4F7F\u7528\u3002`;t.push({id:h("dead-import",i++),category:"dead-import",severity:F,title:`\u672A\u4F7F\u7528\u7684\u9759\u6001 import: ${f}`,file:m,detail:Ie,suggestion:ce(I)?`\u5220\u9664\u5197\u4F59 import\uFF1B\u82E5\u8DEF\u7531/\u9875\u9762\u5DF2\u4E0B\u7EBF\uFF0C\u786E\u8BA4 \`${I}\` \u662F\u5426\u4E5F\u53EF\u79FB\u9664\u3002`:`\u5220\u9664\u672A\u4F7F\u7528\u7684 import \`${f}\` from '${d}'\u3002`,cost:{transferKb:b?$:0,parseMsEstimate:b?y($):0,description:b?`\u5197\u4F59 import \u5BFC\u81F4\u7EA6 ${$} KB \u8FDB\u5165\u4EA7\u7269`:"\u7EF4\u62A4\u6027\u6D6A\u8D39"},metadata:{binding:f,specifier:d,importedModule:I,inBundle:b}});}}return t}function pe(e){if(!e.options.scanUnreachable)return [];let t=[],o=te(e),s=0,r=new Set;for(let n of o){if(n.startsWith("\0")||n.includes("virtual:"))continue;let i=S.isAbsolute(n)?c(n):c(S.resolve(e.projectRoot,n));r.add(i);}for(let n of e.sourceFiles){let i=c(n);if(e.entries.some(g=>c(S.resolve(g))===i))continue;let u=[...r].some(g=>g===i||i.endsWith(g)||g.endsWith(i)),l=e.parsedModules.get(i)??e.parsedModules.get(n),m=l&&l.importers.size>0;if(u||m)continue;let p=E(n),f=v(e.projectRoot,n),d=/pages?|views?|components?|routes?/i.test(f)&&/\.(vue|tsx|jsx)$/.test(f);t.push({id:h("unreachable",s++),category:"unreachable-component",severity:d?"high":"medium",title:d?"\u4E0D\u53EF\u8FBE\u9875\u9762/\u7EC4\u4EF6":"\u4E0D\u53EF\u8FBE\u6E90\u6587\u4EF6",file:f,detail:`${f} \u672A\u51FA\u73B0\u5728\u4EFB\u4F55\u6784\u5EFA\u5165\u53E3\u7684 module graph \u4E2D\uFF0C\u5C5E\u4E8E\u9759\u6001\u4E0D\u53EF\u8FBE\u4EE3\u7801\u3002`,suggestion:d?"\u82E5\u4E1A\u52A1\u5DF2\u4E0B\u7EBF\uFF0C\u5220\u9664\u8BE5\u9875\u9762/\u7EC4\u4EF6\u53CA\u5173\u8054\u9759\u6001\u8D44\u6E90\u3002":"\u786E\u8BA4\u662F\u5426\u4ECD\u88AB\u52A8\u6001\u8DEF\u5F84\u5F15\u7528\uFF1B\u82E5\u65E0\uFF0C\u8BF7\u5220\u9664\u6216\u79FB\u51FA src\u3002",cost:{transferKb:p,parseMsEstimate:y(p),description:`\u6587\u4EF6\u672C\u4F53 ${p} KB\uFF1B\u82E5\u88AB glob \u626B\u5165\u53EF\u80FD\u4EA7\u751F\u66F4\u5927 chunk \u6D6A\u8D39`},metadata:{isPageOrComponent:d}});}return t}function fe(e){let t=[],o=0,s=e.bundleFiles.filter(a=>a.isEntry),r=new Set(e.bundleFiles.filter(a=>a.type==="chunk").map(a=>a.fileName)),n=new Set,i=s.map(a=>a.fileName);for(;i.length;){let a=i.shift();if(n.has(a))continue;n.add(a);let u=e.bundleFiles.find(l=>l.fileName===a);if(u)for(let l of u.imports??[])r.has(l)&&!n.has(l)&&i.push(l);}for(let a of e.bundleFiles){if(a.type!=="chunk"||a.isEntry||n.has(a.fileName))continue;let u=Math.round(a.size/1024*100)/100,l=a.fileName.includes("legacy")||a.fileName.includes("admin");t.push({id:h("orphan-chunk",o++),category:"static-unused-js",severity:"low",title:"\u72EC\u7ACB\u5F02\u6B65 chunk\uFF08\u672A\u88AB\u9759\u6001\u5F15\u7528\uFF09",file:a.fileName,detail:`\u4EA7\u7269 chunk ${a.fileName} (${u} KB) \u4EC5\u901A\u8FC7\u52A8\u6001 import \u52A0\u8F7D\uFF0C\u672C\u8EAB\u4E0D\u662F\u6D6A\u8D39\uFF0C\u4F46\u82E5\u88AB\u5168\u7AD9 prefetch \u5219\u4F1A\u4EA7\u751F\u52A0\u8F7D\u6D6A\u8D39\u3002`,suggestion:"\u68C0\u67E5\u662F\u5426\u5BF9\u8BE5 chunk \u914D\u7F6E\u4E86\u4E0D\u5FC5\u8981\u7684 prefetch/preload\u3002",cost:{transferKb:0,parseMsEstimate:0,description:"\u672C\u8EAB\u4E3A\u6309\u9700\u52A0\u8F7D\uFF1B\u6D6A\u8D39\u53D6\u51B3\u4E8E prefetch \u7B56\u7565"},metadata:{chunkSizeKb:u,dynamicOnly:true,suspiciousPrefetch:l}});}return t}async function K(e){let t=await Promise.all([ee(e),Promise.resolve(le(e)),Promise.resolve(pe(e)),Promise.resolve(fe(e)),Promise.resolve(G(e)),Promise.resolve(J(e)),Promise.resolve(X(e))]);return je(t.flat())}function je(e){let t=new Set;return e.filter(o=>{let s=`${o.category}:${o.file}:${o.title}`;return t.has(s)?false:(t.add(s),true)})}function B(e){let t={high:0,medium:1,low:2};return [...e].sort((o,s)=>{let r=t[o.severity]-t[s.severity];return r!==0?r:s.cost.transferKb-o.cost.transferKb})}function me(e,t,o,s,r){let n=c(t),i=e.get(n)??{id:n,importers:new Set,importedIds:new Set,dynamicImporters:new Set,isEntry:false,code:void 0};i.isEntry=i.isEntry||r,o&&(i.code=o);for(let a of s)i.importedIds.add(c(a));e.set(n,i);for(let a of s){let u=c(a),l=e.get(u)??{id:u,importers:new Set,importedIds:new Set,dynamicImporters:new Set,isEntry:false};l.importers.add(n),e.set(u,l);}}function de(e){let t=[];for(let[o,s]of Object.entries(e))if(s.type==="chunk"){let r=s;t.push({fileName:o,type:"chunk",size:Buffer.byteLength(r.code,"utf-8"),modules:Object.keys(r.modules??{}),isEntry:r.isEntry??false,imports:r.imports,dynamicImports:r.dynamicImports});}else {let n=s.source,i=typeof n=="string"?Buffer.byteLength(n,"utf-8"):n instanceof Uint8Array?n.byteLength:0;t.push({fileName:o,type:"asset",size:i});}return t}function k(e,t){let o=ze(),s={high:0,medium:0,low:0},r=0,n=0;for(let i of e)o[i.category]++,s[i.severity]++,!i.metadata?.informational&&(r+=i.cost.transferKb,n+=i.cost.parseMsEstimate);return {generatedAt:new Date().toISOString(),projectRoot:t.projectRoot,mode:t.mode,outDir:t.outDir,summary:{totalIssues:e.length,totalWasteTransferKb:Math.round(r*100)/100,totalParseMsEstimate:Math.round(n*10)/10,byCategory:o,bySeverity:s},issues:e}}function ze(){return {"static-unused-js":0,"unreachable-component":0,"cache-miss":0,"duplicate-dependency":0,"import-pattern":0,"dead-import":0,"prefetch-waste":0}}function ge(e,t){let{summary:o,issues:s}=e,r=s.slice(0,5);if(console.log(`
1
+ import M from'fs';import S from'path';var _={root:"src",reportDir:"resource-waste",wasteThresholdKb:300,failOnThreshold:false,htmlReport:true,scanImportPatterns:true,scanUnusedImports:true,scanUnreachable:true,scanCacheStrategy:true,scanDuplicateDeps:true,include:[],exclude:["**/*.spec.*","**/*.test.*","**/__tests__/**","**/node_modules/**"],silent:false},W=[".ts",".tsx",".js",".jsx",".vue",".svelte"],D=[".js",".css",".woff",".woff2",".ttf",".png",".jpg",".jpeg",".gif",".webp",".svg",".ico"],U=/\.[a-f0-9]{8,}\.(js|css|woff2?|ttf|png|jpe?g|gif|webp|svg|ico)$/i,L=[[/import\s+_\s+from\s+['"]lodash['"]/,"lodash","high",68],[/import\s+\*\s+as\s+\w+\s+from\s+['"]lodash['"]/,"lodash","high",68],[/import\s+\w+\s+from\s+['"]moment['"]/,"moment","high",65],[/import\s+\*\s+as\s+\w+\s+from\s+['"]antd['"]/,"antd","high",200],[/import\s+\*\s+as\s+\w+\s+from\s+['"]@ant-design\/icons['"]/,"@ant-design/icons","medium",80],[/import\s+['"][^'"]+\.css['"]\s*;\s*\/\/\s*unused/i,"css","medium",10]],H={lodash:"\u6539\u4E3A import debounce from 'lodash-es/debounce' \u6216\u6309\u9700\u5BFC\u5165",moment:"\u6539\u7528 dayjs \u6216 date-fns \u6309\u9700\u5BFC\u5165",antd:"\u6539\u7528 antd \u6309\u9700\u5BFC\u5165\u6216 unplugin-vue-components","@ant-design/icons":"\u6539\u4E3A\u6309\u9700\u5BFC\u5165\u5177\u4F53\u56FE\u6807",css:"\u79FB\u9664\u672A\u4F7F\u7528\u7684 CSS \u526F\u4F5C\u7528 import"};function c(e){return e.split(S.sep).join("/")}function R(e){try{return M.readFileSync(e,"utf-8")}catch{return ""}}function E(e){try{let t=M.statSync(e);return Math.round(t.size/1024*100)/100}catch{return 0}}function y(e){return Math.round(e*.45*10)/10}function V(e){let t=c(e),n=t.lastIndexOf("node_modules/");if(n===-1)return null;let s=t.slice(0,n+13),o=t.slice(n+13).split("/");if(o[0]?.startsWith("@")&&o[1]){let i=`${o[0]}/${o[1]}`,a=q(S.join(s,i));return {name:i,version:a}}if(o[0]){let i=o[0],a=q(S.join(s,i));return {name:i,version:a}}return null}function q(e){try{let t=S.join(e,"package.json");return JSON.parse(M.readFileSync(t,"utf-8")).version}catch{return}}function w(e,t){return S.isAbsolute(t)?t:S.resolve(e,t)}function h(e,t){return `${e}-${t}`}function G(e=new Date){let t=n=>String(n).padStart(2,"0");return `${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())} ${t(e.getHours())}:${t(e.getMinutes())}:${t(e.getSeconds())}`}function j(e){M.mkdirSync(e,{recursive:true});}function v(e,t){return c(S.relative(e,t))}function J(e){if(!e.options.scanCacheStrategy)return [];let t=[],n=0;for(let s of e.bundleFiles){if(s.type!=="asset")continue;let r=Se(s.fileName);if(!D.includes(r))continue;let o=Math.round(s.size/1024*100)/100;if(!U.test(s.fileName)){let a=/\.(woff2?|ttf|otf)$/i.test(s.fileName),u=o>100;t.push({id:h("cache-miss",n++),category:"cache-miss",severity:u||a?"high":"medium",title:"\u4EA7\u7269\u6587\u4EF6\u540D\u7F3A\u5C11 content hash",file:s.fileName,detail:`\u9759\u6001\u8D44\u6E90 ${s.fileName} (${o} KB) \u672A\u5305\u542B content hash\uFF0C\u6D4F\u89C8\u5668\u96BE\u4EE5\u5B89\u5168\u957F\u671F\u7F13\u5B58\uFF0C\u56DE\u8BBF\u7528\u6237\u53EF\u80FD\u91CD\u590D\u4E0B\u8F7D\u3002`,suggestion:a?"\u914D\u7F6E vite build.assetsInlineLimit \u4E0E rollup assetFileNames \u542B [hash]\uFF1BCDN \u8BBE\u7F6E immutable \u7F13\u5B58\u3002":"\u5728 vite.config \u4E2D\u8BBE\u7F6E build.rollupOptions.output.assetFileNames \u5305\u542B [hash] \u5360\u4F4D\u7B26\u3002",cost:{transferKb:o,parseMsEstimate:a?y(o*.1):0,description:u?`\u56DE\u8BBF\u7528\u6237\u53EF\u80FD\u91CD\u590D\u4F20\u8F93 ${o} KB`:"\u7F13\u5B58\u547D\u4E2D\u7387\u4F4E\u5BFC\u81F4\u91CD\u590D\u9A8C\u8BC1\u6210\u672C"},metadata:{sizeKb:o,extension:r,hasContentHash:false}});}}return t}function Se(e){let t=e.lastIndexOf(".");return t===-1?"":e.slice(t).toLowerCase()}function X(e){if(!e.options.scanDuplicateDeps)return [];let t=new Map,n=0,s=[];for(let r of e.bundleFiles)if(r.type==="chunk")for(let o of r.modules??[]){let i=V(o);if(!i?.version)continue;t.has(i.name)||t.set(i.name,new Map);let a=t.get(i.name);a.set(i.version,(a.get(i.version)??0)+1);}for(let[r,o]of t){if(o.size<=1)continue;let i=[...o.entries()],a=i.reduce((l,[,f])=>l+f,0),u=Math.max(5,Math.round(a*3));s.push({id:h("duplicate-dep",n++),category:"duplicate-dependency",severity:"medium",title:`\u91CD\u590D\u4F9D\u8D56\u7248\u672C: ${r}`,file:r,detail:`\u4F9D\u8D56 ${r} \u5728\u4EA7\u7269\u4E2D\u51FA\u73B0\u591A\u4E2A\u7248\u672C: ${i.map(([l,f])=>`${l}(${f}\u6B21)`).join(", ")}\u3002`,suggestion:`\u4F7F\u7528 package.json overrides / pnpm.overrides \u7EDF\u4E00 ${r} \u7248\u672C\uFF0C\u907F\u514D\u91CD\u590D\u6253\u5305\u4E0E\u7F13\u5B58\u5931\u6548\u3002`,cost:{transferKb:u,parseMsEstimate:y(u),description:`\u9884\u4F30\u91CD\u590D\u4F20\u8F93\u7EA6 ${u} KB`},metadata:{packageName:r,versions:Object.fromEntries(i)}});}return s}function Y(e){let t=[],n=0;for(let[s,r]of e.parsedModules){if(s.includes("node_modules")||s.startsWith("\0")||!r.code)continue;let o=[...r.code.matchAll(/export\s+(?:const|function|class|type|interface)\s+(\w+)/g)];if(o.length!==0&&o.length>=8&&r.importers.size<=1){let i=Math.round(r.code.length/1024*.3);t.push({id:h("unused-export",n++),category:"static-unused-js",severity:"low",title:"\u7591\u4F3C\u8FC7\u591A\u672A\u4F7F\u7528 export",file:s,detail:`${s} \u5BFC\u51FA\u4E86 ${o.length} \u4E2A\u7B26\u53F7\uFF0C\u4F46\u4EC5\u88AB ${r.importers.size} \u4E2A\u6A21\u5757\u5F15\u7528\uFF0C\u53EF\u80FD\u5B58\u5728\u672A\u4F7F\u7528\u7684 export\u3002`,suggestion:"\u4F7F\u7528 Knip \u6216 ESLint \u8FDB\u4E00\u6B65\u786E\u8BA4\uFF0C\u79FB\u9664\u672A\u4F7F\u7528\u7684 export \u4EE5\u6539\u5584 tree-shaking\u3002",cost:{transferKb:i,parseMsEstimate:y(i),description:"\u4FDD\u5B88\u4F30\u8BA1\uFF0C\u9700\u7ED3\u5408\u9759\u6001\u5206\u6790\u5DE5\u5177\u786E\u8BA4"},metadata:{exportCount:o.length,importerCount:r.importers.size}});}}return t}function Z(e,t){let n=c(e);for(let s of t)if(s.includes("*.spec.")&&/\.spec\.(tsx?|jsx?)$/.test(n)||s.includes("*.test.")&&/\.test\.(tsx?|jsx?)$/.test(n)||s.includes("__tests__")&&n.includes("__tests__")||s.includes("node_modules")&&n.includes("node_modules"))return true;return false}function Q(e,t,n){let s=[],r=new Set(t.map(i=>i.toLowerCase()));function o(i){let a;try{a=M.readdirSync(i,{withFileTypes:!0});}catch{return}for(let u of a){let l=S.join(i,u.name),f=c(S.relative(e,l));if(u.isDirectory()){if(Z(f+"/",n))continue;o(l);continue}if(!u.isFile()||Z(f,n))continue;let p=S.extname(u.name).toLowerCase();r.has(p)&&s.push(c(l));}}return o(e),s}async function te(e){if(!e.options.scanImportPatterns)return [];let t=[],n=0;for(let s of e.sourceFiles){let r=R(s);if(!r)continue;let o=v(e.projectRoot,s);for(let[l,f,p,m]of L){if(!l.test(r))continue;let d=Math.round(m*.35);t.push({id:h("import-pattern",n++),category:"import-pattern",severity:p,title:`\u5168\u91CF/\u4F4E\u6548\u5BFC\u5165: ${f}`,file:o,detail:`${o} \u5B58\u5728\u53EF\u80FD\u5BFC\u81F4 tree-shake \u5931\u6548\u7684\u5BFC\u5165\uFF08${f}\uFF09\u3002`,suggestion:H[f]??"\u6539\u4E3A\u6309\u9700\u5BFC\u5165",cost:{transferKb:d,parseMsEstimate:y(d),description:`\u9884\u4F30 gzip \u540E\u7EA6 ${d} KB`},metadata:{packageName:f}});}let i=/export\s+default/.test(r),a=/export\s+(const|function|class|type|interface|\{)/.test(r);/export\s+\*\s+from/.test(r)&&t.push({id:h("import-pattern",n++),category:"import-pattern",severity:"medium",title:"Barrel \u6587\u4EF6\u53EF\u80FD\u5BFC\u81F4 tree-shake \u5931\u6548",file:o,detail:`${o} \u4F7F\u7528\u4E86 export * from \u6A21\u5F0F\uFF0C\u5BB9\u6613\u5BFC\u81F4\u672A\u4F7F\u7528\u7684\u6A21\u5757\u88AB\u4E00\u5E76\u6253\u5305\u3002`,suggestion:"\u6539\u4E3A\u663E\u5F0F\u5177\u540D\u5BFC\u51FA\uFF0C\u6216\u76F4\u63A5\u4ECE\u6E90\u6587\u4EF6\u6309\u9700\u5BFC\u5165\u3002",cost:{transferKb:15,parseMsEstimate:y(15),description:"Barrel \u6587\u4EF6\u95F4\u63A5\u5F15\u5165\u7684\u5197\u4F59\u4F53\u79EF\u96BE\u4EE5\u7CBE\u786E\u91CF\u5316\uFF0C\u6B64\u4E3A\u4FDD\u5B88\u4F30\u8BA1"}}),!i&&!a&&o.includes("/components/")&&r.trim().length<20&&t.push({id:h("static-unused",n++),category:"static-unused-js",severity:"low",title:"\u7591\u4F3C\u7A7A\u7EC4\u4EF6\u6587\u4EF6",file:o,detail:`${o} \u51E0\u4E4E\u6CA1\u6709\u6709\u6548\u5185\u5BB9\uFF0C\u53EF\u80FD\u662F\u9057\u7559\u6587\u4EF6\u3002`,suggestion:"\u786E\u8BA4\u662F\u5426\u4ECD\u9700\u8981\uFF0C\u4E0D\u9700\u8981\u5219\u5220\u9664\u3002",cost:{transferKb:0,parseMsEstimate:0,description:"\u7EF4\u62A4\u6210\u672C\u6D6A\u8D39"}});}return t}async function A(e){let t=S.resolve(e.projectRoot,e.options.root??"src"),n=[...W,...(e.options.include??[]).map(s=>S.extname(s)).filter(Boolean)];return Q(t,n,e.options.exclude??[])}function se(e){let t=new Set,n=[...e.entries];for(;n.length;){let s=n.shift();if(t.has(s))continue;t.add(s);let r=e.parsedModules.get(s);if(r)for(let o of r.importedIds)t.has(o)||n.push(o);}return t}function ve(e){let t=new Set;for(let n of e.bundleFiles)if(!(n.type!=="chunk"||!n.modules))for(let s of n.modules)t.add(c(s));return t}function Re(e,t){if(t.size===0)return false;let n=c(e);for(let s of t)if(s===n||s.endsWith(n)||n.endsWith(s))return true;return false}function re(e,t){if(!t.startsWith("."))return null;let n=S.resolve(S.dirname(e),t);if(S.extname(n))return M.existsSync(n)?c(n):null;let s=[".ts",".tsx",".js",".jsx",".vue",".svelte",".mjs",".cjs"];for(let r of s){let o=n+r;if(M.existsSync(o))return c(o)}for(let r of s){let o=S.join(n,"index"+r);if(M.existsSync(o))return c(o)}return null}function we(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}function ie(e){let t=e.match(/<script(?:\s+[^>]*)?>([\s\S]*?)<\/script>/i)?.[1]??"",r=e.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<\/?template[^>]*>/gi,"");return {script:t,template:r}}function ae(e){let t=e.replace(/^\s*import\s+['"][^'"]+['"]\s*;?\s*$/gm,"");return t=t.replace(/import\s+(?:type\s+)?(?:(?!\n\s*import)[\s\S])*?\s+from\s+['"][^'"]+['"]\s*;?/g,""),t}function ne(e){return e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")}function $e(e){let t=e.trim();if(!t||t.startsWith("type ")||/\bimport\s/.test(t))return [];let n=[],s=t.match(/^\*\s+as\s+(\w+)(?:\s*,\s*(.+))?$/);if(s)return n.push(s[1]),s[2]&&n.push(...oe(s[2])),n.filter(P);let r=t.indexOf("{");if(r===-1){let i=t.replace(/,$/,"").trim();return P(i)&&n.push(i),n}let o=t.slice(0,r).replace(/,$/,"").trim();return P(o)&&n.push(o),n.push(...oe(t.slice(r))),n.filter(P)}function P(e){return /^\w+$/.test(e)}function Me(e){let t=[],n=e.split(`
2
+ `),s="",r=false,o=()=>{s.trim()&&t.push(s.trim()),s="",r=false;};for(let i of n){let a=i.trim();if(!r&&a.startsWith("import ")?(r=true,s=i):r&&(s+=`
3
+ ${i}`),!!r){if(/^import\s+['"][^'"]+['"]\s*;?\s*$/.test(s.trim())){o();continue}/from\s+['"][^'"]+['"]\s*;?\s*$/.test(a)&&o();}}return r&&s.trim()&&t.push(s.trim()),t}function Ee(e){return /^import\s+['"][^'"]+['"]\s*;?\s*$/.test(e.trim())}function oe(e){let t=[],n=e.match(/\{([\s\S]*)\}/)?.[1]??e;for(let s of n.split(",")){let r=s.trim();if(!r||r.startsWith("type "))continue;let o=r.match(/(?:\w+\s+as\s+)?(\w+)\s*$/);o&&t.push(o[1]);}return t}function ue(e){let t=[];for(let n of Me(e)){if(Ee(n)||/^\s*import\s+type\s+/.test(n))continue;let s=n.match(/^\s*import\s+(?:type\s+)?([\s\S]+?)\s+from\s+['"]([^'"]+)['"]\s*;?\s*$/);if(!s)continue;let r=s[1].trim(),o=s[2];if(!(!r||r.startsWith("type ")||/\bimport\s/.test(r)))for(let i of $e(r))t.push({localName:i,specifier:o});}return t}function ce(e,t,n){let s=ne(t),r=new RegExp(`\\b${e}\\b`);if(r.test(s))return true;if(!n)return false;let o=ne(n);if(r.test(o))return true;let i=we(e);return !!(i!==e.toLowerCase()&&new RegExp(`<${i}[\\s/>]`,"i").test(o))}function Ce(e){let t=new Map;for(let n of e.sourceFiles){let s=R(n);if(!s)continue;let r=c(n),o=n.endsWith(".vue"),{script:i,template:a}=o?ie(s):{script:s,template:""},u=ae(o?i:s);for(let{localName:l,specifier:f}of ue(i)){if(!f.startsWith(".")||!ce(l,u,a))continue;let p=re(n,f);if(!p)continue;let m=t.get(r)??new Set;m.add(c(p)),t.set(r,m);}}return t}function Pe(e,t){let n=new Set(e.sourceFiles.map(i=>c(i))),s=new Set,r=[],o=i=>{let a=c(i);n.has(a)&&!s.has(a)&&r.push(a);};for(let i of e.entries){o(i);let a=e.parsedModules.get(c(i));if(a)for(let u of a.importedIds)o(u);}for(let i of e.sourceFiles){let a=c(i);e.parsedModules.get(a)?.isEntry&&o(a);}if(r.length===0)return n;for(;r.length;){let i=r.shift();if(!s.has(i)){s.add(i);for(let a of t.get(i)??[])s.has(a)||r.push(a);}}return s}function Fe(e,t){let n=e.endsWith(".vue"),{script:s,template:r}=n?ie(t):{script:t,template:""},o=ae(n?s:t),i=[];for(let{localName:a,specifier:u}of ue(s))u.startsWith(".")&&(ce(a,o,r)||i.push({localName:a,specifier:u,resolved:re(e,u)}));return i}function le(e){return /\.(vue|tsx|jsx)$/i.test(e)&&/pages?|views?|components?|routes?/i.test(e)}function je(e,t,n){let s=le(e);return t?"medium":n?"low":s?"medium":"low"}function pe(e){if(!e.options.scanUnusedImports)return [];let t=[],n=ve(e),s=n.size>0,r=Ce(e),o=Pe(e,r),i=0;for(let a of e.sourceFiles){let u=c(a);if(!o.has(u))continue;let l=R(a);if(!l)continue;let f=v(e.projectRoot,a),p=Fe(a,l);if(p.length!==0)for(let{localName:m,specifier:d,resolved:g}of p){let b=g?v(e.projectRoot,g):d,I=g?Re(g,n):false,F=je(b,I,s),$=g?E(g):0,Ie=I?`${f} \u5F15\u5165\u4E86 \`${b}\`\uFF08\u7ED1\u5B9A \`${m}\`\uFF09\u4F46\u672A\u5728\u6587\u4EF6\u5185\u4F7F\u7528\u3002\u8BE5\u6A21\u5757\u4ECD\u51FA\u73B0\u5728\u6784\u5EFA\u4EA7\u7269\u4E2D\uFF08\u7EA6 ${$} KB\uFF09\u3002`:`${f} \u5F15\u5165\u4E86 \`${b}\`\uFF08\u7ED1\u5B9A \`${m}\`\uFF09\u4F46\u672A\u5728\u6587\u4EF6\u5185\u4F7F\u7528\u3002`;t.push({id:h("dead-import",i++),category:"dead-import",severity:F,title:`\u672A\u4F7F\u7528\u7684\u9759\u6001 import: ${m}`,file:f,detail:Ie,suggestion:le(b)?`\u5220\u9664\u5197\u4F59 import\uFF1B\u82E5\u8DEF\u7531/\u9875\u9762\u5DF2\u4E0B\u7EBF\uFF0C\u786E\u8BA4 \`${b}\` \u662F\u5426\u4E5F\u53EF\u79FB\u9664\u3002`:`\u5220\u9664\u672A\u4F7F\u7528\u7684 import \`${m}\` from '${d}'\u3002`,cost:{transferKb:I?$:0,parseMsEstimate:I?y($):0,description:I?`\u5197\u4F59 import \u5BFC\u81F4\u7EA6 ${$} KB \u8FDB\u5165\u4EA7\u7269`:"\u7EF4\u62A4\u6027\u6D6A\u8D39"},metadata:{binding:m,specifier:d,importedModule:b,inBundle:I}});}}return t}function me(e){if(!e.options.scanUnreachable)return [];let t=[],n=se(e),s=0,r=new Set;for(let o of n){if(o.startsWith("\0")||o.includes("virtual:"))continue;let i=S.isAbsolute(o)?c(o):c(S.resolve(e.projectRoot,o));r.add(i);}for(let o of e.sourceFiles){let i=c(o);if(e.entries.some(g=>c(S.resolve(g))===i))continue;let u=[...r].some(g=>g===i||i.endsWith(g)||g.endsWith(i)),l=e.parsedModules.get(i)??e.parsedModules.get(o),f=l&&l.importers.size>0;if(u||f)continue;let p=E(o),m=v(e.projectRoot,o),d=/pages?|views?|components?|routes?/i.test(m)&&/\.(vue|tsx|jsx)$/.test(m);t.push({id:h("unreachable",s++),category:"unreachable-component",severity:d?"high":"medium",title:d?"\u4E0D\u53EF\u8FBE\u9875\u9762/\u7EC4\u4EF6":"\u4E0D\u53EF\u8FBE\u6E90\u6587\u4EF6",file:m,detail:`${m} \u672A\u51FA\u73B0\u5728\u4EFB\u4F55\u6784\u5EFA\u5165\u53E3\u7684 module graph \u4E2D\uFF0C\u5C5E\u4E8E\u9759\u6001\u4E0D\u53EF\u8FBE\u4EE3\u7801\u3002`,suggestion:d?"\u82E5\u4E1A\u52A1\u5DF2\u4E0B\u7EBF\uFF0C\u5220\u9664\u8BE5\u9875\u9762/\u7EC4\u4EF6\u53CA\u5173\u8054\u9759\u6001\u8D44\u6E90\u3002":"\u786E\u8BA4\u662F\u5426\u4ECD\u88AB\u52A8\u6001\u8DEF\u5F84\u5F15\u7528\uFF1B\u82E5\u65E0\uFF0C\u8BF7\u5220\u9664\u6216\u79FB\u51FA src\u3002",cost:{transferKb:p,parseMsEstimate:y(p),description:`\u6587\u4EF6\u672C\u4F53 ${p} KB\uFF1B\u82E5\u88AB glob \u626B\u5165\u53EF\u80FD\u4EA7\u751F\u66F4\u5927 chunk \u6D6A\u8D39`},metadata:{isPageOrComponent:d}});}return t}function fe(e){let t=[],n=0,s=e.bundleFiles.filter(a=>a.isEntry),r=new Set(e.bundleFiles.filter(a=>a.type==="chunk").map(a=>a.fileName)),o=new Set,i=s.map(a=>a.fileName);for(;i.length;){let a=i.shift();if(o.has(a))continue;o.add(a);let u=e.bundleFiles.find(l=>l.fileName===a);if(u)for(let l of u.imports??[])r.has(l)&&!o.has(l)&&i.push(l);}for(let a of e.bundleFiles){if(a.type!=="chunk"||a.isEntry||o.has(a.fileName))continue;let u=Math.round(a.size/1024*100)/100,l=a.fileName.includes("legacy")||a.fileName.includes("admin");t.push({id:h("orphan-chunk",n++),category:"static-unused-js",severity:"low",title:"\u72EC\u7ACB\u5F02\u6B65 chunk\uFF08\u672A\u88AB\u9759\u6001\u5F15\u7528\uFF09",file:a.fileName,detail:`\u4EA7\u7269 chunk ${a.fileName} (${u} KB) \u4EC5\u901A\u8FC7\u52A8\u6001 import \u52A0\u8F7D\uFF0C\u672C\u8EAB\u4E0D\u662F\u6D6A\u8D39\uFF0C\u4F46\u82E5\u88AB\u5168\u7AD9 prefetch \u5219\u4F1A\u4EA7\u751F\u52A0\u8F7D\u6D6A\u8D39\u3002`,suggestion:"\u68C0\u67E5\u662F\u5426\u5BF9\u8BE5 chunk \u914D\u7F6E\u4E86\u4E0D\u5FC5\u8981\u7684 prefetch/preload\u3002",cost:{transferKb:0,parseMsEstimate:0,description:"\u672C\u8EAB\u4E3A\u6309\u9700\u52A0\u8F7D\uFF1B\u6D6A\u8D39\u53D6\u51B3\u4E8E prefetch \u7B56\u7565"},metadata:{chunkSizeKb:u,dynamicOnly:true,suspiciousPrefetch:l}});}return t}async function K(e){let t=await Promise.all([te(e),Promise.resolve(pe(e)),Promise.resolve(me(e)),Promise.resolve(fe(e)),Promise.resolve(J(e)),Promise.resolve(X(e)),Promise.resolve(Y(e))]);return ze(t.flat())}function ze(e){let t=new Set;return e.filter(n=>{let s=`${n.category}:${n.file}:${n.title}`;return t.has(s)?false:(t.add(s),true)})}function B(e){let t={high:0,medium:1,low:2};return [...e].sort((n,s)=>{let r=t[n.severity]-t[s.severity];return r!==0?r:s.cost.transferKb-n.cost.transferKb})}function de(e,t,n,s,r){let o=c(t),i=e.get(o)??{id:o,importers:new Set,importedIds:new Set,dynamicImporters:new Set,isEntry:false,code:void 0};i.isEntry=i.isEntry||r,n&&(i.code=n);for(let a of s)i.importedIds.add(c(a));e.set(o,i);for(let a of s){let u=c(a),l=e.get(u)??{id:u,importers:new Set,importedIds:new Set,dynamicImporters:new Set,isEntry:false};l.importers.add(o),e.set(u,l);}}function ge(e){let t=[];for(let[n,s]of Object.entries(e))if(s.type==="chunk"){let r=s;t.push({fileName:n,type:"chunk",size:Buffer.byteLength(r.code,"utf-8"),modules:Object.keys(r.modules??{}),isEntry:r.isEntry??false,imports:r.imports,dynamicImports:r.dynamicImports});}else {let o=s.source,i=typeof o=="string"?Buffer.byteLength(o,"utf-8"):o instanceof Uint8Array?o.byteLength:0;t.push({fileName:n,type:"asset",size:i});}return t}function k(e,t){let n=Ae(),s={high:0,medium:0,low:0},r=0,o=0;for(let i of e)n[i.category]++,s[i.severity]++,!i.metadata?.informational&&(r+=i.cost.transferKb,o+=i.cost.parseMsEstimate);return {generatedAt:G(),projectRoot:t.projectRoot,mode:t.mode,outDir:t.outDir,summary:{totalIssues:e.length,totalWasteTransferKb:Math.round(r*100)/100,totalParseMsEstimate:Math.round(o*10)/10,byCategory:n,bySeverity:s},issues:e}}function Ae(){return {"static-unused-js":0,"unreachable-component":0,"cache-miss":0,"duplicate-dependency":0,"import-pattern":0,"dead-import":0,"prefetch-waste":0}}function he(e,t){let{summary:n,issues:s}=e,r=s.slice(0,5);if(console.log(`
4
4
  [vite-plugin-resource-waste] Resource waste analysis complete
5
- `),console.log(` Issues : ${o.totalIssues}`),console.log(` Waste (est.) : ${o.totalWasteTransferKb} KB transfer / ${o.totalParseMsEstimate} ms parse`),console.log(` Threshold : ${t} KB`),r.length>0){console.log(`
6
- Top issues:`);for(let n of r)console.log(` [${n.severity.toUpperCase()}] ${n.title}${n.file?` (${n.file})`:""}`);}console.log("");}var he={cyan:e=>`\x1B[36m${e}\x1B[0m`,yellow:e=>`\x1B[33m${e}\x1B[0m`};function ye(e={}){let t={..._,...e},o={},s=process.cwd(),r="dist",n="production",i=[],a=[],u=new Map,l=(p=[])=>({root:t.root??"src",projectRoot:s,outDir:r,mode:n,entries:i,sourceFiles:a,parsedModules:u,bundleFiles:p,options:t});async function m(){if(!o.bundle)return;let p=de(o.bundle),f=l(p),d=B(await K(f)),g=k(d,{projectRoot:s,mode:n,outDir:r}),I=S.resolve(s,r,t.reportDir??"resource-waste");j(I);let b=S.join(I,"report.json");if(M.writeFileSync(b,JSON.stringify(g,null,2),"utf-8"),t.htmlReport){let{renderHtmlReport:F}=await import('./html-HJC2K4KV.js');M.writeFileSync(S.join(I,"report.html"),F(g),"utf-8");}if(t.silent||(ge(g,t.wasteThresholdKb??300),console.log(` Report JSON : ${c(S.relative(s,b))}`),t.htmlReport&&console.log(` Report HTML : ${c(S.relative(s,S.join(I,"report.html")))}`)),t.failOnThreshold&&g.summary.totalWasteTransferKb>(t.wasteThresholdKb??300))throw new Error(`[vite-plugin-resource-waste] Estimated waste ${g.summary.totalWasteTransferKb} KB exceeds threshold ${t.wasteThresholdKb} KB`)}return {name:"vite-plugin-resource-waste",enforce:"post",configResolved(p){s=p.root,r=p.build.outDir,n=p.mode;let f=p.build.rollupOptions.input;typeof f=="string"?i=[c(w(s,f))]:Array.isArray(f)?i=f.map(d=>c(w(s,d))):f&&typeof f=="object"?i=Object.values(f).map(d=>c(w(s,d))):i=[c(w(s,"index.html"))];},async buildStart(){a=await A(l());},moduleParsed(p){p.id&&me(u,p.id,p.code??null,[...p.importedIds,...p.dynamicallyImportedIds??[]],p.isEntry);},generateBundle(p,f){o.bundle=f;},async closeBundle(){await m();},configureServer(p){p.httpServer?.once("listening",async()=>{if(n==="production")return;a=await A(l());let f=B(await K(l()));!t.silent&&f.length>0&&console.log(he.cyan(`
7
- [vite-plugin-resource-waste]`)+he.yellow(` Dev mode: found ${f.length} potential resource waste issue(s). Run "vite build" for full report.
8
- `));let d=S.resolve(s,"node_modules/.cache/resource-waste");j(d);let g=k(f,{projectRoot:s,mode:n,outDir:r});M.writeFileSync(S.join(d,"dev-report.json"),JSON.stringify(g,null,2),"utf-8");});}}}var Ae=ye;export{Ae as default,ye as resourceWaste};
5
+ `),console.log(` Issues : ${n.totalIssues}`),console.log(` Waste (est.) : ${n.totalWasteTransferKb} KB transfer / ${n.totalParseMsEstimate} ms parse`),console.log(` Threshold : ${t} KB`),r.length>0){console.log(`
6
+ Top issues:`);for(let o of r)console.log(` [${o.severity.toUpperCase()}] ${o.title}${o.file?` (${o.file})`:""}`);}console.log("");}var ye={cyan:e=>`\x1B[36m${e}\x1B[0m`,yellow:e=>`\x1B[33m${e}\x1B[0m`};function be(e={}){let t={..._,...e},n={},s=process.cwd(),r="dist",o="production",i=[],a=[],u=new Map,l=(p=[])=>({root:t.root??"src",projectRoot:s,outDir:r,mode:o,entries:i,sourceFiles:a,parsedModules:u,bundleFiles:p,options:t});async function f(){if(!n.bundle)return;let p=ge(n.bundle),m=l(p),d=B(await K(m)),g=k(d,{projectRoot:s,mode:o,outDir:r}),b=S.resolve(s,r,t.reportDir??"resource-waste");j(b);let I=S.join(b,"report.json");if(M.writeFileSync(I,JSON.stringify(g,null,2),"utf-8"),t.htmlReport){let{renderHtmlReport:F}=await import('./html-HJC2K4KV.js');M.writeFileSync(S.join(b,"report.html"),F(g),"utf-8");}if(t.silent||(he(g,t.wasteThresholdKb??300),console.log(` Report JSON : ${c(S.relative(s,I))}`),t.htmlReport&&console.log(` Report HTML : ${c(S.relative(s,S.join(b,"report.html")))}`)),t.failOnThreshold&&g.summary.totalWasteTransferKb>(t.wasteThresholdKb??300))throw new Error(`[vite-plugin-resource-waste] Estimated waste ${g.summary.totalWasteTransferKb} KB exceeds threshold ${t.wasteThresholdKb} KB`)}return {name:"vite-plugin-resource-waste",enforce:"post",configResolved(p){s=p.root,r=p.build.outDir,o=p.mode;let m=p.build.rollupOptions.input;typeof m=="string"?i=[c(w(s,m))]:Array.isArray(m)?i=m.map(d=>c(w(s,d))):m&&typeof m=="object"?i=Object.values(m).map(d=>c(w(s,d))):i=[c(w(s,"index.html"))];},async buildStart(){a=await A(l());},moduleParsed(p){p.id&&de(u,p.id,p.code??null,[...p.importedIds,...p.dynamicallyImportedIds??[]],p.isEntry);},generateBundle(p,m){n.bundle=m;},async closeBundle(){await f();},configureServer(p){p.httpServer?.once("listening",async()=>{if(o==="production")return;a=await A(l());let m=B(await K(l()));!t.silent&&m.length>0&&console.log(ye.cyan(`
7
+ [vite-plugin-resource-waste]`)+ye.yellow(` Dev mode: found ${m.length} potential resource waste issue(s). Run "vite build" for full report.
8
+ `));let d=S.resolve(s,"node_modules/.cache/resource-waste");j(d);let g=k(m,{projectRoot:s,mode:o,outDir:r});M.writeFileSync(S.join(d,"dev-report.json"),JSON.stringify(g,null,2),"utf-8");});}}}var Ne=be;export{Ne as default,be as resourceWaste};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-resource-waste",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "基于 Vite 的前端构建资源浪费分析插件,利用 Module Graph 检测未使用 JS、不可达组件、缓存失效与重复依赖,量化传输/解析开销并输出可执行优化报告,支持 CI 构建阈值拦截",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",