'f'
mh-two-thousand-and-two
2024-04-12 26f2711ef9461961fb953e2b497bd314ef95e345
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
const path = require('path')
 
const parser = require('@babel/parser')
 
const {
  removeExt,
  hyphenate,
  normalizePath,
  getComponentName,
  jsPreprocessOptions
} = require('@dcloudio/uni-cli-shared')
 
const {
  getBabelParserOptions
} = require('@dcloudio/uni-cli-shared/lib/platform')
 
const {
  isBuiltInComponentPath
} = require('@dcloudio/uni-cli-shared/lib/pages')
 
const {
  updateUsingComponents
} = require('@dcloudio/uni-cli-shared/lib/cache')
 
const preprocessor = require('@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/preprocess')
 
const traverse = require('./babel/scoped-component-traverse')
 
const {
  resolve,
  normalizeNodeModules,
  getIssuer
} = require('./shared')
 
const {
  findBabelLoader,
  addDynamicImport
} = require('./babel/util')
 
const uniI18n = require('@dcloudio/uni-cli-i18n')
 
module.exports = function (content, map) {
  this.cacheable && this.cacheable()
 
  content = preprocessor.preprocess(content, jsPreprocessOptions.context, {
    type: jsPreprocessOptions.type
  })
 
  let resourcePath = normalizeNodeModules(removeExt(normalizePath(path.relative(process.env.UNI_INPUT_DIR, this
    .resourcePath))))
 
  let type = ''
  if (resourcePath === 'App') {
    type = 'App'
  } else if (process.UNI_ENTRY[resourcePath]) {
    type = 'Page'
  }
  // <script src=""/>
  if (!type) {
    const moduleIssuer = getIssuer(this._compilation, this._module)
    if (moduleIssuer) {
      const moduleIssuerIssuer = getIssuer(this._compilation, moduleIssuer)
      if (moduleIssuerIssuer) {
        resourcePath = normalizeNodeModules(removeExt(normalizePath(path.relative(process.env.UNI_INPUT_DIR, moduleIssuerIssuer.resource))))
        if (resourcePath === 'App') {
          type = 'App'
        } else if (process.UNI_ENTRY[resourcePath]) {
          type = 'Page'
        }
      }
    }
  }
 
  if ( // windows 上 page-meta, navigation-bar 可能在不同盘上
    /^win/.test(process.platform) &&
    path.isAbsolute(resourcePath) &&
    isBuiltInComponentPath(resourcePath)
  ) {
    resourcePath = normalizePath(path.relative(process.env.UNI_CLI_CONTEXT, resourcePath))
  }
 
  if (!type) {
    type = 'Component'
  }
 
  const {
    state: {
      components
    }
  } = traverse(parser.parse(content, getBabelParserOptions()), {
    type,
    components: [],
    filename: this.resourcePath
  })
 
  const callback = this.async()
 
  if (!components.length) {
    if (type === 'App') {
      callback(null, content, map)
      return
    }
    // 防止组件从有到无,App.vue 中不支持使用组件
    updateUsingComponents(resourcePath, Object.create(null), type)
    callback(null, content, map)
    return
  }
 
  const dynamicImports = Object.create(null)
  Promise.all(components.map(component => {
    return resolve.call(this, component.source).then(resolved => {
      component.name = getComponentName(hyphenate(component.name))
      const source = component.source
      component.source = normalizeNodeModules(removeExt(path.relative(process.env.UNI_INPUT_DIR,
        resolved)))
      // 非页面组件才需要 dynamic import
      if (!process.UNI_ENTRY[component.source]) {
        dynamicImports[source] = {
          identifier: component.value,
          chunkName: component.source,
          source: source
        }
      }
    })
  })).then(() => {
    const usingComponents = Object.create(null)
    components.forEach(({
      name,
      source
    }) => {
      usingComponents[name] = `/${source}`
    })
 
    let babelLoader = findBabelLoader(this.loaders)
    if (!babelLoader) {
      callback(new Error(uniI18n.__('mpLoader.findFail', {
        0: 'babel-loader'
      })), content)
    } else {
      const webpack = require('webpack')
      if (webpack.version[0] > 4) {
        // clone babelLoader and options
        const index = this.loaders.indexOf(babelLoader)
        const newBabelLoader = Object.assign({}, babelLoader)
        Object.assign(newBabelLoader, { options: Object.assign({}, babelLoader.options) })
        this.loaders.splice(index, 1, newBabelLoader)
        babelLoader = newBabelLoader
      }
      addDynamicImport(babelLoader, resourcePath, dynamicImports)
 
      updateUsingComponents(resourcePath, usingComponents, type)
      callback(null, content, map)
    }
  }, err => {
    callback(err, content, map)
  })
}