@mpxjs/webpack-plugin 2.7.0-beta.2 → 2.7.0-beta.6

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 (48) hide show
  1. package/lib/dependencies/CommonJsVariableDependency.js +2 -7
  2. package/lib/dependencies/DynamicEntryDependency.js +5 -1
  3. package/lib/dependencies/{RecordStaticResourceDependency.js → RecordResourceMapDependency.js} +12 -7
  4. package/lib/dependencies/RemoveEntryDependency.js +40 -0
  5. package/lib/dependencies/ResolveDependency.js +8 -7
  6. package/lib/extractor.js +5 -4
  7. package/lib/file-loader.js +2 -2
  8. package/lib/helpers.js +1 -0
  9. package/lib/index.js +136 -112
  10. package/lib/json-compiler/helper.js +14 -21
  11. package/lib/json-compiler/index.js +67 -51
  12. package/lib/json-compiler/plugin.js +21 -5
  13. package/lib/loader.js +27 -50
  14. package/lib/native-loader.js +28 -65
  15. package/lib/parser.js +1 -2
  16. package/lib/platform/json/wx/index.js +7 -2
  17. package/lib/platform/template/wx/component-config/button.js +3 -3
  18. package/lib/platform/template/wx/component-config/navigator.js +1 -1
  19. package/lib/resolver/AddEnvPlugin.js +3 -2
  20. package/lib/resolver/AddModePlugin.js +3 -2
  21. package/lib/runtime/base.styl +5 -0
  22. package/lib/runtime/components/web/getInnerListeners.js +51 -45
  23. package/lib/runtime/components/web/mpx-keep-alive.vue +4 -1
  24. package/lib/runtime/components/web/mpx-tab-bar-container.vue +2 -2
  25. package/lib/runtime/optionProcessor.js +5 -20
  26. package/lib/runtime/stringify.wxs +3 -3
  27. package/lib/selector.js +3 -6
  28. package/lib/style-compiler/index.js +4 -5
  29. package/lib/template-compiler/bind-this.js +4 -4
  30. package/lib/template-compiler/compiler.js +105 -45
  31. package/lib/template-compiler/index.js +3 -6
  32. package/lib/template-compiler/trans-dynamic-class-expr.js +3 -3
  33. package/lib/utils/const.js +5 -1
  34. package/lib/utils/eval-json-js.js +31 -0
  35. package/lib/utils/get-json-content.js +41 -0
  36. package/lib/utils/resolve.js +13 -0
  37. package/lib/web/processJSON.js +113 -142
  38. package/lib/web/processScript.js +30 -24
  39. package/lib/web/processTemplate.js +56 -40
  40. package/lib/wxs/i18n-loader.js +1 -3
  41. package/lib/wxs/loader.js +6 -26
  42. package/lib/wxs/pre-loader.js +7 -8
  43. package/lib/wxss/processCss.js +44 -44
  44. package/package.json +8 -8
  45. package/lib/built-in-loader.js +0 -49
  46. package/lib/record-loader.js +0 -11
  47. package/lib/utils/get-main-compilation.js +0 -6
  48. package/lib/utils/read-json-for-src.js +0 -34
@@ -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) {
1729
+ addAttrs(el, [{
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
+
1730
1739
  addAttrs(el, [{
1731
- name: 'v-ex-classes',
1732
- value: JSON.stringify(externalClasses)
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 {
@@ -2283,5 +2342,6 @@ module.exports = {
2283
2342
  makeAttrsMap,
2284
2343
  stringifyAttr,
2285
2344
  parseMustache,
2286
- stringifyWithResolveComputed
2345
+ stringifyWithResolveComputed,
2346
+ addAttrs
2287
2347
  }
@@ -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
  }
@@ -0,0 +1,31 @@
1
+ const path = require('path')
2
+
3
+ module.exports = function evalJSONJS (source, filename, loaderContext) {
4
+ const fs = loaderContext._compiler.inputFileSystem
5
+ const defs = loaderContext.getMpx().defs
6
+ const defKeys = Object.keys(defs)
7
+ const defValues = defKeys.map((key) => {
8
+ return defs[key]
9
+ })
10
+ // 记录依赖
11
+ loaderContext.addDependency(filename)
12
+ const dirname = path.dirname(filename)
13
+ // eslint-disable-next-line no-new-func
14
+ const func = new Function('module', 'exports', 'require', '__filename', '__dirname', ...defKeys, source)
15
+ const module = {
16
+ exports: {}
17
+ }
18
+ // 此处采用readFileSync+evalJSONJS而不直接使用require获取依赖内容有两个原因:
19
+ // 1. 支持依赖中正常访问defs变量
20
+ // 2. 避免对应的依赖文件被作为buildDependencies
21
+ func(module, module.exports, function (request) {
22
+ if (request.startsWith('.')) {
23
+ request = path.join(dirname, request)
24
+ }
25
+ const filename = require.resolve(request)
26
+ const source = fs.readFileSync(filename).toString('utf-8')
27
+ return evalJSONJS(source, filename, loaderContext)
28
+ }, filename, dirname, ...defValues)
29
+
30
+ return module.exports
31
+ }
@@ -0,0 +1,41 @@
1
+ const parseRequest = require('./parse-request')
2
+ const evalJSONJS = require('./eval-json-js')
3
+ const resolve = require('./resolve')
4
+ const async = require('async')
5
+ const { JSON_JS_EXT } = require('./const')
6
+
7
+ module.exports = function getJSONContent (json, loaderContext, callback) {
8
+ const fs = loaderContext._compiler.inputFileSystem
9
+ async.waterfall([
10
+ (callback) => {
11
+ if (json.src) {
12
+ resolve(loaderContext.context, json.src, loaderContext, (err, result) => {
13
+ if (err) return callback(err)
14
+ const { rawResourcePath: resourcePath } = parseRequest(result)
15
+ fs.readFile(resourcePath, (err, content) => {
16
+ if (err) return callback(err)
17
+ callback(null, {
18
+ content: content.toString('utf-8'),
19
+ useJSONJS: json.useJSONJS || resourcePath.endsWith(JSON_JS_EXT),
20
+ filename: resourcePath
21
+
22
+ })
23
+ })
24
+ })
25
+ } else {
26
+ callback(null, {
27
+ content: json.content,
28
+ useJSONJS: json.useJSONJS,
29
+ filename: loaderContext.resourcePath
30
+ })
31
+ }
32
+ },
33
+ ({ content, useJSONJS, filename }, callback) => {
34
+ if (!content) return callback(null, '{}')
35
+ if (useJSONJS) {
36
+ content = JSON.stringify(evalJSONJS(content, filename, loaderContext))
37
+ }
38
+ callback(null, content)
39
+ }
40
+ ], callback)
41
+ }
@@ -0,0 +1,13 @@
1
+ const parseRequest = require('./parse-request')
2
+ const { RESOLVE_IGNORED_ERR } = require('./const')
3
+
4
+ // todo 提供不记录dependency的resolve方法,非必要的情况下不记录dependency,提升缓存利用率
5
+ module.exports = (context, request, loaderContext, callback) => {
6
+ const { queryObj } = parseRequest(request)
7
+ context = queryObj.context || context
8
+ return loaderContext.resolve(context, request, (err, resource, info) => {
9
+ if (err) return callback(err)
10
+ if (resource === false) return callback(RESOLVE_IGNORED_ERR)
11
+ callback(null, resource, info)
12
+ })
13
+ }