index.js 3.1 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 97 98 99 100 101 102 103 104 105 106 107
const path = require('path')

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

const {
  getPages,
  getSubPages,
  getTemplates,
  getCompilerOptions
} = require('../shared')

const generateApp = require('./generate-app')

const generatePagesWxml = require('./generate-pages-wxml')

const generateComponentsWxml = require('./generate-components-wxml')

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
      }
    }
  }
}

class WebpackUniMPPlugin {
  apply (compiler) {
    compiler.hooks.emit.tapPromise('webpack-uni-mp-emit', compilation => {
      return new Promise((resolve, reject) => {
        // app.js,app.wxss
        generateApp(compilation)
          .forEach(({
            file,
            source
          }) => emitFile(file, source, compilation))

        if (process.env.UNI_PLATFORM === 'mp-alipay') { // 支付宝页面 axml 仅生成一个(因 template 内不能使用自定义组件,比如 rich-text )
          const pageAxmls = {}
          generatePagesWxml(getPages(), getSubPages())
            .forEach(({
              file,
              source
            }) => {
              pageAxmls[file] = source
            })
          // components wxml
          generateComponentsWxml(getTemplates(), getCompilerOptions(), Array.from(new Set(
            Object.values(process.UNI_SUB_PACKAGES_ROOT))))
            .forEach(({
              file,
              source
            }) => {
              const pageAxmlPath = file.replace('.vue', '')
              const pageAxmlSource = pageAxmls[pageAxmlPath]
              if (pageAxmlSource) { // page.axml
                emitFile(pageAxmlPath, source + '\n' + pageAxmlSource,
                  compilation)
              } else {
                emitFile(file, source, compilation)
              }
            })
        } else {
          // pages wxml
          generatePagesWxml(getPages(), getSubPages())
            .forEach(({
              file,
              source
            }) => emitFile(file, source, compilation))

          // components wxml
          generateComponentsWxml(getTemplates(), getCompilerOptions(), Array.from(new Set(
            Object.values(process.UNI_SUB_PACKAGES_ROOT))))
            .forEach(({
              file,
              source
            }) => emitFile(file, source, 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