@mpxjs/webpack-plugin 2.7.0-alpha.0 → 2.7.0-alpha.2

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.
Files changed (108) hide show
  1. package/README.md +1 -1
  2. package/lib/config.js +14 -0
  3. package/lib/dependencies/AddEntryDependency.js +24 -0
  4. package/lib/dependencies/AppEntryDependency.js +2 -0
  5. package/lib/dependencies/CommonJsAsyncDependency.js +51 -0
  6. package/lib/dependencies/CommonJsVariableDependency.js +13 -6
  7. package/lib/dependencies/DynamicEntryDependency.js +85 -41
  8. package/lib/dependencies/FlagPluginDependency.js +1 -0
  9. package/lib/dependencies/RecordIndependentDependency.js +44 -0
  10. package/lib/dependencies/RecordResourceMapDependency.js +62 -0
  11. package/lib/dependencies/RemoveEntryDependency.js +40 -0
  12. package/lib/dependencies/ResolveDependency.js +11 -6
  13. package/lib/extractor.js +17 -7
  14. package/lib/file-loader.js +2 -2
  15. package/lib/helpers.js +6 -12
  16. package/lib/independent-loader.js +52 -0
  17. package/lib/index.js +595 -304
  18. package/lib/json-compiler/helper.js +36 -32
  19. package/lib/json-compiler/index.js +119 -66
  20. package/lib/json-compiler/plugin.js +23 -7
  21. package/lib/loader.js +135 -90
  22. package/lib/native-loader.js +37 -69
  23. package/lib/parser.js +1 -2
  24. package/lib/partial-compile/index.js +35 -0
  25. package/lib/platform/json/wx/index.js +8 -3
  26. package/lib/platform/template/normalize-component-rules.js +2 -3
  27. package/lib/platform/template/wx/component-config/button.js +17 -5
  28. package/lib/platform/template/wx/component-config/image.js +4 -0
  29. package/lib/platform/template/wx/component-config/input.js +4 -0
  30. package/lib/platform/template/wx/component-config/navigator.js +1 -1
  31. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  32. package/lib/platform/template/wx/component-config/scroll-view.js +4 -0
  33. package/lib/platform/template/wx/component-config/switch.js +4 -0
  34. package/lib/platform/template/wx/component-config/text.js +4 -0
  35. package/lib/platform/template/wx/component-config/textarea.js +5 -0
  36. package/lib/platform/template/wx/component-config/view.js +4 -0
  37. package/lib/platform/template/wx/index.js +149 -3
  38. package/lib/record-loader.js +2 -2
  39. package/lib/resolve-loader.js +4 -1
  40. package/lib/resolver/AddEnvPlugin.js +4 -3
  41. package/lib/resolver/AddModePlugin.js +4 -3
  42. package/lib/resolver/FixDescriptionInfoPlugin.js +28 -0
  43. package/lib/resolver/PackageEntryPlugin.js +23 -36
  44. package/lib/runtime/base.styl +5 -0
  45. package/lib/runtime/components/tenon/getInnerListeners.js +317 -0
  46. package/lib/runtime/components/tenon/tenon-button.vue +305 -0
  47. package/lib/runtime/components/tenon/tenon-image.vue +61 -0
  48. package/lib/runtime/components/tenon/tenon-input.vue +99 -0
  49. package/lib/runtime/components/tenon/tenon-rich-text.vue +21 -0
  50. package/lib/runtime/components/tenon/tenon-scroll-view.vue +124 -0
  51. package/lib/runtime/components/tenon/tenon-switch.vue +91 -0
  52. package/lib/runtime/components/tenon/tenon-text-area.vue +64 -0
  53. package/lib/runtime/components/tenon/tenon-text.vue +64 -0
  54. package/lib/runtime/components/tenon/tenon-view.vue +93 -0
  55. package/lib/runtime/components/tenon/util.js +44 -0
  56. package/lib/runtime/components/web/getInnerListeners.js +51 -45
  57. package/lib/runtime/components/web/mpx-image.vue +20 -5
  58. package/lib/runtime/components/web/mpx-keep-alive.vue +4 -1
  59. package/lib/runtime/components/web/mpx-movable-view.vue +6 -2
  60. package/lib/runtime/components/web/mpx-swiper.vue +37 -8
  61. package/lib/runtime/components/web/mpx-tab-bar-container.vue +2 -2
  62. package/lib/runtime/components/web/mpx-textarea.vue +1 -1
  63. package/lib/runtime/i18n.wxs +28 -8
  64. package/lib/runtime/optionProcessor.js +50 -20
  65. package/lib/runtime/optionProcessor.tenon.js +386 -0
  66. package/lib/runtime/stringify.wxs +6 -4
  67. package/lib/selector.js +23 -5
  68. package/lib/style-compiler/index.js +12 -13
  69. package/lib/style-compiler/load-postcss-config.js +3 -1
  70. package/lib/style-compiler/plugins/conditional-strip.js +68 -65
  71. package/lib/style-compiler/plugins/hm.js +20 -0
  72. package/lib/style-compiler/plugins/rpx.js +43 -37
  73. package/lib/style-compiler/plugins/scope-id.js +79 -72
  74. package/lib/style-compiler/plugins/trans-special.js +25 -18
  75. package/lib/style-compiler/plugins/trim.js +13 -7
  76. package/lib/style-compiler/plugins/vw.js +19 -12
  77. package/lib/template-compiler/bind-this.js +4 -4
  78. package/lib/template-compiler/compiler.js +172 -62
  79. package/lib/template-compiler/index.js +8 -9
  80. package/lib/template-compiler/trans-dynamic-class-expr.js +32 -22
  81. package/lib/tenon/index.js +105 -0
  82. package/lib/tenon/processJSON.js +356 -0
  83. package/lib/tenon/processScript.js +261 -0
  84. package/lib/tenon/processStyles.js +21 -0
  85. package/lib/tenon/processTemplate.js +133 -0
  86. package/lib/utils/const.js +6 -1
  87. package/lib/utils/eval-json-js.js +31 -0
  88. package/lib/utils/get-entry-name.js +3 -3
  89. package/lib/utils/get-json-content.js +42 -0
  90. package/lib/utils/get-relative-path.js +25 -0
  91. package/lib/utils/match-condition.js +4 -1
  92. package/lib/utils/normalize.js +4 -2
  93. package/lib/utils/resolve.js +13 -0
  94. package/lib/web/processJSON.js +113 -144
  95. package/lib/web/processScript.js +45 -38
  96. package/lib/web/processTemplate.js +56 -41
  97. package/lib/wxml/loader.js +1 -6
  98. package/lib/wxs/WxsModuleIdsPlugin.js +11 -14
  99. package/lib/wxs/i18n-loader.js +5 -4
  100. package/lib/wxs/loader.js +87 -56
  101. package/lib/wxs/pre-loader.js +30 -10
  102. package/lib/wxss/loader.js +3 -3
  103. package/lib/wxss/processCss.js +135 -131
  104. package/package.json +23 -17
  105. package/lib/built-in-loader.js +0 -49
  106. package/lib/dependencies/RecordStaticResourceDependency.js +0 -47
  107. package/lib/utils/get-main-compilation.js +0 -6
  108. package/lib/utils/read-json-for-src.js +0 -34
package/lib/loader.js CHANGED
@@ -3,7 +3,7 @@ const parseComponent = require('./parser')
3
3
  const createHelpers = require('./helpers')
4
4
  const loaderUtils = require('loader-utils')
5
5
  const parseRequest = require('./utils/parse-request')
6
- const matchCondition = require('./utils/match-condition')
6
+ const { matchCondition } = require('./utils/match-condition')
7
7
  const fixUsingComponent = require('./utils/fix-using-component')
8
8
  const addQuery = require('./utils/add-query')
9
9
  const async = require('async')
@@ -11,27 +11,38 @@ const processJSON = require('./web/processJSON')
11
11
  const processScript = require('./web/processScript')
12
12
  const processStyles = require('./web/processStyles')
13
13
  const processTemplate = require('./web/processTemplate')
14
- const readJsonForSrc = require('./utils/read-json-for-src')
14
+ const processForTenon = require('./tenon/index')
15
+ const getJSONContent = require('./utils/get-json-content')
15
16
  const normalize = require('./utils/normalize')
16
17
  const getEntryName = require('./utils/get-entry-name')
17
18
  const AppEntryDependency = require('./dependencies/AppEntryDependency')
19
+ const RecordResourceMapDependency = require('./dependencies/RecordResourceMapDependency')
20
+ const CommonJsVariableDependency = require('./dependencies/CommonJsVariableDependency')
21
+ const { MPX_APP_MODULE_ID } = require('./utils/const')
22
+ const path = require('path')
18
23
 
19
24
  module.exports = function (content) {
20
25
  this.cacheable()
21
26
 
27
+ // 兼容处理处理ts-loader中watch-run/updateFile逻辑,直接跳过当前loader及后续的vue-loader返回内容
28
+ if (path.extname(this.resourcePath) === '.ts') {
29
+ this.loaderIndex -= 2
30
+ return content
31
+ }
32
+
22
33
  const mpx = this.getMpx()
23
34
  if (!mpx) {
24
35
  return content
25
36
  }
26
37
  const { resourcePath, queryObj } = parseRequest(this.resource)
27
- const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
38
+
39
+ const packageRoot = queryObj.packageRoot || mpx.currentPackageRoot
40
+ const packageName = packageRoot || 'main'
41
+ const independent = queryObj.independent
28
42
  const pagesMap = mpx.pagesMap
29
43
  const componentsMap = mpx.componentsMap[packageName]
30
- const resolveMode = mpx.resolveMode
31
- const projectRoot = mpx.projectRoot
32
44
  const mode = mpx.mode
33
45
  const env = mpx.env
34
- const defs = mpx.defs
35
46
  const i18n = mpx.i18n
36
47
  const globalSrcMode = mpx.srcMode
37
48
  const localSrcMode = queryObj.mode
@@ -39,16 +50,6 @@ module.exports = function (content) {
39
50
  const vueContentCache = mpx.vueContentCache
40
51
  const autoScope = matchCondition(resourcePath, mpx.autoScopeRules)
41
52
 
42
- // 支持资源query传入page或component支持页面/组件单独编译
43
- if ((queryObj.component && !componentsMap[resourcePath]) || (queryObj.page && !pagesMap[resourcePath])) {
44
- const entryName = getEntryName(this)
45
- if (queryObj.component) {
46
- componentsMap[resourcePath] = entryName || 'noEntryComponent'
47
- } else {
48
- pagesMap[resourcePath] = entryName || 'noEntryPage'
49
- }
50
- }
51
-
52
53
  let ctorType = 'app'
53
54
  if (pagesMap[resourcePath]) {
54
55
  // page
@@ -58,42 +59,40 @@ module.exports = function (content) {
58
59
  ctorType = 'component'
59
60
  }
60
61
 
61
- if (ctorType === 'app') {
62
- const appName = getEntryName(this)
63
- this._module.addPresentationalDependency(new AppEntryDependency(resourcePath, appName))
62
+ // 支持资源query传入isPage或isComponent支持页面/组件单独编译
63
+ if (ctorType === 'app' && (queryObj.isComponent || queryObj.isPage)) {
64
+ const entryName = getEntryName(this) || (queryObj.isComponent ? 'noEntryComponent' : 'noEntryPage')
65
+ ctorType = queryObj.isComponent ? 'component' : 'page'
66
+ this._module.addPresentationalDependency(new RecordResourceMapDependency(resourcePath, ctorType, entryName, packageRoot))
64
67
  }
65
68
 
66
69
  const loaderContext = this
67
70
  const stringifyRequest = r => loaderUtils.stringifyRequest(loaderContext, r)
68
71
  const isProduction = this.minimize || process.env.NODE_ENV === 'production'
69
-
70
- const filePath = resourcePath
71
-
72
- const moduleId = 'm' + mpx.pathHash(filePath)
72
+ const filePath = this.resourcePath
73
+ const moduleId = ctorType === 'app' ? MPX_APP_MODULE_ID : 'm' + mpx.pathHash(filePath)
73
74
 
74
75
  const parts = parseComponent(content, {
75
76
  filePath,
76
77
  needMap: this.sourceMap,
77
78
  mode,
78
- defs,
79
79
  env
80
80
  })
81
81
 
82
+ const {
83
+ getRequire
84
+ } = createHelpers(loaderContext)
85
+
82
86
  let output = ''
83
87
  const callback = this.async()
84
88
 
85
89
  async.waterfall([
86
90
  (callback) => {
87
- const json = parts.json || {}
88
- if (json.src) {
89
- readJsonForSrc(json.src, loaderContext, (err, result) => {
90
- if (err) return callback(err)
91
- json.content = result
92
- callback()
93
- })
94
- } else {
91
+ getJSONContent(parts.json || {}, loaderContext, (err, content) => {
92
+ if (err) return callback(err)
93
+ if (parts.json) parts.json.content = content
95
94
  callback()
96
- }
95
+ })
97
96
  },
98
97
  (callback) => {
99
98
  // web输出模式下没有任何inject,可以通过cache直接返回,由于读取src json可能会新增模块依赖,需要在之后返回缓存内容
@@ -124,12 +123,51 @@ module.exports = function (content) {
124
123
  }
125
124
  }
126
125
 
127
- // 处理mode为web时输出vue格式文件
128
- if (mode === 'web') {
126
+ if (mode === 'tenon') {
129
127
  if (ctorType === 'app' && !queryObj.app) {
130
128
  const request = addQuery(this.resource, { app: true })
131
129
  output += `
132
130
  import App from ${stringifyRequest(request)}
131
+ import * as Tenon from '@hummer/tenon-vue'
132
+
133
+ Tenon.render(App)\n`
134
+ // 直接结束loader进入parse
135
+ this.loaderIndex = -1
136
+ return callback(null, output)
137
+ }
138
+ if (ctorType === 'page' && queryObj.tenon) {
139
+ console.log(resourcePath)
140
+ const request = addQuery(resourcePath, { page: true })
141
+ output += `
142
+ import page from ${stringifyRequest(request)}
143
+ import * as Tenon from '@hummer/tenon-vue'
144
+
145
+ Tenon.render(page)\n`
146
+ this.loaderIndex = -1
147
+ return callback(null, output)
148
+ }
149
+ return processForTenon({
150
+ mpx,
151
+ loaderContext,
152
+ isProduction,
153
+ queryObj,
154
+ filePath,
155
+ parts,
156
+ ctorType,
157
+ autoScope,
158
+ componentsMap,
159
+ vueContentCache,
160
+ moduleId,
161
+ callback
162
+ })
163
+ }
164
+
165
+ // 处理mode为web时输出vue格式文件
166
+ if (mode === 'web') {
167
+ if (ctorType === 'app' && !queryObj.isApp) {
168
+ const request = addQuery(this.resource, { isApp: true })
169
+ output += `
170
+ import App from ${stringifyRequest(request)}
133
171
  import Vue from 'vue'
134
172
  new Vue({
135
173
  el: '#app',
@@ -148,20 +186,15 @@ module.exports = function (content) {
148
186
  async.parallel([
149
187
  (callback) => {
150
188
  processTemplate(parts.template, {
189
+ loaderContext,
151
190
  hasScoped,
152
191
  hasComment,
153
192
  isNative,
154
- mode,
155
193
  srcMode,
156
- defs,
157
- loaderContext,
158
194
  moduleId,
159
195
  ctorType,
160
196
  usingComponents,
161
- componentGenerics,
162
- decodeHTMLText: mpx.decodeHTMLText,
163
- externalClasses: mpx.externalClasses,
164
- checkUsingComponents: mpx.checkUsingComponents
197
+ componentGenerics
165
198
  }, callback)
166
199
  },
167
200
  (callback) => {
@@ -173,16 +206,9 @@ module.exports = function (content) {
173
206
  },
174
207
  (callback) => {
175
208
  processJSON(parts.json, {
176
- mode,
177
- env,
178
- defs,
179
- resolveMode,
180
209
  loaderContext,
181
210
  pagesMap,
182
- pagesEntryMap: mpx.pagesEntryMap,
183
- pathHash: mpx.pathHash,
184
- componentsMap,
185
- projectRoot
211
+ componentsMap
186
212
  }, callback)
187
213
  }
188
214
  ], (err, res) => {
@@ -198,23 +224,20 @@ module.exports = function (content) {
198
224
  }
199
225
 
200
226
  processScript(parts.script, {
227
+ loaderContext,
201
228
  ctorType,
202
229
  srcMode,
203
- loaderContext,
204
230
  isProduction,
205
- i18n,
206
231
  componentGenerics,
207
- projectRoot,
208
232
  jsonConfig: jsonRes.jsonObj,
209
- componentId: queryObj.componentId || '',
233
+ outputPath: queryObj.outputPath || '',
210
234
  tabBarMap: jsonRes.tabBarMap,
211
235
  tabBarStr: jsonRes.tabBarStr,
212
236
  builtInComponentsMap: templateRes.builtInComponentsMap,
213
237
  genericsInfo: templateRes.genericsInfo,
214
238
  wxsModuleMap: templateRes.wxsModuleMap,
215
239
  localComponentsMap: jsonRes.localComponentsMap,
216
- localPagesMap: jsonRes.localPagesMap,
217
- forceDisableBuiltInLoader: mpx.forceDisableBuiltInLoader
240
+ localPagesMap: jsonRes.localPagesMap
218
241
  }, callback)
219
242
  }
220
243
  ], (err, scriptRes) => {
@@ -225,29 +248,48 @@ module.exports = function (content) {
225
248
  })
226
249
  }
227
250
 
228
- const {
229
- getRequire
230
- } = createHelpers(loaderContext)
251
+ const moduleGraph = this._compilation.moduleGraph
252
+
253
+ const issuer = moduleGraph.getIssuer(this._module)
254
+
255
+ if (issuer) {
256
+ return callback(new Error(`Current ${ctorType} [${this.resourcePath}] is issued by [${issuer.resource}], which is not allowed!`))
257
+ }
258
+
259
+ if (ctorType === 'app') {
260
+ const appName = getEntryName(this)
261
+ this._module.addPresentationalDependency(new AppEntryDependency(resourcePath, appName))
262
+ }
231
263
 
232
264
  // 注入模块id及资源路径
233
265
  output += `global.currentModuleId = ${JSON.stringify(moduleId)}\n`
234
266
  if (!isProduction) {
235
267
  output += `global.currentResource = ${JSON.stringify(filePath)}\n`
236
268
  }
237
- if (ctorType === 'app' && i18n) {
238
- output += `global.i18n = ${JSON.stringify({ locale: i18n.locale, version: 0 })}\n`
239
269
 
270
+ // 为app注入i18n
271
+ if (i18n && ctorType === 'app') {
240
272
  const i18nWxsPath = normalize.lib('runtime/i18n.wxs')
241
273
  const i18nWxsLoaderPath = normalize.lib('wxs/i18n-loader.js')
242
274
  const i18nWxsRequest = i18nWxsLoaderPath + '!' + i18nWxsPath
275
+ this._module.addDependency(new CommonJsVariableDependency(i18nWxsRequest))
276
+ // 避免该模块被concatenate导致注入的i18n没有最先执行
277
+ this._module.buildInfo.moduleConcatenationBailout = 'i18n'
278
+ }
243
279
 
244
- output += `global.i18nMethods = require(${loaderUtils.stringifyRequest(loaderContext, i18nWxsRequest)})\n`
280
+ // 为独立分包注入init module
281
+ if (independent && typeof independent === 'string') {
282
+ const independentLoader = normalize.lib('independent-loader.js')
283
+ const independentInitRequest = `!!${independentLoader}!${independent}`
284
+ this._module.addDependency(new CommonJsVariableDependency(independentInitRequest))
285
+ // 避免该模块被concatenate导致注入的independent init没有最先执行
286
+ this._module.buildInfo.moduleConcatenationBailout = 'independent init'
245
287
  }
288
+
246
289
  // 注入构造函数
247
290
  let ctor = 'App'
248
291
  if (ctorType === 'page') {
249
- // swan也默认使用Page构造器
250
- if (mpx.forceUsePageCtor || mode === 'ali' || mode === 'swan') {
292
+ if (mpx.forceUsePageCtor || mode === 'ali') {
251
293
  ctor = 'Page'
252
294
  } else {
253
295
  ctor = 'Component'
@@ -259,6 +301,7 @@ module.exports = function (content) {
259
301
  output += `global.currentCtorType = ${JSON.stringify(ctor.replace(/^./, (match) => {
260
302
  return match.toLowerCase()
261
303
  }))}\n`
304
+ output += `global.currentResourceType = ${JSON.stringify(ctorType)}\n`
262
305
 
263
306
  // template
264
307
  output += '/* template */\n'
@@ -266,6 +309,10 @@ module.exports = function (content) {
266
309
 
267
310
  if (template) {
268
311
  const extraOptions = {
312
+ ...template.src ? {
313
+ ...queryObj,
314
+ resourcePath
315
+ } : null,
269
316
  hasScoped,
270
317
  hasComment,
271
318
  isNative,
@@ -286,52 +333,50 @@ module.exports = function (content) {
286
333
  parts.styles.forEach((style, i) => {
287
334
  const scoped = style.scoped || autoScope
288
335
  const extraOptions = {
336
+ // style src会被特殊处理为全局复用样式,不添加resourcePath,添加isStatic及issuerFile
337
+ ...style.src ? {
338
+ ...queryObj,
339
+ isStatic: true,
340
+ issuerResource: addQuery(this.resource, { type: 'styles' }, true)
341
+ } : null,
289
342
  moduleId,
290
343
  scoped
291
344
  }
292
345
  // require style
293
- if (style.src) {
294
- // style src会被特殊处理为全局复用样式,不添加resourcePath,添加isStatic及issuerResource
295
- extraOptions.isStatic = true
296
- extraOptions.issuerFile = mpx.getExtractedFile(this.resource)
297
- }
298
346
  output += getRequire('styles', style, extraOptions, i) + '\n'
299
347
  })
300
- } else if (ctorType === 'app' && mode === 'ali') {
301
- output += getRequire('styles', {}) + '\n'
348
+ }
349
+
350
+ if (parts.styles.filter(style => !style.src).length === 0 && ctorType === 'app' && mode === 'ali') {
351
+ output += getRequire('styles', {}, {}, parts.styles.length) + '\n'
302
352
  }
303
353
 
304
354
  // json
305
355
  output += '/* json */\n'
306
356
  // 给予json默认值, 确保生成json request以自动补全json
307
357
  const json = parts.json || {}
308
- output += getRequire('json', json, json.src && { resourcePath }) + '\n'
358
+ output += getRequire('json', json, json.src && {
359
+ ...queryObj,
360
+ resourcePath
361
+ }) + '\n'
309
362
 
310
363
  // script
311
364
  output += '/* script */\n'
312
365
  let scriptSrcMode = srcMode
313
- const script = parts.script
366
+ // 给予script默认值, 确保生成js request以自动补全js
367
+ const script = parts.script || {}
314
368
  if (script) {
315
369
  scriptSrcMode = script.mode || scriptSrcMode
316
370
  if (scriptSrcMode) output += `global.currentSrcMode = ${JSON.stringify(scriptSrcMode)}\n`
317
- const extraOptions = {}
318
- if (script.src) extraOptions.resourcePath = resourcePath
319
- output += getRequire('script', script, extraOptions) + '\n'
320
- } else {
321
- switch (ctorType) {
322
- case 'app':
323
- output += 'import {createApp} from "@mpxjs/core"\n' +
324
- 'createApp({})\n'
325
- break
326
- case 'page':
327
- output += 'import {createPage} from "@mpxjs/core"\n' +
328
- 'createPage({})\n'
329
- break
330
- case 'component':
331
- output += 'import {createComponent} from "@mpxjs/core"\n' +
332
- 'createComponent({})\n'
371
+ // 传递ctorType以补全js内容
372
+ const extraOptions = {
373
+ ...script.src ? {
374
+ ...queryObj,
375
+ resourcePath
376
+ } : null,
377
+ ctorType
333
378
  }
334
- output += '\n'
379
+ output += getRequire('script', script, extraOptions) + '\n'
335
380
  }
336
381
  callback(null, output)
337
382
  }
@@ -3,10 +3,11 @@ const JSON5 = require('json5')
3
3
  const parseRequest = require('./utils/parse-request')
4
4
  const config = require('./config')
5
5
  const createHelpers = require('./helpers')
6
- const mpxJSON = require('./utils/mpx-json')
6
+ const getJSONContent = require('./utils/get-json-content')
7
7
  const async = require('async')
8
- const matchCondition = require('./utils/match-condition')
8
+ const { matchCondition } = require('./utils/match-condition')
9
9
  const fixUsingComponent = require('./utils/fix-using-component')
10
+ const { JSON_JS_EXT } = require('./utils/const')
10
11
 
11
12
  module.exports = function (content) {
12
13
  this.cacheable()
@@ -23,7 +24,6 @@ module.exports = function (content) {
23
24
  const moduleId = 'm' + mpx.pathHash(filePath)
24
25
  const { resourcePath, queryObj } = parseRequest(this.resource)
25
26
  const mode = mpx.mode
26
- const defs = mpx.defs
27
27
  const globalSrcMode = mpx.srcMode
28
28
  const localSrcMode = queryObj.mode
29
29
  const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
@@ -33,12 +33,10 @@ module.exports = function (content) {
33
33
  const resourceName = path.join(parsed.dir, parsed.name)
34
34
  const isApp = !(pagesMap[resourcePath] || componentsMap[resourcePath])
35
35
  const srcMode = localSrcMode || globalSrcMode
36
- const fs = this._compiler.inputFileSystem
37
36
  const typeExtMap = config[srcMode].typeExtMap
38
37
  const typeResourceMap = {}
39
38
  const autoScope = matchCondition(resourcePath, mpx.autoScopeRules)
40
39
 
41
- const EXT_MPX_JSON = '.json.js'
42
40
  const CSS_LANG_EXT_MAP = {
43
41
  less: '.less',
44
42
  stylus: '.styl',
@@ -46,40 +44,18 @@ module.exports = function (content) {
46
44
  scss: '.scss'
47
45
  }
48
46
 
49
- let useMPXJSON = false
47
+ let useJSONJS = false
50
48
  let cssLang = ''
51
49
  const hasScoped = (queryObj.scoped || autoScope) && mode === 'ali'
52
50
  const hasComment = false
53
51
  const isNative = true
54
52
 
55
- const tryEvalMPXJSON = (callback) => {
56
- const { rawResourcePath } = parseRequest(typeResourceMap['json'])
57
- const _src = rawResourcePath
58
- this.addDependency(_src)
59
- fs.readFile(_src, (err, raw) => {
60
- if (err) {
61
- callback(err)
62
- } else {
63
- try {
64
- const source = raw.toString('utf-8')
65
- const text = mpxJSON.compileMPXJSONText({ source, defs, filePath: _src })
66
- callback(null, text)
67
- } catch (e) {
68
- callback(e)
69
- }
70
- }
71
- })
72
- }
73
-
74
53
  const checkFileExists = (extName, callback) => {
75
- this.resolve(parsed.dir, resourceName + extName, (err, result) => {
76
- err = null
77
- callback(err, result)
78
- })
54
+ this.resolve(parsed.dir, resourceName + extName, callback)
79
55
  }
80
56
 
81
57
  function checkCSSLangFiles (callback) {
82
- const langs = mpx.nativeOptions.cssLangs || ['less', 'stylus', 'scss', 'sass']
58
+ const langs = mpx.nativeConfig.cssLangs || ['less', 'stylus', 'scss', 'sass']
83
59
  const results = []
84
60
  async.eachOf(langs, function (lang, i, callback) {
85
61
  if (!CSS_LANG_EXT_MAP[lang]) {
@@ -89,7 +65,7 @@ module.exports = function (content) {
89
65
  if (!err && result) {
90
66
  results[i] = result
91
67
  }
92
- callback(err)
68
+ callback()
93
69
  })
94
70
  }, function (err) {
95
71
  for (let i = 0; i < langs.length; i++) {
@@ -103,14 +79,13 @@ module.exports = function (content) {
103
79
  })
104
80
  }
105
81
 
106
- function checkMPXJSONFile (callback) {
107
- // checkFileExists(EXT_MPX_JSON, (err, result) => {
108
- checkFileExists(EXT_MPX_JSON, (err, result) => {
82
+ function checkJSONJSFile (callback) {
83
+ checkFileExists(JSON_JS_EXT, (err, result) => {
109
84
  if (!err && result) {
110
85
  typeResourceMap.json = result
111
- useMPXJSON = true
86
+ useJSONJS = true
112
87
  }
113
- callback(err)
88
+ callback()
114
89
  })
115
90
  }
116
91
 
@@ -119,55 +94,42 @@ module.exports = function (content) {
119
94
  (callback) => {
120
95
  async.parallel([
121
96
  checkCSSLangFiles,
122
- checkMPXJSONFile
97
+ checkJSONJSFile
123
98
  ], (err) => {
124
99
  callback(err)
125
100
  })
126
101
  },
127
102
  (callback) => {
128
103
  async.forEachOf(typeExtMap, (ext, key, callback) => {
129
- // 检测到mpxJson或cssLang时跳过对应类型文件检测
130
- if ((key === 'json' && useMPXJSON) || (key === 'styles' && cssLang)) {
104
+ // 检测到jsonjs或cssLang时跳过对应类型文件检测
105
+ if (typeResourceMap[key]) {
131
106
  return callback()
132
107
  }
133
108
  checkFileExists(ext, (err, result) => {
134
109
  if (!err && result) {
135
110
  typeResourceMap[key] = result
136
111
  }
137
- callback(err)
112
+ callback()
138
113
  })
139
114
  }, callback)
140
115
  },
141
116
  (callback) => {
142
- // 对原生写法增强json写法,可以用js来写json,尝试找.json.js文件,找不到用回json的内容
143
- if (useMPXJSON) {
144
- tryEvalMPXJSON(callback)
145
- } else {
146
- if (typeResourceMap['json']) {
147
- // eslint-disable-next-line handle-callback-err
148
- const { rawResourcePath } = parseRequest(typeResourceMap['json'])
149
- fs.readFile(rawResourcePath, (err, raw) => {
150
- if (err) {
151
- callback(err)
152
- } else {
153
- callback(null, raw.toString('utf-8'))
154
- }
155
- })
156
- } else {
157
- callback(null, '{}')
158
- }
159
- }
117
+ getJSONContent({
118
+ src: typeResourceMap.json,
119
+ useJSONJS
120
+ }, this, callback)
160
121
  }, (content, callback) => {
161
- let usingComponents = [].concat(Object.keys(mpx.usingComponents))
122
+ let json
162
123
  try {
163
- let ret = JSON5.parse(content)
164
- if (ret.usingComponents) {
165
- fixUsingComponent(ret.usingComponents, mode)
166
- usingComponents = usingComponents.concat(Object.keys(ret.usingComponents))
167
- }
124
+ json = JSON5.parse(content)
168
125
  } catch (e) {
126
+ return callback(e)
127
+ }
128
+ let usingComponents = Object.keys(mpx.usingComponents)
129
+ if (json.usingComponents) {
130
+ fixUsingComponent(json.usingComponents, mode)
131
+ usingComponents = usingComponents.concat(Object.keys(json.usingComponents))
169
132
  }
170
-
171
133
  const {
172
134
  getRequire
173
135
  } = createHelpers(loaderContext)
@@ -175,11 +137,10 @@ module.exports = function (content) {
175
137
  const getRequireByType = (type) => {
176
138
  const src = typeResourceMap[type]
177
139
  const part = { src }
178
- const extraOptions = Object.assign({}, queryObj, {
140
+ const extraOptions = {
141
+ ...queryObj,
179
142
  resourcePath
180
- })
181
-
182
- if (type !== 'script') this.addDependency(src)
143
+ }
183
144
 
184
145
  switch (type) {
185
146
  case 'template':
@@ -199,6 +160,9 @@ module.exports = function (content) {
199
160
  scoped: hasScoped
200
161
  })
201
162
  break
163
+ case 'json':
164
+ if (useJSONJS) part.useJSONJS = true
165
+ break
202
166
  }
203
167
  return getRequire(type, part, extraOptions)
204
168
  }
@@ -211,7 +175,9 @@ module.exports = function (content) {
211
175
 
212
176
  // 注入构造函数
213
177
  let ctor = 'App'
178
+ let ctorType = 'app'
214
179
  if (pagesMap[resourcePath]) {
180
+ ctorType = 'page'
215
181
  if (mpx.forceUsePageCtor || mode === 'ali' || mode === 'swan') {
216
182
  ctor = 'Page'
217
183
  } else {
@@ -219,11 +185,13 @@ module.exports = function (content) {
219
185
  }
220
186
  } else if (componentsMap[resourcePath]) {
221
187
  ctor = 'Component'
188
+ ctorType = 'component'
222
189
  }
223
190
  output += `global.currentCtor = ${ctor}\n`
224
191
  output += `global.currentCtorType = ${JSON.stringify(ctor.replace(/^./, (match) => {
225
192
  return match.toLowerCase()
226
193
  }))}\n`
194
+ output += `global.currentResourceType = ${JSON.stringify(ctorType)}\n`
227
195
 
228
196
  if (srcMode) {
229
197
  output += `global.currentSrcMode = ${JSON.stringify(srcMode)}\n`
package/lib/parser.js CHANGED
@@ -6,7 +6,7 @@ const SourceMapGenerator = require('source-map').SourceMapGenerator
6
6
  const splitRE = /\r?\n/g
7
7
  const emptyRE = /^(?:\/\/)?\s*$/
8
8
 
9
- module.exports = (content, { filePath, needMap, mode, defs, env }) => {
9
+ module.exports = (content, { filePath, needMap, mode, env }) => {
10
10
  // 缓存需要mode隔离,不同mode经过区块条件编译parseComponent得到的内容并不一致
11
11
  const cacheKey = hash(filePath + content + mode + env)
12
12
 
@@ -14,7 +14,6 @@ module.exports = (content, { filePath, needMap, mode, defs, env }) => {
14
14
  if (output) return JSON.parse(output)
15
15
  output = compiler.parseComponent(content, {
16
16
  mode,
17
- defs,
18
17
  filePath,
19
18
  pad: 'line',
20
19
  env
@@ -0,0 +1,35 @@
1
+ const { matchCondition } = require('../utils/match-condition')
2
+ const { parseQuery } = require('loader-utils')
3
+
4
+ class MpxPartialCompilePlugin {
5
+ constructor (condition) {
6
+ this.condition = condition
7
+ }
8
+
9
+ isResolvingPage (obj) {
10
+ // valid query should start with '?'
11
+ const query = obj.query || '?'
12
+ return parseQuery(query).isPage
13
+ }
14
+
15
+ apply (compiler) {
16
+ compiler.resolverFactory.hooks.resolver.intercept({
17
+ factory: (type, hook) => {
18
+ hook.tap('MpxPartialCompilePlugin', (resolver) => {
19
+ resolver.hooks.result.tapAsync({
20
+ name: 'MpxPartialCompilePlugin',
21
+ stage: -100
22
+ }, (obj, resolverContext, callback) => {
23
+ if (this.isResolvingPage(obj) && !matchCondition(obj.path, this.condition)) {
24
+ obj.path = false
25
+ }
26
+ callback(null, obj)
27
+ })
28
+ })
29
+ return hook
30
+ }
31
+ })
32
+ }
33
+ }
34
+
35
+ module.exports = MpxPartialCompilePlugin