@mpxjs/webpack-plugin 2.7.0-beta.1 → 2.7.0-beta.13

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 (51) hide show
  1. package/lib/dependencies/AppEntryDependency.js +2 -0
  2. package/lib/dependencies/CommonJsVariableDependency.js +9 -5
  3. package/lib/dependencies/DynamicEntryDependency.js +8 -3
  4. package/lib/dependencies/FlagPluginDependency.js +1 -0
  5. package/lib/dependencies/RecordIndependentDependency.js +41 -0
  6. package/lib/dependencies/{RecordStaticResourceDependency.js → RecordResourceMapDependency.js} +12 -7
  7. package/lib/dependencies/RemoveEntryDependency.js +40 -0
  8. package/lib/dependencies/ResolveDependency.js +8 -7
  9. package/lib/extractor.js +7 -4
  10. package/lib/file-loader.js +2 -2
  11. package/lib/helpers.js +1 -0
  12. package/lib/index.js +218 -146
  13. package/lib/json-compiler/helper.js +21 -25
  14. package/lib/json-compiler/index.js +70 -54
  15. package/lib/json-compiler/plugin.js +21 -5
  16. package/lib/loader.js +59 -77
  17. package/lib/native-loader.js +28 -65
  18. package/lib/parser.js +1 -2
  19. package/lib/platform/json/wx/index.js +7 -2
  20. package/lib/platform/template/wx/component-config/button.js +3 -3
  21. package/lib/platform/template/wx/component-config/navigator.js +1 -1
  22. package/lib/record-loader.js +2 -2
  23. package/lib/resolver/AddEnvPlugin.js +3 -2
  24. package/lib/resolver/AddModePlugin.js +3 -2
  25. package/lib/runtime/base.styl +5 -0
  26. package/lib/runtime/components/web/getInnerListeners.js +51 -45
  27. package/lib/runtime/components/web/mpx-keep-alive.vue +4 -1
  28. package/lib/runtime/components/web/mpx-tab-bar-container.vue +2 -2
  29. package/lib/runtime/optionProcessor.js +5 -20
  30. package/lib/runtime/stringify.wxs +3 -3
  31. package/lib/selector.js +23 -5
  32. package/lib/style-compiler/index.js +8 -10
  33. package/lib/template-compiler/bind-this.js +4 -4
  34. package/lib/template-compiler/compiler.js +109 -46
  35. package/lib/template-compiler/index.js +3 -6
  36. package/lib/template-compiler/trans-dynamic-class-expr.js +3 -3
  37. package/lib/utils/const.js +5 -1
  38. package/lib/utils/eval-json-js.js +31 -0
  39. package/lib/utils/get-json-content.js +41 -0
  40. package/lib/utils/resolve.js +13 -0
  41. package/lib/web/processJSON.js +113 -142
  42. package/lib/web/processScript.js +30 -30
  43. package/lib/web/processTemplate.js +56 -40
  44. package/lib/wxs/i18n-loader.js +1 -3
  45. package/lib/wxs/loader.js +24 -27
  46. package/lib/wxs/pre-loader.js +7 -8
  47. package/lib/wxss/processCss.js +44 -44
  48. package/package.json +8 -8
  49. package/lib/built-in-loader.js +0 -49
  50. package/lib/utils/get-main-compilation.js +0 -6
  51. package/lib/utils/read-json-for-src.js +0 -34
@@ -1,4 +1,5 @@
1
1
  import { isEmptyObject } from './util'
2
+ const isTouchDevice = 'ontouchstart' in document.documentElement
2
3
 
3
4
  function processModel (listeners, context) {
4
5
  // 该函数只有wx:model的情况下才调用,而且默认e.detail.value有值
@@ -54,58 +55,63 @@ function processTap (listeners, context) {
54
55
  })
55
56
  if (isEmptyObject(listenerMap)) return
56
57
  context.__mpxTapInfo = context.__mpxTapInfo || {}
57
- let events = {
58
- touchstart (e) {
59
- context.__mpxTapInfo.detail = {
60
- x: e.changedTouches[0].pageX,
61
- y: e.changedTouches[0].pageY
62
- }
63
- context.__mpxTapInfo.startTimer = null
64
- context.__mpxTapInfo.needTap = true
65
- context.__mpxTapInfo.hadTouch = true
66
- if (listenerMap.longpress || listenerMap.longtap) {
67
- context.__mpxTapInfo.startTimer = setTimeout(() => {
58
+ let events
59
+ if (isTouchDevice) {
60
+ events = {
61
+ touchstart (e) {
62
+ context.__mpxTapInfo.detail = {
63
+ x: e.changedTouches[0].pageX,
64
+ y: e.changedTouches[0].pageY
65
+ }
66
+ context.__mpxTapInfo.startTimer = null
67
+ context.__mpxTapInfo.needTap = true
68
+ if (listenerMap.longpress || listenerMap.longtap) {
69
+ context.__mpxTapInfo.startTimer = setTimeout(() => {
70
+ context.__mpxTapInfo.needTap = false
71
+ if (listenerMap.longpress) {
72
+ const re = inheritEvent('longpress', e, context.__mpxTapInfo.detail)
73
+ context.$emit('longpress', re)
74
+ }
75
+ if (listenerMap.longtap) {
76
+ const re = inheritEvent('longtap', e, context.__mpxTapInfo.detail)
77
+ context.$emit('longtap', re)
78
+ }
79
+ }, 350)
80
+ }
81
+ },
82
+ touchmove (e) {
83
+ const tapDetailInfo = context.__mpxTapInfo.detail || {}
84
+ const currentPageX = e.changedTouches[0].pageX
85
+ const currentPageY = e.changedTouches[0].pageY
86
+ if (Math.abs(currentPageX - tapDetailInfo.x) > 1 || Math.abs(currentPageY - tapDetailInfo.y) > 1) {
68
87
  context.__mpxTapInfo.needTap = false
69
- if (listenerMap.longpress) {
70
- const re = inheritEvent('longpress', e, context.__mpxTapInfo.detail)
71
- context.$emit('longpress', re)
72
- }
73
- if (listenerMap.longtap) {
74
- const re = inheritEvent('longtap', e, context.__mpxTapInfo.detail)
75
- context.$emit('longtap', re)
76
- }
77
- }, 350)
78
- }
79
- },
80
- touchmove (e) {
81
- const tapDetailInfo = context.__mpxTapInfo.detail || {}
82
- const currentPageX = e.changedTouches[0].pageX
83
- const currentPageY = e.changedTouches[0].pageY
84
- if (Math.abs(currentPageX - tapDetailInfo.x) > 1 || Math.abs(currentPageY - tapDetailInfo.y) > 1) {
85
- context.__mpxTapInfo.needTap = false
88
+ context.__mpxTapInfo.startTimer && clearTimeout(context.__mpxTapInfo.startTimer)
89
+ context.__mpxTapInfo.startTimer = null
90
+ }
91
+ },
92
+ touchend (e) {
86
93
  context.__mpxTapInfo.startTimer && clearTimeout(context.__mpxTapInfo.startTimer)
87
- context.__mpxTapInfo.startTimer = null
88
- }
89
- },
90
- touchend (e) {
91
- context.__mpxTapInfo.startTimer && clearTimeout(context.__mpxTapInfo.startTimer)
92
- if (listenerMap.tap && context.__mpxTapInfo.needTap) {
93
- const re = inheritEvent('tap', e, context.__mpxTapInfo.detail)
94
- context.$emit('tap', re)
94
+ if (listenerMap.tap && context.__mpxTapInfo.needTap) {
95
+ const re = inheritEvent('tap', e, context.__mpxTapInfo.detail)
96
+ context.$emit('tap', re)
97
+ }
95
98
  }
96
- },
97
- click (e) {
98
- if (listenerMap.tap && !context.__mpxTapInfo.hadTouch) {
99
- context.__mpxTapInfo.detail = {
100
- x: e.pageX,
101
- y: e.pageY
99
+ }
100
+ } else {
101
+ events = {
102
+ click (e) {
103
+ if (listenerMap.tap) {
104
+ context.__mpxTapInfo.detail = {
105
+ x: e.pageX,
106
+ y: e.pageY
107
+ }
108
+ const re = inheritEvent('tap', e, context.__mpxTapInfo.detail)
109
+ context.$emit('tap', re)
102
110
  }
103
- const re = inheritEvent('tap', e, context.__mpxTapInfo.detail)
104
- context.$emit('tap', re)
105
111
  }
106
- context.__mpxTapInfo.hadTouch = false
107
112
  }
108
113
  }
114
+
109
115
  mergeListeners(listeners, events, {
110
116
  force: true
111
117
  })
@@ -1,5 +1,6 @@
1
1
  <script>
2
2
  import { inBrowser } from '../../../utils/env'
3
+
3
4
  function isDef (v) {
4
5
  return v !== undefined && v !== null
5
6
  }
@@ -30,7 +31,7 @@
30
31
 
31
32
  function getVnodeKey (vnode) {
32
33
  if (vnode && vnode.componentOptions) {
33
- return vnode.key || vnode.componentOptions.Ctor.cid + (vnode.componentOptions.tag ? ('::' + (vnode.componentOptions.tag)) : '')
34
+ return vnode.componentOptions.Ctor.cid + (vnode.componentOptions.tag ? ('::' + (vnode.componentOptions.tag)) : '')
34
35
  }
35
36
  }
36
37
 
@@ -73,6 +74,8 @@
73
74
  const current = stack[i - 1]
74
75
  if (current.vnode && current.vnodeKey === vnodeKey && current.vnode.componentInstance) {
75
76
  vnode.componentInstance = current.vnode.componentInstance
77
+ // 避免组件实例复用但是vnode.key不一致带来的bad case
78
+ vnode.key = current.vnode.key
76
79
  break
77
80
  }
78
81
  }
@@ -15,7 +15,7 @@
15
15
  'mpx-tab-bar': tabBarPagesMap['mpx-tab-bar']
16
16
  }
17
17
  tabBar.list.forEach(({ pagePath }) => {
18
- const name = pagePath.replace('/', '-')
18
+ const name = pagePath.replace(/\//g, '-')
19
19
  const page = tabBarPagesMap[pagePath]
20
20
  if (page) {
21
21
  components[name] = page
@@ -39,7 +39,7 @@
39
39
  currentComponent () {
40
40
  const index = this.currentIndex
41
41
  const tabItem = tabBar.list[index]
42
- return tabItem.pagePath.replace('/', '-')
42
+ return tabItem.pagePath.replace(/\//g, '-')
43
43
  }
44
44
  },
45
45
  watch: {
@@ -4,7 +4,7 @@ export default function processOption (
4
4
  option,
5
5
  ctorType,
6
6
  firstPage,
7
- componentId,
7
+ outputPath,
8
8
  pageConfig,
9
9
  pagesMap,
10
10
  componentsMap,
@@ -25,23 +25,6 @@ export default function processOption (
25
25
  }
26
26
  }
27
27
 
28
- // 注册v-ex-classes自定义指令处理externalClasses
29
- Vue.directive('ex-classes', (el, binding, vnode) => {
30
- const context = vnode.context
31
- if (context) {
32
- const externalClasses = context.$options.externalClasses || []
33
- const classList = el.classList
34
- binding.value.forEach((className) => {
35
- const actualExternalClassNames = context.$attrs[className]
36
- if (externalClasses.indexOf(className) !== -1 && actualExternalClassNames) {
37
- classList.remove(className)
38
- actualExternalClassNames.split(/\s+/).forEach((actualExternalClassName) => {
39
- if (actualExternalClassName) classList.add(actualExternalClassName)
40
- })
41
- }
42
- })
43
- }
44
- })
45
28
  Vue.directive('animation', (el, binding) => {
46
29
  const newActions = binding && binding.value && binding.value.actions
47
30
  if (el.actions === newActions) {
@@ -121,7 +104,9 @@ export default function processOption (
121
104
  redirect: '/' + firstPage
122
105
  })
123
106
  }
107
+ const webRouteConfig = global.__mpx.config.webRouteConfig
124
108
  global.__mpxRouter = option.router = new VueRouter({
109
+ ...webRouteConfig,
125
110
  routes: routes
126
111
  })
127
112
  global.__mpxRouter.stack = []
@@ -354,8 +339,8 @@ registered in parent context!`)
354
339
  option.mixins = [mixin]
355
340
  }
356
341
 
357
- if (componentId) {
358
- option.componentPath = '/' + componentId
342
+ if (outputPath) {
343
+ option.componentPath = '/' + outputPath
359
344
  }
360
345
 
361
346
  return option
@@ -93,7 +93,7 @@ function isDef (v) {
93
93
  return v !== undefined && v !== null
94
94
  }
95
95
 
96
- function stringifyClass (value) {
96
+ function stringifyDynamicClass (value) {
97
97
  if (!value) return ''
98
98
  if (likeArray(value)) {
99
99
  return stringifyArray(value)
@@ -111,7 +111,7 @@ function stringifyArray (value) {
111
111
  var res = ''
112
112
  var stringified
113
113
  for (var i = 0; i < value.length; i++) {
114
- if (isDef(stringified = stringifyClass(value[i])) && stringified !== '') {
114
+ if (isDef(stringified = stringifyDynamicClass(value[i])) && stringified !== '') {
115
115
  if (res) res += ' '
116
116
  res += stringified
117
117
  }
@@ -207,7 +207,7 @@ module.exports = {
207
207
  if (typeof staticClass !== 'string') {
208
208
  return console.log('Template attr class must be a string!')
209
209
  }
210
- return concat(staticClass, stringifyClass(dynamicClass))
210
+ return concat(staticClass, stringifyDynamicClass(dynamicClass))
211
211
  },
212
212
  stringifyStyle: function (staticStyle, dynamicStyle) {
213
213
  var normalizedDynamicStyle = normalizeDynamicStyle(dynamicStyle)
package/lib/selector.js CHANGED
@@ -9,24 +9,42 @@ module.exports = function (content) {
9
9
  return content
10
10
  }
11
11
  const { queryObj } = parseRequest(this.resource)
12
+ const ctorType = queryObj.ctorType
12
13
  const type = queryObj.type
13
14
  const index = queryObj.index || 0
14
15
  const mode = mpx.mode
15
16
  const env = mpx.env
16
- const defs = mpx.defs
17
17
  const filePath = this.resourcePath
18
18
  const parts = parseComponent(content, {
19
19
  filePath,
20
20
  needMap: this.sourceMap,
21
21
  mode,
22
- defs,
23
22
  env
24
23
  })
25
- let part = parts[type] || {}
24
+ let part = parts[type]
26
25
  if (Array.isArray(part)) {
27
- part = part[index] || {
28
- content: ''
26
+ part = part[index]
27
+ }
28
+ if (!part) {
29
+ let content = ''
30
+ // 补全js内容
31
+ if (type === 'script') {
32
+ switch (ctorType) {
33
+ case 'app':
34
+ content += 'import {createApp} from "@mpxjs/core"\n' +
35
+ 'createApp({})\n'
36
+ break
37
+ case 'page':
38
+ content += 'import {createPage} from "@mpxjs/core"\n' +
39
+ 'createPage({})\n'
40
+ break
41
+ case 'component':
42
+ content += 'import {createComponent} from "@mpxjs/core"\n' +
43
+ 'createComponent({})\n'
44
+ }
29
45
  }
46
+ part = { content }
30
47
  }
48
+ part = part || { content: '' }
31
49
  this.callback(null, part.content, part.map)
32
50
  }
@@ -1,5 +1,6 @@
1
1
  const postcss = require('postcss')
2
2
  const loadPostcssConfig = require('./load-postcss-config')
3
+ const { MPX_ROOT_VIEW, MPX_APP_MODULE_ID } = require('../utils/const')
3
4
  const trim = require('./plugins/trim')
4
5
  const rpx = require('./plugins/rpx')
5
6
  const vw = require('./plugins/vw')
@@ -15,12 +16,10 @@ module.exports = function (css, map) {
15
16
  const { resourcePath, queryObj } = parseRequest(this.resource)
16
17
  const id = queryObj.moduleId || queryObj.mid
17
18
  const mpx = this.getMpx()
19
+ const appInfo = mpx.appInfo
18
20
  const defs = mpx.defs
19
21
  const mode = mpx.mode
20
- const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
21
- const componentsMap = mpx.componentsMap[packageName]
22
- const pagesMap = mpx.pagesMap
23
- const isApp = !(pagesMap[resourcePath] || componentsMap[resourcePath])
22
+ const isApp = resourcePath === appInfo.resourcePath
24
23
  const transRpxRulesRaw = mpx.transRpxRules
25
24
  const transRpxRules = transRpxRulesRaw ? (Array.isArray(transRpxRulesRaw) ? transRpxRulesRaw : [transRpxRulesRaw]) : []
26
25
 
@@ -39,15 +38,14 @@ module.exports = function (css, map) {
39
38
  },
40
39
  config.options
41
40
  )
42
- // ali环境处理host选择器
41
+ // ali平台下处理scoped和host选择器
43
42
  if (mode === 'ali') {
43
+ if (queryObj.scoped) {
44
+ plugins.push(scopeId({ id }))
45
+ }
44
46
  plugins.push(transSpecial({ id }))
45
47
  }
46
48
 
47
- if (queryObj.scoped) {
48
- plugins.push(scopeId({ id }))
49
- }
50
-
51
49
  plugins.push(pluginCondStrip({
52
50
  defs
53
51
  }))
@@ -85,7 +83,7 @@ module.exports = function (css, map) {
85
83
  .then(result => {
86
84
  // ali环境添加全局样式抹平root差异
87
85
  if (mode === 'ali' && isApp) {
88
- result.css += '\n.mpx-root-view { display: inline; line-height: normal; }\n'
86
+ result.css += `\n.${MPX_ROOT_VIEW} { display: initial }\n.${MPX_APP_MODULE_ID} { line-height: normal }`
89
87
  }
90
88
  if (result.messages) {
91
89
  result.messages.forEach(({ type, file }) => {
@@ -1,7 +1,7 @@
1
- const babylon = require('babylon')
2
- const traverse = require('babel-traverse').default
3
- const t = require('babel-types')
4
- const generate = require('babel-generator').default
1
+ const babylon = require('@babel/parser')
2
+ const traverse = require('@babel/traverse').default
3
+ const t = require('@babel/types')
4
+ const generate = require('@babel/generator').default
5
5
 
6
6
  let names = 'Infinity,undefined,NaN,isFinite,isNaN,' +
7
7
  'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
@@ -1,10 +1,10 @@
1
1
  const JSON5 = require('json5')
2
2
  const he = require('he')
3
3
  const config = require('../config')
4
+ const { MPX_ROOT_VIEW, MPX_APP_MODULE_ID } = require('../utils/const')
4
5
  const normalize = require('../utils/normalize')
5
6
  const isValidIdentifierStr = require('../utils/is-valid-identifier-str')
6
7
  const isEmptyObject = require('../utils/is-empty-object')
7
- const mpxJSON = require('../utils/mpx-json')
8
8
  const getRulesRunner = require('../platform/index')
9
9
  const addQuery = require('../utils/add-query')
10
10
  const transDynamicClassExpr = require('./trans-dynamic-class-expr')
@@ -496,7 +496,6 @@ function parseHTML (html, options) {
496
496
 
497
497
  function parseComponent (content, options) {
498
498
  mode = options.mode || 'wx'
499
- defs = options.defs || {}
500
499
  env = options.env
501
500
  filePath = options.filePath
502
501
 
@@ -548,6 +547,9 @@ function parseComponent (content, options) {
548
547
  if (/^application\/json/.test(currentBlock.type) || currentBlock.name === 'json') {
549
548
  tag = 'json'
550
549
  }
550
+ if (currentBlock.name === 'json') {
551
+ currentBlock.useJSONJS = true
552
+ }
551
553
  }
552
554
  if (currentBlock.mode && currentBlock.env) {
553
555
  if (currentBlock.mode === mode && currentBlock.env === env) {
@@ -606,20 +608,15 @@ function parseComponent (content, options) {
606
608
  }
607
609
  }
608
610
 
609
- function end (tag, start, end) {
611
+ function end (tag, start) {
610
612
  if (depth === 1 && currentBlock) {
611
613
  currentBlock.end = start
612
614
  let text = content.slice(currentBlock.start, currentBlock.end)
613
615
  // pad content so that linters and pre-processors can output correct
614
616
  // line numbers in errors and warnings
615
- if (currentBlock.tag !== 'template' && options.pad) {
617
+ if (options.pad) {
616
618
  text = padContent(currentBlock, options.pad) + text
617
619
  }
618
-
619
- // 对于<script name="json">的标签,传参调用函数,其返回结果作为json的内容
620
- if (currentBlock.tag === 'script' && !/^application\/json/.test(currentBlock.type) && currentBlock.name === 'json') {
621
- text = mpxJSON.compileMPXJSONText({ source: text, defs, filePath })
622
- }
623
620
  currentBlock.content = text
624
621
  currentBlock = null
625
622
  }
@@ -1714,31 +1711,71 @@ function processAliExternalClassesHack (el, options) {
1714
1711
  }
1715
1712
  }
1716
1713
 
1714
+ // externalClasses只能模拟静态传递
1717
1715
  function processWebExternalClassesHack (el, options) {
1718
- // todo 处理scoped的情况, 处理组件多层传递externalClass的情况,通过externalClass属性传递实际类名及scopeId信息,可以使用特殊的类名形式代表scopeId,如#idstring
1719
- let staticClass = el.attrsMap['class']
1720
- let dynamicClass = el.attrsMap[':class']
1721
- if (staticClass || dynamicClass) {
1722
- const externalClasses = []
1716
+ const staticClass = getAndRemoveAttr(el, 'class').val
1717
+ if (staticClass) {
1718
+ const classNames = staticClass.split(/\s+/)
1719
+ const replacements = []
1723
1720
  options.externalClasses.forEach((className) => {
1724
- const reg = new RegExp('\\b' + className + '\\b')
1725
- if (reg.test(staticClass) || reg.test(dynamicClass)) {
1726
- externalClasses.push(className)
1721
+ const index = classNames.indexOf(className)
1722
+ if (index > -1) {
1723
+ replacements.push(`$attrs[${JSON.stringify(className)}]`)
1724
+ classNames.splice(index, 1)
1727
1725
  }
1728
1726
  })
1729
- if (externalClasses.length) {
1727
+
1728
+ if (classNames.length) {
1730
1729
  addAttrs(el, [{
1731
- name: 'v-ex-classes',
1732
- value: JSON.stringify(externalClasses)
1730
+ name: 'class',
1731
+ value: classNames.join(' ')
1732
+ }])
1733
+ }
1734
+
1735
+ if (replacements.length) {
1736
+ const dynamicClass = getAndRemoveAttr(el, ':class').val
1737
+ if (dynamicClass) replacements.push(dynamicClass)
1738
+
1739
+ addAttrs(el, [{
1740
+ name: ':class',
1741
+ value: `[${replacements.join(',')}]`
1733
1742
  }])
1734
1743
  }
1735
1744
  }
1745
+
1746
+ // 处理externalClasses多层透传
1747
+ const isComponent = isComponentNode(el, options)
1748
+ if (isComponent) {
1749
+ options.externalClasses.forEach((classLikeAttrName) => {
1750
+ let classLikeAttrValue = getAndRemoveAttr(el, classLikeAttrName).val
1751
+ if (classLikeAttrValue) {
1752
+ const classNames = classLikeAttrValue.split(/\s+/)
1753
+ const replacements = []
1754
+ options.externalClasses.forEach((className) => {
1755
+ const index = classNames.indexOf(className)
1756
+ if (index > -1) {
1757
+ replacements.push(`$attrs[${JSON.stringify(className)}]`)
1758
+ classNames.splice(index, 1)
1759
+ }
1760
+ })
1761
+
1762
+ if (classNames.length) {
1763
+ replacements.unshift(JSON.stringify(classNames.join(' ')))
1764
+ }
1765
+
1766
+ addAttrs(el, [{
1767
+ name: ':' + classLikeAttrName,
1768
+ value: `[${replacements.join(',')}].join(' ')`
1769
+ }])
1770
+ }
1771
+ })
1772
+ }
1736
1773
  }
1737
1774
 
1738
1775
  function processScoped (el, options) {
1739
1776
  if (options.hasScoped && isRealNode(el)) {
1740
1777
  const moduleId = options.moduleId
1741
- const rootModuleId = options.isComponent ? '' : 'mpx-app-scope' // 处理app全局样式对页面的影响
1778
+ const rootModuleId = options.isComponent ? '' : MPX_APP_MODULE_ID // 处理app全局样式对页面的影响
1742
1779
  const staticClass = getAndRemoveAttr(el, 'class').val
1743
1780
  addAttrs(el, [{
1744
1781
  name: 'class',
@@ -1761,17 +1798,33 @@ function processBuiltInComponents (el, meta) {
1761
1798
  }
1762
1799
  }
1763
1800
 
1764
- function processAliStyleClassHack (el, options) {
1765
- if (!isComponentNode(el, options)) return
1801
+ function processAliStyleClassHack (el, options, root) {
1802
+ let processor
1803
+ // 处理组件标签
1804
+ if (isComponentNode(el, options)) processor = ({ value, typeName }) => [typeName, value]
1805
+ // 处理组件根节点
1806
+ if (options.isComponent && el === root && isRealNode(el)) {
1807
+ processor = ({ name, value, typeName }) => {
1808
+ let sep = name === 'style' ? ';' : ' '
1809
+ value = value ? `{{${typeName}||''}}${sep}${value}` : `{{${typeName}||''}}`
1810
+ return [name, value]
1811
+ }
1812
+ }
1813
+ // 非上述两种不处理
1814
+ if (!processor) return
1815
+ // 处理style、class
1766
1816
  ['style', 'class'].forEach((type) => {
1767
1817
  let exp = getAndRemoveAttr(el, type).val
1768
- let typeName = 'mpx' + type.replace(/^./, (matched) => {
1769
- return matched.toUpperCase()
1818
+ let typeName = 'mpx' + type.replace(/^./, (matched) => matched.toUpperCase())
1819
+ let [newName, newValue] = processor({
1820
+ name: type,
1821
+ value: exp,
1822
+ typeName
1770
1823
  })
1771
- if (exp !== undefined) {
1824
+ if (newValue !== undefined) {
1772
1825
  addAttrs(el, [{
1773
- name: typeName,
1774
- value: exp
1826
+ name: newName,
1827
+ value: newValue
1775
1828
  }])
1776
1829
  }
1777
1830
  })
@@ -1779,21 +1832,24 @@ function processAliStyleClassHack (el, options) {
1779
1832
 
1780
1833
  // 有virtualHost情况wx组件注入virtualHost。无virtualHost阿里组件注入root-view。其他跳过。
1781
1834
  function getVirtualHostRoot (options, meta) {
1782
- if (mode === 'wx' && options.hasVirtualHost && options.isComponent) {
1783
- !meta.options && (meta.options = {})
1784
- meta.options.virtualHost = true
1785
- }
1786
- if (mode === 'ali' && !options.hasVirtualHost && options.isComponent) {
1787
- return createASTElement('view', [
1788
- {
1789
- name: 'class',
1790
- value: `mpx-root-view host-${options.moduleId} ${options.hasScoped ? options.moduleId : ''} {{mpxClass||''}}`
1791
- },
1792
- {
1793
- name: 'style',
1794
- value: `{{mpxStyle||''}}`
1795
- }
1796
- ])
1835
+ if (options.isComponent) {
1836
+ // 处理组件时
1837
+ if (mode === 'wx' && options.hasVirtualHost) {
1838
+ // wx组件注入virtualHost配置
1839
+ !meta.options && (meta.options = {})
1840
+ meta.options.virtualHost = true
1841
+ }
1842
+ if (mode === 'ali' && !options.hasVirtualHost) {
1843
+ // ali组件根节点实体化
1844
+ let rootView = createASTElement('view', [
1845
+ {
1846
+ name: 'class',
1847
+ value: `${MPX_ROOT_VIEW} host-${options.moduleId}`
1848
+ }
1849
+ ])
1850
+ processElement(rootView, rootView, options, meta)
1851
+ return rootView
1852
+ }
1797
1853
  }
1798
1854
  return getTempNode()
1799
1855
  }
@@ -1801,7 +1857,10 @@ function getVirtualHostRoot (options, meta) {
1801
1857
  function processShow (el, options, root) {
1802
1858
  let show = getAndRemoveAttr(el, config[mode].directive.show).val
1803
1859
  if (mode === 'swan') show = wrapMustache(show)
1804
- if (options.isComponent && el.parent === root && isRealNode(el)) {
1860
+ let processFlag = el.parent === root
1861
+ // 当ali且未开启virtualHost时,mpxShow打到根节点上
1862
+ if (mode === 'ali' && !options.hasVirtualHost) processFlag = el === root
1863
+ if (options.isComponent && processFlag && isRealNode(el)) {
1805
1864
  if (show !== undefined) {
1806
1865
  show = `{{${parseMustache(show).result}&&mpxShow}}`
1807
1866
  } else {
@@ -1980,7 +2039,10 @@ function processElement (el, root, options, meta) {
1980
2039
 
1981
2040
  const pass = isNative || processTemplate(el) || processingTemplate
1982
2041
 
1983
- processScoped(el, options)
2042
+ // 仅ali平台需要scoped模拟样式隔离
2043
+ if (mode === 'ali') {
2044
+ processScoped(el, options)
2045
+ }
1984
2046
 
1985
2047
  if (transAli) {
1986
2048
  processAliExternalClassesHack(el, options)
@@ -2283,5 +2345,6 @@ module.exports = {
2283
2345
  makeAttrsMap,
2284
2346
  stringifyAttr,
2285
2347
  parseMustache,
2286
- stringifyWithResolveComputed
2348
+ stringifyWithResolveComputed,
2349
+ addAttrs
2287
2350
  }
@@ -38,7 +38,7 @@ module.exports = function (raw) {
38
38
  )
39
39
  }
40
40
 
41
- const parsed = compiler.parse(raw, {
41
+ const { root: ast, meta } = compiler.parse(raw, {
42
42
  warn,
43
43
  error,
44
44
  usingComponents,
@@ -57,13 +57,10 @@ module.exports = function (raw) {
57
57
  i18n,
58
58
  checkUsingComponents: mpx.checkUsingComponents,
59
59
  globalComponents: Object.keys(mpx.usingComponents),
60
- forceProxyEvent: matchCondition(this.resourcePath, mpx.forceProxyEventRules),
61
- hasVirtualHost: matchCondition(this.resourcePath, mpx.autoVirtualHostRules)
60
+ forceProxyEvent: matchCondition(resourcePath, mpx.forceProxyEventRules),
61
+ hasVirtualHost: matchCondition(resourcePath, mpx.autoVirtualHostRules)
62
62
  })
63
63
 
64
- let ast = parsed.root
65
- let meta = parsed.meta
66
-
67
64
  if (meta.wxsContentMap) {
68
65
  for (let module in meta.wxsContentMap) {
69
66
  wxsContentMap[`${resourcePath}~${module}`] = meta.wxsContentMap[module]
@@ -1,6 +1,6 @@
1
- const babylon = require('babylon')
2
- const t = require('babel-types')
3
- const generate = require('babel-generator').default
1
+ const babylon = require('@babel/parser')
2
+ const t = require('@babel/types')
3
+ const generate = require('@babel/generator').default
4
4
  const dash2hump = require('../utils/hump-dash').dash2hump
5
5
 
6
6
  module.exports = function transDynamicClassExpr (expr) {
@@ -1,5 +1,9 @@
1
1
  module.exports = {
2
2
  MPX_PROCESSED_FLAG: 'mpx_processed',
3
3
  MPX_DISABLE_EXTRACTOR_CACHE: 'mpx_disable_extractor_cache',
4
- DEFAULT_RESULT_SOURCE: ''
4
+ DEFAULT_RESULT_SOURCE: '',
5
+ RESOLVE_IGNORED_ERR: new Error('Resolve ignored!'),
6
+ JSON_JS_EXT: '.json.js',
7
+ MPX_ROOT_VIEW: 'mpx-root-view', // 根节点类名
8
+ MPX_APP_MODULE_ID: 'mpx-app-scope' // app文件moduleId
5
9
  }