| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- #!/usr/bin/env node
- /**
- * E 批:图片 lazy-load 治理
- * 在长列表页的 <image> 标签上补 lazy-load(若尚未有 lazy-load 属性)
- *
- * 策略:
- * - 对 <image ...> 不含 lazy-load 的标签补上 lazy-load
- * - 跳过已有 lazy-load 的标签
- * - 仅处理已识别的长列表页(discover / article-center / shop / activity / growth 等)
- */
- const fs = require('fs')
- const path = require('path')
- const ROOT = path.resolve(__dirname, '..')
- const EXCLUDE_DIRS = new Set(['node_modules', 'dist', 'unpackage', '.git', 'docs'])
- // 需要治理的长列表页面/组件(按父目录分组,walk 时过滤)
- const TARGET_PATTERNS = [
- 'pages/discover/',
- 'pages/article-center/',
- 'pages/shop/',
- 'pages/activity/',
- 'pages/growth/',
- 'pages/promotion/',
- 'components/DimensionActivities.vue',
- 'components/DimensionProducts.vue',
- 'components/RecommendedFeed.vue',
- 'components/ArticleBookshelf.vue',
- 'components/FamilyFeed.vue',
- 'components/daily-task-card.vue',
- ]
- // 模式:找到 <image ...> 中不含 lazy-load 的,加上 lazy-load
- // 匹配:<image ...attrs...>(不含 lazy-load),在后面某个位置补
- const IMG_TAG_RE = /<image\s([^>]*)>/gi
- function processFile(filePath) {
- const src = fs.readFileSync(filePath, 'utf8')
- // 只处理包含长列表 image 的文件(启发式:有 v-for 或 list/data 字样的文件优先)
- const hasLoop = /v-for\s*=/.test(src) || /v_loop/.test(src)
- if (!hasLoop) return { changed: false, count: 0 }
- let result = src
- let count = 0
- result = result.replace(IMG_TAG_RE, (fullMatch, attrs) => {
- if (/lazy-load/.test(attrs)) return fullMatch // 已有 lazy-load,跳过
- // 在标签闭合 `>`(可能为 `/>`)前插入 lazy-load
- if (fullMatch.endsWith('/>')) {
- return fullMatch.slice(0, -2) + ' lazy-load />'
- }
- return fullMatch.slice(0, -1) + ' lazy-load>'
- })
- count = (result.match(/lazy-load/g) || []).length - (src.match(/lazy-load/g) || []).length
- if (count > 0) {
- fs.writeFileSync(filePath, result, 'utf8')
- }
- return { changed: count > 0, count }
- }
- function walk(dir, out = []) {
- for (const name of fs.readdirSync(dir)) {
- if (EXCLUDE_DIRS.has(name)) continue
- const p = path.join(dir, name)
- const st = fs.statSync(p)
- if (st.isDirectory()) walk(p, out)
- else if (name.endsWith('.vue')) out.push(p)
- }
- return out
- }
- function main() {
- const allFiles = walk(ROOT)
- const targets = allFiles.filter(f => {
- const rel = path.relative(ROOT, f).split(path.sep).join('/')
- return TARGET_PATTERNS.some(p => rel.startsWith(p))
- })
- let grandTotal = 0
- const log = []
- for (const f of targets) {
- const rel = path.relative(ROOT, f)
- const r = processFile(f)
- if (r.changed) {
- grandTotal += r.count
- log.push(`${r.count.toString().padStart(3)} ${rel}`)
- }
- }
- console.log(`\n=== E 批 lazy-load 补全完成 ===`)
- console.log(`新增 lazy-load: ${grandTotal} 处`)
- log.sort((a, b) => parseInt(b.split(' ')[0]) - parseInt(a.split(' ')[0]))
- for (const line of log.slice(0, 30)) console.log(line)
- }
- main()
|