docs: function scan (webpack, webpackConfig, options) {
    return getMetaInfo()
      .then(function (info) {
        var builtInPkgMap = info['built-in']
        var builtInComponentMap = builtInPkgMap.component
        var builtInModuleMap = builtInPkgMap.module
        var aliPkgMap = info['ali']
        var aliComponentMap = aliPkgMap.component
        var aliModuleMap = aliPkgMap.module
        var ignoreComponents = info['ignore']
        var componentMap = {}
        var moduleMap = {}
        var nodes = {}
        var allNodes = {}
  
        for (var key in builtInComponentMap) {
          nodes[key] = 0
          componentMap[key] = builtInComponentMap[key]
        }
        extend(moduleMap, builtInModuleMap)
        ignoreComponents.forEach(function (comp) {
          delete nodes[comp]
          delete componentMap[comp]
        })
        if (options && options.ali) {
          for (var key in aliComponentMap) {
            nodes[key] = 0
            componentMap[key] = aliComponentMap[key]
          }
          extend(moduleMap, aliModuleMap)
        }
  
        var config = extend({}, webpackConfig)
        var deferred = getDeferred()
  
        var mod = config.module
        var rules = mod.rules || mod.loaders
        if (!rules) {
          return console.error('webpack config missing rules.')
        }
        var is2 = !!mod.rules
        if (is2) {  // webpack 2.0
          rules.forEach(function (rule) {
            if (rule.use && isArray(rule.use)) { // use multiple loaders.
              var vueLoaderIndex = -1
              rule.use.forEach(function (use, idx) {
                if (typeof use === 'string' && use.match(/vue-loader/)) {
                  vueLoaderIndex = idx
                }
                else if (typeof use === 'object' && use.loader.match(/vue-loader/)) {
                  use.options = genVueOptions(use.options, nodes, allNodes)
                }
              })
              if (vueLoaderIndex > -1) {
                var options = genVueOptions({}, nodes, allNodes)
                rules.use[vueLoaderIndex] = {
                  loader: use,
                  options
                }
              }
            }
          })
        }
        else {  // webpack 1.0
          config.vue = genVueOptions(config.vue || {}, nodes, allNodes)
        }
        var loaders = webpackConfig.module.loaders
        webpack(webpackConfig, function (err, stats) {
          if (err) {
            console.error('[weex-vue-bundle-util] error:', err)
            deferred.reject(err)
          }
          else {
            var info = stats.toJson()
            if (stats.hasErrors()) {
              var error = info.errors
              console.error('[weex-vue-bundle-util] webpack compiling error:', error)
            }
            var parseAssetsOptions = {
              output: config.output
            }
            parseAssets(info.assets, parseAssetsOptions)
              .then(function (modules) {
                var pkgMap = {}
                var res = {
                  components: {},
                  modules: {},
                  pkgs: []
                }
                for (var key in nodes) {
                  if (nodes[key] > 0) {
                    var pkgName = componentMap[key]
                    res.components[key] = pkgName
                    pkgMap[pkgName] = true
                  }
                }
                for (var key in modules) {
                  if (modules[key] > 0 && moduleMap[key]) {
                    var pkgName = moduleMap[key]
                    res.modules[key] = pkgName
                    pkgMap[pkgName] = true
                  }
                }
                res.pkgs = Object.keys(pkgMap)
                if (res.pkgs && res.pkgs.length > 0 && options && options.output) {
                  res.peerDependencies = processPkgs(res.pkgs, options)
                }
                deferred.resolve(res)
              })
          }
        })
        return deferred.promise
      })
  }