generate-component.js 6.2 KB
Newer Older
1
const fs = require('fs')
fxy060608's avatar
fxy060608 已提交
2 3 4
const path = require('path')
const {
  removeExt,
5 6
  normalizePath,
  getPlatformExts
fxy060608's avatar
fxy060608 已提交
7 8 9 10 11 12 13 14 15
} = require('@dcloudio/uni-cli-shared')
const {
  getComponentSet
} = require('@dcloudio/uni-cli-shared/lib/cache')

const {
  restoreNodeModules
} = require('../shared')

fxy060608's avatar
fxy060608 已提交
16 17
const EMPTY_COMPONENT_LEN = 'Component({})'.length

fxy060608's avatar
fxy060608 已提交
18
const uniPath = require('@dcloudio/uni-cli-shared/lib/platform').getMPRuntimePath()
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

function findModule (modules, resource, altResource) {
  return modules.find(
    module => {
      let moduleResource = module.resource
      if (
        !moduleResource ||
        (
          moduleResource.indexOf('.vue') === -1 &&
          moduleResource.indexOf('.nvue') === -1
        )
      ) {
        return
      }
      moduleResource = removeExt(module.resource)
      return moduleResource === resource || moduleResource === altResource
    }
  )
}

function findModuleId (modules, resource, altResource) {
  const module = findModule(modules, resource, altResource)
  return module && module.id
}

function findModuleIdFromConcatenatedModules (modules, resource, altResource) {
  const module = modules.find(module => {
    return findModule(module.modules, resource, altResource)
  })
  return module && module.id
}

function findComponentModuleId (modules, concatenatedModules, resource, altResource) {
  return findModuleId(modules, resource, altResource) ||
    findModuleIdFromConcatenatedModules(concatenatedModules, resource, altResource) ||
    resource
}

57
let lastComponents = []
fxy060608's avatar
fxy060608 已提交
58 59
// TODO 解决方案不太理想
module.exports = function generateComponent (compilation) {
60
  const curComponents = []
fxy060608's avatar
fxy060608 已提交
61 62 63 64 65
  const components = getComponentSet()
  if (components.size) {
    const assets = compilation.assets
    const modules = compilation.modules

66
    const concatenatedModules = modules.filter(module => module.modules)
fxy060608's avatar
fxy060608 已提交
67
    const uniModuleId = modules.find(module => module.resource && normalizePath(module.resource) === uniPath).id
68
    const styleImports = {}
fxy060608's avatar
fxy060608 已提交
69 70 71

    Object.keys(assets).forEach(name => {
      if (components.has(name.replace('.js', ''))) {
72
        curComponents.push(name.replace('.js', ''))
fxy060608's avatar
fxy060608 已提交
73 74 75 76 77

        if (assets[name].source.__$wrappered) {
          return
        }

fxy060608's avatar
fxy060608 已提交
78 79 80 81 82
        const chunkName = name.replace('.js', '-create-component')

        let moduleId = ''
        if (name.indexOf('node-modules') === 0) {
          const modulePath = removeExt(restoreNodeModules(name))
fxy060608's avatar
fxy060608 已提交
83
          let resource = normalizePath(path.resolve(process.env.UNI_INPUT_DIR, '..', modulePath))
fxy060608's avatar
fxy060608 已提交
84
          const altResource = normalizePath(path.resolve(process.env.UNI_INPUT_DIR, modulePath))
fxy060608's avatar
fxy060608 已提交
85

86
          if (
fxy060608's avatar
fxy060608 已提交
87 88 89 90 91 92 93 94 95 96
            /^win/.test(process.platform) &&
            modulePath.includes('@dcloudio') &&
            (
              modulePath.includes('page-meta') ||
              modulePath.includes('navigation-bar')
            )
          ) {
            resource = normalizePath(path.resolve(process.env.UNI_CLI_CONTEXT, modulePath))
          }

97
          moduleId = findComponentModuleId(modules, concatenatedModules, resource, altResource)
fxy060608's avatar
fxy060608 已提交
98 99
        } else {
          const resource = removeExt(path.resolve(process.env.UNI_INPUT_DIR, name))
100
          moduleId = findComponentModuleId(modules, concatenatedModules, resource)
fxy060608's avatar
fxy060608 已提交
101 102 103
        }

        const origSource = assets[name].source()
fxy060608's avatar
fxy060608 已提交
104
        if (origSource.length !== EMPTY_COMPONENT_LEN) { // 不是空组件
fxy060608's avatar
fxy060608 已提交
105 106 107 108 109 110 111
          const globalVar = process.env.UNI_PLATFORM === 'mp-alipay' ? 'my' : 'global'
          // 主要是为了解决支付宝旧版本, Component 方法只在组件 js 里有,需要挂在 my.defineComponent
          let beforeCode = ''
          if (process.env.UNI_PLATFORM === 'mp-alipay') {
            beforeCode = ';my.defineComponent || (my.defineComponent = Component);'
          }
          const source = beforeCode + origSource +
112
            `
fxy060608's avatar
fxy060608 已提交
113 114 115 116 117 118 119 120
;(${globalVar}["webpackJsonp"] = ${globalVar}["webpackJsonp"] || []).push([
    '${chunkName}',
    {
        '${chunkName}':(function(module, exports, __webpack_require__){
            __webpack_require__('${uniModuleId}')['createComponent'](__webpack_require__(${JSON.stringify(moduleId)}))
        })
    },
    [['${chunkName}']]
121
]);
fxy060608's avatar
fxy060608 已提交
122
`
fxy060608's avatar
fxy060608 已提交
123 124
          const newSource = function () {
            return source
fxy060608's avatar
fxy060608 已提交
125
          }
fxy060608's avatar
fxy060608 已提交
126 127
          newSource.__$wrappered = true
          assets[name].source = newSource
fxy060608's avatar
fxy060608 已提交
128 129
        }
      }
130 131
      const styleExtname = getPlatformExts().style
      if (name.endsWith(styleExtname)) {
132
        // 移除部分含有错误引用的 wxss 文件
133 134
        let origSource = assets[name].source()
        origSource = origSource.trim ? origSource.trim() : ''
135 136
        const result = origSource.match(/^@import ["'](.+?)["']$/)
        if (result) {
137 138 139 140
          const stylePath = path.join(path.dirname(name), result[1])
          if (Object.keys(assets).includes(stylePath)) {
            styleImports[stylePath] = styleImports[stylePath] || []
            styleImports[stylePath].push(name)
141
          } else {
142 143 144
            if (styleImports[name]) {
              styleImports[name].forEach(name => delete assets[name])
              delete styleImports[name]
145 146 147 148 149
            }
            delete assets[name]
          }
        }
      }
fxy060608's avatar
fxy060608 已提交
150 151
    })
  }
fxy060608's avatar
fxy060608 已提交
152
  if (process.env.UNI_FEATURE_OBSOLETE !== 'false') {
153 154 155
    if (lastComponents.length) {
      for (const name of lastComponents) {
        if (!curComponents.includes(name)) {
fxy060608's avatar
fxy060608 已提交
156
          removeUnusedComponent(name) // 组件被移除
157 158
        }
      }
fxy060608's avatar
fxy060608 已提交
159 160 161 162 163
    }
    for (const name of curComponents) {
      if (!lastComponents.includes(name)) {
        addComponent(name) // 新增组件
      }
164 165 166 167 168
    }
    lastComponents = curComponents
  }
}

fxy060608's avatar
fxy060608 已提交
169 170 171 172 173 174 175 176 177
function addComponent (name) {
  const bakJson = path.join(process.env.UNI_OUTPUT_DIR, name + '.bak.json')
  if (fs.existsSync(bakJson)) {
    try {
      fs.renameSync(bakJson, path.join(process.env.UNI_OUTPUT_DIR, name + '.json'))
    } catch (e) {}
  }
}

178 179
function removeUnusedComponent (name) {
  try {
fxy060608's avatar
fxy060608 已提交
180 181
    fs.renameSync(path.join(process.env.UNI_OUTPUT_DIR, name + '.json'), path.join(process.env.UNI_OUTPUT_DIR, name +
      '.bak.json'))
182
  } catch (e) {}
183
}