原生小程序优化--删除注册却并未使用到的组件

662 阅读1分钟

优化背景

根据微信提示的优化项:

组件/页面的usingComponents会影响启动速度,应避免将多余的组件声明usingComponents中

随着开发迭代的深入,很多页面中删除了对应的组件使用,却会习惯性的忘记删除对应的注册,根据优化提示,需要删除在usingComponents注册了,但没有在wxml真实使用的组件

实现细节

1. 获取入口小程序页面路由注册app.json文件

// 小程序注册入口文件
const entry = require(`${rootDir}/src/app.json`)

2. 根据入口文件获取分析pages,subPackages入口,找到每个页面的引用组件

Object.keys(entry).forEach((i) => {
  if (i === 'pages') {
    entry[i] &&
      entry[i].length > 0 &&
      entry[i].forEach((j) => {
        inflateEntries(entries, currentDirname, j)
      })
  }
  if (i === 'subPackages') {
    entry[i].forEach((j) => {
      if (j && j.pages && j.pages.length > 0) {
        j.pages.forEach((k) => {
          inflateEntries(entries, currentDirname, `${j.root}/${k}`)
        })
      }
    })
  }
})

3. 动态的遍历入口文件下所有子引用

通过每个入口文件找到引用到的每一个组件,将他们以文件绝对路径的形式存入数组,todo: 这里可以用weakmap优化性能

function _inflateEntries(entries = [], dirname, entry) {
  const configFile = replaceExt(entry, '.json')
  const content = fs.readFileSync(configFile, 'utf8')
  const config = JSON.parse(content)

  const { pages, usingComponents, subPackages } = config
  pages && pages.forEach((item) => inflateEntries(entries, dirname, item))
  usingComponents && Object.values(usingComponents).forEach((item) => inflateEntries(entries, dirname, item))
  subPackages &&
    subPackages.forEach((subpackage) => {
      if (!subpackage.pages) {
        return
      }
      return subpackage.pages.forEach((item) => inflateEntries(entries, dirname + `/${subpackage.root}`, item))
    })
}

function inflateEntries(entries, dirname, entry) {
  if (/plugin:\/\//.test(entry)) {
    console.log(`发现插件 ${entry}`)
    return
  }

  if (typeof entry !== 'string') {
    throw new Error('入口文件位置获取有误')
  }

  entry = path.resolve(dirname, entry)
  if (entry != null && !entries.includes(entry)) {
    entries.push(entry)
    _inflateEntries(entries, path.dirname(entry), entry)
  }
}

4. 查找当前页面内未使用的组件并记录

遍历项目内所有已经在被使用的页面和组件,将当前页面/组件json和xml进行对比。把json里的usingComponents逐个遍历,通过<tagName 的形式判断是否在xml的文本里出现过。如果没有则记录可以删除的noUseTags内

const findNoUseComponents = (i, json, wxml) => {
  const currentJSONComponents = []
  const noUseTags = []
  if (json.usingComponents) {
    Object.keys(json.usingComponents).forEach((i) => {
      currentJSONComponents.push(i)
    })
  } else {
    console.log('there is no use components', i, json)
  }

  if (currentJSONComponents.length > 0) {
    currentJSONComponents.forEach((i) => {
      const tagsName = `<${i}`
      if (wxml.indexOf(tagsName) < 0) {
        noUseTags.push(i)
      }
    })
  }
  if (noUseTags.length > 0) {
    noUseTagsNumsPages += 1
    noUseTagPagesMap[i] = noUseTags
  }
}

entries.forEach((i) => {
  const jsonFile = path.resolve(`${i}.json`)
  const xmlFile = path.resolve(`${i}.wxml`)
  const jsonContent = fs.readFileSync(jsonFile, 'utf8')
  const wxmlInfo = fs.readFileSync(xmlFile, 'utf8')
  const jsonInfo = JSON.parse(jsonContent, 'utf8')
  findNoUseComponents(i, jsonInfo, wxmlInfo)
})

5. 根据配置选择是否删除json里面的未使用的tag

if (isAutoDelete) {
  Object.keys(noUseTagPagesMap).forEach((i) => {
    const filePath = path.resolve(`${i}.json`)
    const fileContent = fs.readFileSync(filePath)
    const json = JSON.parse(fileContent, 'utf8')
    const { usingComponents } = json
    const noUseTagArr = noUseTagPagesMap[i]
    Object.keys(usingComponents).forEach((j) => {
      if (noUseTagArr.includes(j)) {
        delete usingComponents[j]
      }
    })
    const jsonContent = JSON.stringify(json)
    fs.writeFile(filePath, jsonContent, 'utf8', function (err) {
      if (err) {
        console.log('An error occured while writing JSON Object to File.')
        return console.log(err)
      }
      console.log('JSON file has been saved.')
    })
  })
}

项目地址

点击就送