@mpxjs/webpack-plugin 2.9.32 → 2.9.33-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  const NullDependency = require('webpack/lib/dependencies/NullDependency')
2
2
  const makeSerializable = require('webpack/lib/util/makeSerializable')
3
3
  const addQuery = require('../utils/add-query')
4
+ const isUrlRequest = require('../utils/is-url-request')
4
5
 
5
6
  class RecordGlobalComponentsDependency extends NullDependency {
6
7
  constructor (usingComponents, context) {
@@ -16,9 +17,19 @@ class RecordGlobalComponentsDependency extends NullDependency {
16
17
  mpxAction (module, compilation, callback) {
17
18
  const mpx = compilation.__mpx__
18
19
  const { usingComponents, context } = this
20
+ const resolver = compilation.resolverFactory.get('normal', module.resolveOptions)
19
21
  Object.keys(usingComponents).forEach((key) => {
20
22
  const request = usingComponents[key]
21
- mpx.usingComponents[key] = addQuery(request, {
23
+ if (!isUrlRequest(request, mpx.projectRoot)) {
24
+ mpx.globalComponentsModuleId[key] = mpx.getModuleId(request, false)
25
+ } else {
26
+ resolver.resolve({}, this.context, request, {}, (err, resource) => {
27
+ if (err) return
28
+ mpx.globalComponentsModuleId[key] = mpx.getModuleId(resource, false)
29
+ })
30
+ }
31
+
32
+ mpx.globalComponents[key] = addQuery(request, {
22
33
  context
23
34
  })
24
35
  })
package/lib/index.js CHANGED
@@ -61,7 +61,7 @@ const async = require('async')
61
61
  const { parseQuery } = require('loader-utils')
62
62
  const stringifyLoadersAndResource = require('./utils/stringify-loaders-resource')
63
63
  const emitFile = require('./utils/emit-file')
64
- const { MPX_PROCESSED_FLAG, MPX_DISABLE_EXTRACTOR_CACHE } = require('./utils/const')
64
+ const { MPX_PROCESSED_FLAG, MPX_DISABLE_EXTRACTOR_CACHE, MPX_APP_MODULE_ID } = require('./utils/const')
65
65
  const isEmptyObject = require('./utils/is-empty-object')
66
66
  require('./utils/check-core-version-match')
67
67
 
@@ -165,6 +165,7 @@ class MpxWebpackPlugin {
165
165
  include: () => true
166
166
  }
167
167
  options.customOutputPath = options.customOutputPath || null
168
+ options.customComponentModuleId = options.customComponentModuleId || null
168
169
  options.nativeConfig = Object.assign({
169
170
  cssLangs: ['css', 'less', 'stylus', 'scss', 'sass']
170
171
  }, options.nativeConfig)
@@ -620,7 +621,8 @@ class MpxWebpackPlugin {
620
621
  assetsModulesMap: new Map(),
621
622
  // 记录与asset相关联的ast,用于体积分析和esCheck,避免重复parse
622
623
  assetsASTsMap: new Map(),
623
- usingComponents: {},
624
+ globalComponents: {},
625
+ globalComponentsModuleId: {},
624
626
  // todo es6 map读写性能高于object,之后会逐步替换
625
627
  wxsAssetsCache: new Map(),
626
628
  addEntryPromiseMap: new Map(),
@@ -681,6 +683,14 @@ class MpxWebpackPlugin {
681
683
  compilation.addEntry(compiler.context, dep, { name }, callback)
682
684
  return dep
683
685
  },
686
+ getModuleId: (filePath, isApp = false) => {
687
+ const customComponentModuleId = this.options.customComponentModuleId
688
+ if (typeof customComponentModuleId === 'function') {
689
+ const customModuleId = customComponentModuleId(filePath, isApp)
690
+ if (customModuleId) return customModuleId
691
+ }
692
+ return isApp ? MPX_APP_MODULE_ID : 'm' + mpx.pathHash(filePath)
693
+ },
684
694
  getEntryNode: (module, type) => {
685
695
  const entryNodeModulesMap = mpx.entryNodeModulesMap
686
696
  let entryNode = entryNodeModulesMap.get(module)
@@ -195,11 +195,16 @@ module.exports = function (content) {
195
195
  error: emitError,
196
196
  data: {
197
197
  // polyfill global usingComponents & record globalComponents
198
- globalComponents: mpx.usingComponents
198
+ globalComponents: mpx.globalComponents
199
199
  }
200
200
  }
201
201
  if (!isApp) {
202
202
  rulesRunnerOptions.mainKey = pagesMap[resourcePath] ? 'page' : 'component'
203
+ // polyfill global usingComponents
204
+ // todo 传入rulesRunner中进行按平台转换
205
+ rulesRunnerOptions.data = {
206
+ globalComponents: mpx.globalComponents
207
+ }
203
208
  }
204
209
 
205
210
  const rulesRunner = getRulesRunner(rulesRunnerOptions)
@@ -209,11 +214,11 @@ module.exports = function (content) {
209
214
  }
210
215
 
211
216
  if (isApp) {
212
- Object.assign(mpx.usingComponents, json.usingComponents)
217
+ Object.assign(mpx.globalComponents, json.usingComponents)
213
218
  // 在 rulesRunner 运行后保存全局注册组件
214
219
  // todo 其余地方在使用mpx.usingComponents时存在缓存问题,要规避该问题需要在所有使用mpx.usingComponents的loader中添加app resourcePath作为fileDependency,但对于缓存有效率影响巨大
215
220
  // todo 需要考虑一种精准控制缓存的方式,仅在全局组件发生变更时才使相关使用方的缓存失效,例如按需在相关模块上动态添加request query?
216
- this._module.addPresentationalDependency(new RecordGlobalComponentsDependency(mpx.usingComponents, this.context))
221
+ this._module.addPresentationalDependency(new RecordGlobalComponentsDependency(mpx.globalComponents, this.context))
217
222
  }
218
223
 
219
224
  const processComponents = (components, context, callback) => {
package/lib/loader.js CHANGED
@@ -17,7 +17,8 @@ const RecordResourceMapDependency = require('./dependencies/RecordResourceMapDep
17
17
  const RecordVueContentDependency = require('./dependencies/RecordVueContentDependency')
18
18
  const CommonJsVariableDependency = require('./dependencies/CommonJsVariableDependency')
19
19
  const tsWatchRunLoaderFilter = require('./utils/ts-loader-watch-run-loader-filter')
20
- const { MPX_APP_MODULE_ID } = require('./utils/const')
20
+ const resolve = require('./utils/resolve')
21
+ const isUrlRequestRaw = require('./utils/is-url-request')
21
22
  const path = require('path')
22
23
  const processMainScript = require('./web/processMainScript')
23
24
  const getRulesRunner = require('./platform')
@@ -50,6 +51,9 @@ module.exports = function (content) {
50
51
  const localSrcMode = queryObj.mode
51
52
  const srcMode = localSrcMode || globalSrcMode
52
53
  const autoScope = matchCondition(resourcePath, mpx.autoScopeRules)
54
+ const root = mpx.projectRoot
55
+
56
+ const isUrlRequest = r => isUrlRequestRaw(r, root)
53
57
 
54
58
  const emitWarning = (msg) => {
55
59
  this.emitWarning(
@@ -75,15 +79,16 @@ module.exports = function (content) {
75
79
  ctorType = queryObj.isComponent ? 'component' : 'page'
76
80
  this._module.addPresentationalDependency(new RecordResourceMapDependency(resourcePath, ctorType, entryName, packageRoot))
77
81
  }
82
+ const isApp = ctorType === 'app'
78
83
 
79
- if (ctorType === 'app') {
84
+ if (isApp) {
80
85
  const appName = getEntryName(this)
81
86
  if (appName) this._module.addPresentationalDependency(new AppEntryDependency(resourcePath, appName))
82
87
  }
83
88
  const loaderContext = this
84
89
  const isProduction = this.minimize || process.env.NODE_ENV === 'production'
85
90
  const filePath = this.resourcePath
86
- const moduleId = ctorType === 'app' ? MPX_APP_MODULE_ID : '_' + mpx.pathHash(filePath)
91
+ const moduleId = mpx.getModuleId(resourcePath, isApp)
87
92
 
88
93
  const parts = parseComponent(content, {
89
94
  filePath,
@@ -104,20 +109,26 @@ module.exports = function (content) {
104
109
  getJSONContent(parts.json || {}, null, loaderContext, (err, content) => {
105
110
  if (err) return callback(err)
106
111
  if (parts.json) parts.json.content = content
107
- callback()
112
+ callback(null, content || '{}')
108
113
  })
109
114
  },
110
- (callback) => {
111
- const hasScoped = parts.styles.some(({ scoped }) => scoped) || autoScope
112
- const templateAttrs = parts.template && parts.template.attrs
113
- const hasComment = templateAttrs && templateAttrs.comments
114
- const isNative = false
115
-
116
- let usingComponents = [].concat(Object.keys(mpx.usingComponents))
115
+ (jsonContent, callback) => {
116
+ if (!jsonContent) return callback(null, {})
117
117
  let componentPlaceholder = []
118
118
  let componentGenerics = {}
119
-
120
- if (parts.json && parts.json.content) {
119
+ let currentUsingComponentsModuleId = {}
120
+ let usingComponents = [].concat(Object.keys(mpx.globalComponents))
121
+ const finalCallback = (err) => {
122
+ currentUsingComponentsModuleId = Object.assign(currentUsingComponentsModuleId, mpx.globalComponentsModuleId)
123
+ callback(err, {
124
+ componentPlaceholder,
125
+ componentGenerics,
126
+ currentUsingComponentsModuleId,
127
+ usingComponents
128
+ })
129
+ }
130
+ try {
131
+ const ret = JSON5.parse(jsonContent)
121
132
  const rulesRunnerOptions = {
122
133
  mode,
123
134
  srcMode,
@@ -131,21 +142,60 @@ module.exports = function (content) {
131
142
  }
132
143
  const rulesRunner = getRulesRunner(rulesRunnerOptions)
133
144
  try {
134
- const ret = JSON5.parse(parts.json.content)
135
145
  if (rulesRunner) rulesRunner(ret)
136
- if (ret.usingComponents) {
137
- usingComponents = usingComponents.concat(Object.keys(ret.usingComponents))
138
- }
139
- if (ret.componentPlaceholder) {
140
- componentPlaceholder = componentPlaceholder.concat(Object.values(ret.componentPlaceholder))
141
- }
142
- if (ret.componentGenerics) {
143
- componentGenerics = Object.assign({}, ret.componentGenerics)
144
- }
145
146
  } catch (e) {
146
- return callback(e)
147
+ return finalCallback(e)
148
+ }
149
+
150
+ if (ret.componentPlaceholder) {
151
+ componentPlaceholder = componentPlaceholder.concat(Object.values(ret.componentPlaceholder))
147
152
  }
153
+ if (ret.componentGenerics) {
154
+ componentGenerics = Object.assign({}, ret.componentGenerics)
155
+ }
156
+ if (ret.usingComponents) {
157
+ // fixUsingComponent(ret.usingComponents, mode)
158
+ usingComponents = usingComponents.concat(Object.keys(ret.usingComponents))
159
+ async.eachOf(ret.usingComponents, (component, name, callback) => {
160
+ if (!isUrlRequest(component)) {
161
+ const moduleId = mpx.getModuleId(component, isApp)
162
+ if (!isApp) {
163
+ currentUsingComponentsModuleId[name] = moduleId
164
+ }
165
+ return callback()
166
+ }
167
+ resolve(this.context, component, loaderContext, (err, resource) => {
168
+ if (err) return callback(err)
169
+ const { rawResourcePath } = parseRequest(resource)
170
+ const moduleId = mpx.getModuleId(rawResourcePath, isApp)
171
+ if (!isApp) {
172
+ currentUsingComponentsModuleId[name] = moduleId
173
+ }
174
+ callback()
175
+ })
176
+ }, (err) => {
177
+ finalCallback(err)
178
+ })
179
+ } else {
180
+ finalCallback(null)
181
+ }
182
+ } catch (err) {
183
+ finalCallback(err)
148
184
  }
185
+ },
186
+ (componentInfo, callback) => {
187
+ const {
188
+ componentPlaceholder,
189
+ componentGenerics,
190
+ currentUsingComponentsModuleId,
191
+ usingComponents
192
+ } = componentInfo
193
+
194
+ const hasScoped = parts.styles.some(({ scoped }) => scoped) || autoScope
195
+ const templateAttrs = parts.template && parts.template.attrs
196
+ const hasComment = templateAttrs && templateAttrs.comments
197
+ const isNative = false
198
+
149
199
  // 处理mode为web时输出vue格式文件
150
200
  if (mode === 'web') {
151
201
  if (ctorType === 'app' && !queryObj.isApp) {
@@ -255,7 +305,7 @@ module.exports = function (content) {
255
305
  }
256
306
 
257
307
  // 为app注入i18n
258
- if (i18n && ctorType === 'app') {
308
+ if (i18n && isApp) {
259
309
  const i18nWxsPath = normalize.lib('runtime/i18n.wxs')
260
310
  const i18nWxsLoaderPath = normalize.lib('wxs/i18n-loader.js')
261
311
  const i18nWxsRequest = i18nWxsLoaderPath + '!' + i18nWxsPath
@@ -300,6 +350,7 @@ module.exports = function (content) {
300
350
  isNative,
301
351
  moduleId,
302
352
  usingComponents,
353
+ usingComponentsModuleId: currentUsingComponentsModuleId,
303
354
  componentPlaceholder
304
355
  // 添加babel处理渲染函数中可能包含的...展开运算符
305
356
  // 由于...运算符应用范围极小以及babel成本极高,先关闭此特性后续看情况打开
@@ -328,7 +379,7 @@ module.exports = function (content) {
328
379
  })
329
380
  }
330
381
 
331
- if (parts.styles.filter(style => !style.src).length === 0 && ctorType === 'app' && mode === 'ali') {
382
+ if (parts.styles.filter(style => !style.src).length === 0 && isApp && mode === 'ali') {
332
383
  output += getRequire('styles', {}, {}, parts.styles.length) + '\n'
333
384
  }
334
385
 
@@ -6,11 +6,13 @@ const createHelpers = require('./helpers')
6
6
  const getJSONContent = require('./utils/get-json-content')
7
7
  const async = require('async')
8
8
  const { matchCondition } = require('./utils/match-condition')
9
- const { JSON_JS_EXT, MPX_APP_MODULE_ID } = require('./utils/const')
9
+ const { JSON_JS_EXT } = require('./utils/const')
10
10
  const getRulesRunner = require('./platform')
11
11
  const getEntryName = require('./utils/get-entry-name')
12
12
  const AppEntryDependency = require('./dependencies/AppEntryDependency')
13
13
  const RecordResourceMapDependency = require('./dependencies/RecordResourceMapDependency')
14
+ const isUrlRequestRaw = require('./utils/is-url-request')
15
+ const resolve = require('./utils/resolve')
14
16
 
15
17
  // todo native-loader考虑与mpx-loader或加强复用,原生组件约等于4个区块都为src的.mpx文件
16
18
  module.exports = function (content) {
@@ -25,6 +27,7 @@ module.exports = function (content) {
25
27
  const loaderContext = this
26
28
  const isProduction = this.minimize || process.env.NODE_ENV === 'production'
27
29
  const filePath = this.resourcePath
30
+ const moduleId = mpx.getModuleId(filePath)
28
31
  const { resourcePath, queryObj } = parseRequest(this.resource)
29
32
  const packageRoot = queryObj.packageRoot || mpx.currentPackageRoot
30
33
  const mode = mpx.mode
@@ -39,6 +42,9 @@ module.exports = function (content) {
39
42
  const typeExtMap = config[srcMode].typeExtMap
40
43
  const typeResourceMap = {}
41
44
  const autoScope = matchCondition(resourcePath, mpx.autoScopeRules)
45
+ const root = mpx.projectRoot
46
+
47
+ const isUrlRequest = r => isUrlRequestRaw(r, root)
42
48
 
43
49
  const CSS_LANG_EXT_MAP = {
44
50
  less: '.less',
@@ -114,7 +120,30 @@ module.exports = function (content) {
114
120
  new Error('[native-loader][' + this.resource + ']: ' + msg)
115
121
  )
116
122
  }
123
+ let ctorType = pagesMap[resourcePath]
124
+ ? 'page'
125
+ : componentsMap[resourcePath]
126
+ ? 'component'
127
+ : 'app'
128
+ // 处理构造器类型
129
+ const ctor = ctorType === 'page'
130
+ ? (mpx.forceUsePageCtor || mode === 'ali') ? 'Page' : 'Component'
131
+ : ctorType === 'component'
132
+ ? 'Component'
133
+ : 'App'
134
+
135
+ // 支持资源query传入isPage或isComponent支持页面/组件单独编译
136
+ if (ctorType === 'app' && (queryObj.isComponent || queryObj.isPage)) {
137
+ const entryName = getEntryName(this) || mpx.getOutputPath(resourcePath, queryObj.isComponent ? 'component' : 'page')
138
+ ctorType = queryObj.isComponent ? 'component' : 'page'
139
+ this._module.addPresentationalDependency(new RecordResourceMapDependency(resourcePath, ctorType, entryName, packageRoot))
140
+ }
141
+ const isApp = ctorType === 'app'
117
142
 
143
+ if (ctorType === 'app') {
144
+ const appName = getEntryName(this)
145
+ if (appName) this._module.addPresentationalDependency(new AppEntryDependency(resourcePath, appName))
146
+ }
118
147
  // 先读取json获取usingComponents信息
119
148
  async.waterfall([
120
149
  (callback) => {
@@ -145,62 +174,75 @@ module.exports = function (content) {
145
174
  src: typeResourceMap.json,
146
175
  useJSONJS
147
176
  }, null, this, callback)
148
- }, (content, callback) => {
177
+ },
178
+ (jsonContent, callback) => {
179
+ if (!jsonContent) return callback(null, {})
149
180
  let componentPlaceholder = []
150
- let json
151
- try {
152
- json = JSON5.parse(content)
153
- } catch (e) {
154
- return callback(e)
155
- }
156
- let usingComponents = Object.keys(mpx.usingComponents)
157
- const rulesRunnerOptions = {
158
- mode,
159
- srcMode,
160
- type: 'json',
161
- waterfall: true,
162
- warn: emitWarning,
163
- error: emitError
164
- }
165
-
166
- let ctorType = pagesMap[resourcePath]
167
- ? 'page'
168
- : componentsMap[resourcePath]
169
- ? 'component'
170
- : 'app'
171
-
172
- // 支持资源query传入isPage或isComponent支持页面/组件单独编译
173
- if (ctorType === 'app' && (queryObj.isComponent || queryObj.isPage)) {
174
- const entryName = getEntryName(this) || mpx.getOutputPath(resourcePath, queryObj.isComponent ? 'component' : 'page')
175
- ctorType = queryObj.isComponent ? 'component' : 'page'
176
- this._module.addPresentationalDependency(new RecordResourceMapDependency(resourcePath, ctorType, entryName, packageRoot))
181
+ let currentUsingComponentsModuleId = {}
182
+ let usingComponents = [].concat(Object.keys(mpx.globalComponents))
183
+ const finalCallback = (err) => {
184
+ currentUsingComponentsModuleId = Object.assign(currentUsingComponentsModuleId, mpx.globalComponentsModuleId)
185
+ callback(err, {
186
+ componentPlaceholder,
187
+ currentUsingComponentsModuleId,
188
+ usingComponents
189
+ })
177
190
  }
191
+ try {
192
+ const json = JSON5.parse(jsonContent)
193
+ const rulesRunnerOptions = {
194
+ mode,
195
+ srcMode,
196
+ type: 'json',
197
+ waterfall: true,
198
+ warn: emitWarning,
199
+ error: emitError
200
+ }
201
+ if (ctorType !== 'app') {
202
+ rulesRunnerOptions.mainKey = pagesMap[resourcePath] ? 'page' : 'component'
203
+ }
204
+ const rulesRunner = getRulesRunner(rulesRunnerOptions)
205
+ if (rulesRunner) rulesRunner(json)
178
206
 
179
- // 处理构造器类型
180
- const ctor = ctorType === 'page'
181
- ? (mpx.forceUsePageCtor || mode === 'ali') ? 'Page' : 'Component'
182
- : ctorType === 'component'
183
- ? 'Component'
184
- : 'App'
185
-
186
- if (ctorType === 'app') {
187
- const appName = getEntryName(this)
188
- if (appName) this._module.addPresentationalDependency(new AppEntryDependency(resourcePath, appName))
207
+ if (json.componentPlaceholder) {
208
+ componentPlaceholder = componentPlaceholder.concat(Object.values(json.componentPlaceholder))
209
+ }
210
+ if (json.usingComponents) {
211
+ usingComponents = usingComponents.concat(Object.keys(json.usingComponents))
212
+ async.eachOf(json.usingComponents, (component, name, callback) => {
213
+ if (!isUrlRequest(component)) {
214
+ const moduleId = mpx.getModuleId(component, isApp)
215
+ if (!isApp) {
216
+ currentUsingComponentsModuleId[name] = moduleId
217
+ }
218
+ return callback()
219
+ }
220
+ resolve(this.context, component, loaderContext, (err, resource) => {
221
+ if (err) return callback(err)
222
+ const { rawResourcePath } = parseRequest(resource)
223
+ const moduleId = mpx.getModuleId(rawResourcePath, isApp)
224
+ if (!isApp) {
225
+ currentUsingComponentsModuleId[name] = moduleId
226
+ }
227
+ callback()
228
+ })
229
+ }, (err) => {
230
+ finalCallback(err)
231
+ })
232
+ } else {
233
+ finalCallback(null)
234
+ }
235
+ } catch (e) {
236
+ return finalCallback(e)
189
237
  }
238
+ },
239
+ (componentInfo, callback) => {
240
+ const {
241
+ componentPlaceholder,
242
+ currentUsingComponentsModuleId,
243
+ usingComponents
244
+ } = componentInfo
190
245
 
191
- const moduleId = ctorType === 'app' ? MPX_APP_MODULE_ID : '_' + mpx.pathHash(filePath)
192
-
193
- if (ctorType !== 'app') {
194
- rulesRunnerOptions.mainKey = pagesMap[resourcePath] ? 'page' : 'component'
195
- }
196
- const rulesRunner = getRulesRunner(rulesRunnerOptions)
197
- if (rulesRunner) rulesRunner(json)
198
- if (json.usingComponents) {
199
- usingComponents = usingComponents.concat(Object.keys(json.usingComponents))
200
- }
201
- if (json.componentPlaceholder) {
202
- componentPlaceholder = componentPlaceholder.concat(Object.values(json.componentPlaceholder))
203
- }
204
246
  const {
205
247
  getRequire
206
248
  } = createHelpers(loaderContext)
@@ -222,7 +264,8 @@ module.exports = function (content) {
222
264
  isNative,
223
265
  moduleId,
224
266
  usingComponents,
225
- componentPlaceholder
267
+ componentPlaceholder,
268
+ usingComponentsModuleId: currentUsingComponentsModuleId
226
269
  })
227
270
  // if (template.src) extraOptions.resourcePath = resourcePath
228
271
  break
@@ -15,7 +15,7 @@ module.exports = function (css, map) {
15
15
  const cb = this.async()
16
16
  const { resourcePath, queryObj } = parseRequest(this.resource)
17
17
  const mpx = this.getMpx()
18
- const id = queryObj.moduleId || queryObj.mid || '_' + mpx.pathHash(resourcePath)
18
+ const id = queryObj.moduleId || queryObj.mid || mpx.getModuleId(resourcePath)
19
19
  const appInfo = mpx.appInfo
20
20
  const defs = mpx.defs
21
21
  const mode = mpx.mode