index-new.js 2.7 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
const path = require('path')

const {
  md5,
  parseEntry,
  normalizePath
} = require('@dcloudio/uni-cli-shared')

const generateApp = require('./generate-app')
const generateJson = require('./generate-json')
const generateComponent = require('./generate-component')

const emitFileCaches = {}

function emitFile (filePath, source, compilation) {
  const emitFileMD5 = md5(filePath + source)
  if (emitFileCaches[filePath] !== emitFileMD5) {
    emitFileCaches[filePath] = emitFileMD5
    compilation.assets[filePath] = {
      size () {
        return Buffer.byteLength(source, 'utf8')
      },
      source () {
        return source
      }
    }
  }
}

function addSubPackagesRequire (compilation) {
  if (!process.env.UNI_OPT_SUBPACKAGES) {
    return
  }
  const assetsKeys = Object.keys(compilation.assets)
  Object.keys(process.UNI_SUBPACKAGES).forEach(root => {
    const subPackageVendorPath = normalizePath(path.join(root, 'common/vendor.js'))
    if (assetsKeys.indexOf(subPackageVendorPath) !== -1) {
      // TODO 理论上仅需在分包第一个 js 中添加 require common vendor,但目前不同平台可能顺序不一致,
      // 故 每个分包里的 js 里均添加一次 require
      assetsKeys.forEach(name => {
        if (
          path.extname(name) === '.js' &&
          name.indexOf(root) === 0 &&
          name !== subPackageVendorPath
        ) {
          const source = `require('${normalizePath(path.relative(path.dirname(name), subPackageVendorPath))}');` +
            compilation.assets[name].source()

          compilation.assets[name] = {
            size () {
              return Buffer.byteLength(source, 'utf8')
            },
            source () {
              return source
            }
          }
        }
      })
    }
  })
}

class WebpackUniMPPlugin {
  apply (compiler) {
    compiler.hooks.emit.tapPromise('webpack-uni-mp-emit', compilation => {
      return new Promise((resolve, reject) => {
        addSubPackagesRequire(compilation)

        generateJson(compilation)

        // app.js,app.wxss
        generateApp(compilation)
          .forEach(({
            file,
            source
          }) => emitFile(file, source, compilation))

        generateComponent(compilation)

        resolve()
      })
    })

    compiler.hooks.invalid.tap('webpack-uni-mp-invalid', (fileName, changeTime) => {
      if (fileName && typeof fileName === 'string' && path.basename(fileName) === 'pages.json') { // 重新解析 entry
        try {
          parseEntry()
        } catch (e) {
          console.error(e)
        }
      }
    })
  }
}

module.exports = WebpackUniMPPlugin