使用ast完成antd4的升級(一)

antd4發佈也有一段時間了,也是時候來一波升級了。
antd v4版本對多個組件作了性能優化,日期選擇也作了優化調整,icon移出到了單獨的庫中。
看了升級文檔,主要是icon和form2大組件改動較大,官方也提供了升級工具,不過我並無去嘗試使用,根據經驗,這類工具坑較多,公司項目也作了其餘封裝,全部不考慮官方升級工具。
因爲對ast有必定的瞭解和使用,對於此次升級是一個很是合適的方案,有大量的文件須要批量修改。
ast工具主要使用babel,支持tsx,仍是比較方便的,先貼下代碼。node

let newCode = convertCodeUseAst(code, {
  Program(rootPath) {
    rootPath.traverse({
      JSXOpeningElement(path1) {
        let newTagName = null, attributes = []
        let node1 = path1.node
        if (node1.name) {
          let tagName = node1.name.name
          if (tagName == 'Icon') {
            attributes = [...node1.attributes]
            if (attributes) {
              let typeValue
              let themeValue
              path1.traverse({
                JSXAttribute(path2) {
                  let node2 = path2.node
                  if (node2.name.name == 'type') {
                    if (node2.value.type == 'StringLiteral') {
                      typeValue = node2.value.value
                        path2.remove()
                    }
                  }
                  if (node2.name.name == 'theme') {
                    themeValue = node2.value.value
                    path2.remove()
                  }
                }
              })
              if (typeValue == null) {
                return
              }
              let typeValue1 = typeValue
                .replace(/^\w/, (w) => w.toUpperCase())
                .replace(/-\w/g, (w) => w.toUpperCase())
                .replace(/-/g, '')

              let theme = 'Outlined'
              if (themeValue == 'filled') {
                theme = 'Filled'
              }
              if (themeValue == 'twoTone') {
                theme = 'TwoTone'
              }
              newTagName = typeValue1 + theme

              if (iconTypeList.indexOf(newTagName) == -1) {
                iconTypeList.push(newTagName)
              }
              converted = true
            }
          }
        }
        if (newTagName) {
          let attributes1 = attributes.filter(attr => {
            let name = attr.name.name
            return name != 'type' && name != 'theme'
          })

          path1.replaceWith(
            t.jsxOpeningElement(t.jsxIdentifier(newTagName), attributes1, node1.selfClosing)
          )
        }
      }
    })
    for (let iconType of iconTypeList) {
      let isImported = isModuleImported(rootPath, iconType)
      if (!isImported) {
        addImportItem(rootPath, `\nimport {${iconType}} from '@ant-design/icons'`)
      }
    }
  }
}, filePath)

代碼僅供參考,這段代碼主要用於將icon轉化到@ant-design/icon。
思路是先遍歷jsx標籤,找到Icon標籤,而後找到type屬性和theme屬性,進行對應的轉化到antd v4方式。性能優化

~下次單獨寫一遍關於babel進行代碼遍歷和替換的文章~~babel

相關文章
相關標籤/搜索