@mpxjs/webpack-plugin 2.10.6-beta.1 → 2.10.6-beta.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.
- package/lib/dependencies/WriteVfsDependency.js +46 -0
- package/lib/index.js +6 -0
- package/lib/platform/index.js +4 -2
- package/lib/platform/template/wx/component-config/index.js +2 -2
- package/lib/platform/template/wx/component-config/template.js +26 -1
- package/lib/platform/template/wx/index.js +10 -3
- package/lib/runtime/optionProcessor.js +2 -2
- package/lib/template-compiler/compiler.js +59 -9
- package/lib/utils/get-template-content.js +47 -0
- package/lib/web/index.js +2 -0
- package/lib/web/processScript.js +29 -7
- package/lib/web/processTemplate.js +10 -4
- package/lib/web/template2vue.js +280 -0
- package/lib/web/wxml-template-loader.js +29 -0
- package/package.json +1 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const NullDependency = require('webpack/lib/dependencies/NullDependency')
|
|
2
|
+
const makeSerializable = require('webpack/lib/util/makeSerializable')
|
|
3
|
+
|
|
4
|
+
class WriteVfsDependency extends NullDependency {
|
|
5
|
+
constructor (filename, content) {
|
|
6
|
+
super()
|
|
7
|
+
this.filename = filename
|
|
8
|
+
this.content = content
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get type () {
|
|
12
|
+
return 'mpx app entry'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
mpxAction (module, compilation, callback) {
|
|
16
|
+
const mpx = compilation.__mpx__
|
|
17
|
+
const vfs = mpx.__vfs
|
|
18
|
+
if (vfs) {
|
|
19
|
+
vfs.writeModule(this.filename, this.content)
|
|
20
|
+
}
|
|
21
|
+
return callback()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
serialize (context) {
|
|
25
|
+
const { write } = context
|
|
26
|
+
write(this.filename)
|
|
27
|
+
write(this.content)
|
|
28
|
+
super.serialize(context)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
deserialize (context) {
|
|
32
|
+
const { read } = context
|
|
33
|
+
this.filename = read()
|
|
34
|
+
this.content = read()
|
|
35
|
+
super.deserialize(context)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
WriteVfsDependency.Template = class WriteVfsDependencyTemplate {
|
|
40
|
+
apply () {
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
makeSerializable(WriteVfsDependency, '@mpxjs/webpack-plugin/lib/dependencies/WriteVfsDependency')
|
|
45
|
+
|
|
46
|
+
module.exports = WriteVfsDependency
|
package/lib/index.js
CHANGED
|
@@ -44,6 +44,7 @@ const FlagPluginDependency = require('./dependencies/FlagPluginDependency')
|
|
|
44
44
|
const RemoveEntryDependency = require('./dependencies/RemoveEntryDependency')
|
|
45
45
|
const RecordLoaderContentDependency = require('./dependencies/RecordLoaderContentDependency')
|
|
46
46
|
const RecordRuntimeInfoDependency = require('./dependencies/RecordRuntimeInfoDependency')
|
|
47
|
+
const WriteVfsDependency = require('./dependencies/WriteVfsDependency')
|
|
47
48
|
const SplitChunksPlugin = require('webpack/lib/optimize/SplitChunksPlugin')
|
|
48
49
|
const fixRelative = require('./utils/fix-relative')
|
|
49
50
|
const parseRequest = require('./utils/parse-request')
|
|
@@ -654,6 +655,9 @@ class MpxWebpackPlugin {
|
|
|
654
655
|
compilation.dependencyFactories.set(RecordRuntimeInfoDependency, new NullFactory())
|
|
655
656
|
compilation.dependencyTemplates.set(RecordRuntimeInfoDependency, new RecordRuntimeInfoDependency.Template())
|
|
656
657
|
|
|
658
|
+
compilation.dependencyFactories.set(WriteVfsDependency, new NullFactory())
|
|
659
|
+
compilation.dependencyTemplates.set(WriteVfsDependency, new WriteVfsDependency.Template())
|
|
660
|
+
|
|
657
661
|
compilation.dependencyTemplates.set(ImportDependency, new ImportDependencyTemplate())
|
|
658
662
|
})
|
|
659
663
|
|
|
@@ -677,6 +681,8 @@ class MpxWebpackPlugin {
|
|
|
677
681
|
componentsMap: {
|
|
678
682
|
main: {}
|
|
679
683
|
},
|
|
684
|
+
// 用于template模版获取父组件引用的自定义组件,目前仅输出web时下支持使用
|
|
685
|
+
parentLocalComponentsMap: {},
|
|
680
686
|
// 静态资源(图片,字体,独立样式)等,依照所属包进行记录
|
|
681
687
|
staticResourcesMap: {
|
|
682
688
|
main: {}
|
package/lib/platform/index.js
CHANGED
|
@@ -9,6 +9,7 @@ module.exports = function getRulesRunner ({
|
|
|
9
9
|
testKey,
|
|
10
10
|
mainKey,
|
|
11
11
|
waterfall,
|
|
12
|
+
moduleId,
|
|
12
13
|
warn,
|
|
13
14
|
error
|
|
14
15
|
}) {
|
|
@@ -23,13 +24,14 @@ module.exports = function getRulesRunner ({
|
|
|
23
24
|
wx: require('./json/wx')
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
|
-
const spec = specMap[type] && specMap[type][srcMode] && specMap[type][srcMode]({ warn, error })
|
|
27
|
+
const spec = specMap[type] && specMap[type][srcMode] && specMap[type][srcMode]({ warn, error, moduleId })
|
|
27
28
|
if (spec && spec.supportedModes.indexOf(mode) > -1) {
|
|
28
29
|
const normalizeTest = spec.normalizeTest
|
|
29
30
|
const mainRules = mainKey ? spec[mainKey] : spec
|
|
30
31
|
if (mainRules) {
|
|
31
32
|
return function (input) {
|
|
32
|
-
|
|
33
|
+
const a = runRules(mainRules, input, { mode, data, meta, testKey, waterfall, normalizeTest })
|
|
34
|
+
return a
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
}
|
|
@@ -45,7 +45,7 @@ const rootPortal = require('./root-portal')
|
|
|
45
45
|
const stickyHeader = require('./sticky-header')
|
|
46
46
|
const stickySection = require('./sticky-section')
|
|
47
47
|
|
|
48
|
-
module.exports = function getComponentConfigs ({ warn, error }) {
|
|
48
|
+
module.exports = function getComponentConfigs ({ warn, error, moduleId }) {
|
|
49
49
|
/**
|
|
50
50
|
* universal print for detail component warn or error
|
|
51
51
|
* @param {object} config
|
|
@@ -116,7 +116,7 @@ module.exports = function getComponentConfigs ({ warn, error }) {
|
|
|
116
116
|
map({ print }),
|
|
117
117
|
canvas({ print }),
|
|
118
118
|
wxs({ print }),
|
|
119
|
-
template(),
|
|
119
|
+
template({ moduleId }),
|
|
120
120
|
block(),
|
|
121
121
|
icon(),
|
|
122
122
|
webView({ print }),
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
const TAG_NAME = 'template'
|
|
2
2
|
|
|
3
|
-
module.exports = function () {
|
|
3
|
+
module.exports = function ({ moduleId }) {
|
|
4
4
|
return {
|
|
5
5
|
test: TAG_NAME,
|
|
6
|
+
web (tag, { el }) {
|
|
7
|
+
if (el.attrsMap[':is']) {
|
|
8
|
+
return 'component'
|
|
9
|
+
}
|
|
10
|
+
},
|
|
6
11
|
props: [
|
|
7
12
|
{
|
|
8
13
|
test: 'data',
|
|
@@ -11,6 +16,26 @@ module.exports = function () {
|
|
|
11
16
|
name,
|
|
12
17
|
value: `{${value}}`
|
|
13
18
|
}
|
|
19
|
+
},
|
|
20
|
+
web ({ value }) {
|
|
21
|
+
let bindValue = value
|
|
22
|
+
if (moduleId) {
|
|
23
|
+
const lastIndex = value.lastIndexOf('}}')
|
|
24
|
+
bindValue = value ? value.slice(0, lastIndex) + `, _data_v_id: '${moduleId}'}}` : `{{ _data_v_id: '${moduleId}' }}`
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
name: 'v-bind',
|
|
28
|
+
value: bindValue
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
test: 'is',
|
|
34
|
+
web ({ value }) {
|
|
35
|
+
return {
|
|
36
|
+
name: ':is',
|
|
37
|
+
value: `'${value}'`
|
|
38
|
+
}
|
|
14
39
|
}
|
|
15
40
|
}
|
|
16
41
|
]
|
|
@@ -3,11 +3,11 @@ const JSON5 = require('json5')
|
|
|
3
3
|
const getComponentConfigs = require('./component-config')
|
|
4
4
|
const normalizeComponentRules = require('../normalize-component-rules')
|
|
5
5
|
const isValidIdentifierStr = require('../../../utils/is-valid-identifier-str')
|
|
6
|
-
const { parseMustacheWithContext, stringifyWithResolveComputed } = require('../../../template-compiler/compiler')
|
|
6
|
+
const { vbindMustache, parseMustacheWithContext, stringifyWithResolveComputed } = require('../../../template-compiler/compiler')
|
|
7
7
|
const normalize = require('../../../utils/normalize')
|
|
8
8
|
const { dash2hump } = require('../../../utils/hump-dash')
|
|
9
9
|
|
|
10
|
-
module.exports = function getSpec ({ warn, error }) {
|
|
10
|
+
module.exports = function getSpec ({ warn, error, moduleId }) {
|
|
11
11
|
function getRnDirectiveEventHandle (mode) {
|
|
12
12
|
return function ({ name, value }, { eventRules, el }) {
|
|
13
13
|
const match = this.test.exec(name)
|
|
@@ -68,6 +68,13 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
68
68
|
postProps: [
|
|
69
69
|
{
|
|
70
70
|
web ({ name, value }) {
|
|
71
|
+
if (name === 'v-bind') {
|
|
72
|
+
const vbindValue = vbindMustache(value)
|
|
73
|
+
return {
|
|
74
|
+
name,
|
|
75
|
+
value: vbindValue
|
|
76
|
+
}
|
|
77
|
+
}
|
|
71
78
|
const parsed = parseMustacheWithContext(value)
|
|
72
79
|
if (name.startsWith('data-')) {
|
|
73
80
|
return {
|
|
@@ -567,6 +574,6 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
567
574
|
]
|
|
568
575
|
}
|
|
569
576
|
}
|
|
570
|
-
spec.rules = normalizeComponentRules(getComponentConfigs({ warn, error }).concat({}), spec)
|
|
577
|
+
spec.rules = normalizeComponentRules(getComponentConfigs({ warn, error, moduleId }).concat({}), spec)
|
|
571
578
|
return spec
|
|
572
579
|
}
|
|
@@ -79,7 +79,7 @@ registered in parent context!`)
|
|
|
79
79
|
transitionName: ''
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
if (!global.__mpx.config.webConfig
|
|
82
|
+
if (!global.__mpx.config.webConfig?.disablePageTransition) {
|
|
83
83
|
option.watch = {
|
|
84
84
|
$route: {
|
|
85
85
|
handler () {
|
|
@@ -161,7 +161,7 @@ function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, t
|
|
|
161
161
|
redirect: '/' + firstPage
|
|
162
162
|
})
|
|
163
163
|
}
|
|
164
|
-
const webRouteConfig = global.__mpx.config.webConfig
|
|
164
|
+
const webRouteConfig = global.__mpx.config.webConfig?.routeConfig || global.__mpx.config.webRouteConfig
|
|
165
165
|
global.__mpxRouter = option.router = new VueRouter(extend({ routes }, webRouteConfig))
|
|
166
166
|
let mpxStackPath = []
|
|
167
167
|
if (isBrowser) {
|
|
@@ -16,6 +16,7 @@ const setBaseWxml = require('../runtime-render/base-wxml')
|
|
|
16
16
|
const { parseExp } = require('./parse-exps')
|
|
17
17
|
const shallowStringify = require('../utils/shallow-stringify')
|
|
18
18
|
const { isReact, isWeb } = require('../utils/env')
|
|
19
|
+
const getTemplateContent = require('../utils/get-template-content')
|
|
19
20
|
|
|
20
21
|
const no = function () {
|
|
21
22
|
return false
|
|
@@ -638,7 +639,7 @@ function parse (template, options) {
|
|
|
638
639
|
componentGenerics = options.componentGenerics || {}
|
|
639
640
|
|
|
640
641
|
if (typeof options.usingComponentsInfo === 'string') options.usingComponentsInfo = JSON.parse(options.usingComponentsInfo)
|
|
641
|
-
usingComponents = Object.keys(options.usingComponentsInfo)
|
|
642
|
+
usingComponents = Object.keys(options.usingComponentsInfo || {})
|
|
642
643
|
usingComponentsInfo = options.usingComponentsInfo
|
|
643
644
|
|
|
644
645
|
const _warn = content => {
|
|
@@ -661,6 +662,7 @@ function parse (template, options) {
|
|
|
661
662
|
srcMode,
|
|
662
663
|
type: 'template',
|
|
663
664
|
testKey: 'tag',
|
|
665
|
+
moduleId,
|
|
664
666
|
data: {
|
|
665
667
|
usingComponents
|
|
666
668
|
},
|
|
@@ -689,6 +691,7 @@ function parse (template, options) {
|
|
|
689
691
|
root = currentParent = getVirtualHostRoot(options, meta)
|
|
690
692
|
stack.push(root)
|
|
691
693
|
}
|
|
694
|
+
options.template = template // processTemplate时需要对template(只用于处理含name的情况)做截取
|
|
692
695
|
|
|
693
696
|
parseHTML(template, {
|
|
694
697
|
warn: warn$1,
|
|
@@ -721,6 +724,7 @@ function parse (template, options) {
|
|
|
721
724
|
|
|
722
725
|
currentParent.children.push(element)
|
|
723
726
|
element.parent = currentParent
|
|
727
|
+
|
|
724
728
|
processElement(element, root, options, meta)
|
|
725
729
|
|
|
726
730
|
tagNames.add(element.tag)
|
|
@@ -1426,7 +1430,6 @@ function processEvent (el, options) {
|
|
|
1426
1430
|
}
|
|
1427
1431
|
}
|
|
1428
1432
|
})
|
|
1429
|
-
|
|
1430
1433
|
addAttrs(el, [
|
|
1431
1434
|
{
|
|
1432
1435
|
name: resultName || config[mode].event.getEvent(type),
|
|
@@ -1462,6 +1465,13 @@ function wrapMustache (val) {
|
|
|
1462
1465
|
return val && !tagRE.test(val) ? `{{${val}}}` : val
|
|
1463
1466
|
}
|
|
1464
1467
|
|
|
1468
|
+
function vbindMustache (val) {
|
|
1469
|
+
const bindREG = /\{\{((?:.|\n|\r|\.{3})+?)\}\}(?!})/
|
|
1470
|
+
const match = bindREG.exec(val) || []
|
|
1471
|
+
const matchStr = match[1]?.trim()
|
|
1472
|
+
return matchStr ? `{${matchStr}}` : val
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1465
1475
|
function parseOptionalChaining (str) {
|
|
1466
1476
|
const wxsName = `${optionalChainWxsName}.g`
|
|
1467
1477
|
let optionsRes
|
|
@@ -2302,7 +2312,7 @@ function processExternalClasses (el, options) {
|
|
|
2302
2312
|
let classNames = classLikeAttrValue.split(/\s+/)
|
|
2303
2313
|
let hasExternalClass = false
|
|
2304
2314
|
classNames = classNames.map((className) => {
|
|
2305
|
-
if (options.externalClasses
|
|
2315
|
+
if (options.externalClasses?.includes(className)) {
|
|
2306
2316
|
hasExternalClass = true
|
|
2307
2317
|
return `($attrs[${stringify(className)}] || '')`
|
|
2308
2318
|
}
|
|
@@ -2345,12 +2355,12 @@ function processExternalClasses (el, options) {
|
|
|
2345
2355
|
}
|
|
2346
2356
|
|
|
2347
2357
|
function processScoped (el) {
|
|
2348
|
-
if (hasScoped && isRealNode(el)) {
|
|
2358
|
+
if (hasScoped && isRealNode(el) && (isWeb(mode) && el.tag !== 'component')) { // 处理web下 template第一个元素不设置mpx-app-scope
|
|
2349
2359
|
const rootModuleId = ctorType === 'component' ? '' : MPX_APP_MODULE_ID // 处理app全局样式对页面的影响
|
|
2350
2360
|
const staticClass = getAndRemoveAttr(el, 'class').val
|
|
2351
2361
|
addAttrs(el, [{
|
|
2352
2362
|
name: 'class',
|
|
2353
|
-
value: `${staticClass || ''} ${moduleId} ${rootModuleId}`
|
|
2363
|
+
value: `${staticClass || ''} ${moduleId || ''} ${rootModuleId}`
|
|
2354
2364
|
}])
|
|
2355
2365
|
}
|
|
2356
2366
|
}
|
|
@@ -2449,7 +2459,7 @@ function getVirtualHostRoot (options, meta) {
|
|
|
2449
2459
|
const rootView = createASTElement('view', [
|
|
2450
2460
|
{
|
|
2451
2461
|
name: 'class',
|
|
2452
|
-
value: `${MPX_ROOT_VIEW}
|
|
2462
|
+
value: `${MPX_ROOT_VIEW} ${moduleId ? 'host-' + moduleId : ''}` // 解决template2vue中拿不到moduleId的情况
|
|
2453
2463
|
},
|
|
2454
2464
|
{
|
|
2455
2465
|
name: 'v-on',
|
|
@@ -2528,8 +2538,33 @@ function processTemplate (el) {
|
|
|
2528
2538
|
}
|
|
2529
2539
|
}
|
|
2530
2540
|
|
|
2531
|
-
function
|
|
2541
|
+
function processImport (el, meta) { // 收集import引用的地址
|
|
2542
|
+
if (el.tag === 'import' && el.attrsMap.src) {
|
|
2543
|
+
if (!meta.templateSrcList) {
|
|
2544
|
+
meta.templateSrcList = []
|
|
2545
|
+
}
|
|
2546
|
+
if (!meta.templateSrcList.includes(el.attrsMap.src)) {
|
|
2547
|
+
meta.templateSrcList.push(el.attrsMap.src)
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
function postProcessTemplate (el, meta, options) {
|
|
2532
2553
|
if (el.isTemplate) {
|
|
2554
|
+
if (mode === 'web') {
|
|
2555
|
+
if (!meta.inlineTemplateMap) {
|
|
2556
|
+
meta.inlineTemplateMap = {}
|
|
2557
|
+
}
|
|
2558
|
+
const name = el.attrsMap.name // 行内的template有name就收集template的内容和给内容生成一个地址
|
|
2559
|
+
if (name) {
|
|
2560
|
+
const content = getTemplateContent(options.template, name)
|
|
2561
|
+
const filePath = options.filePath.replace(/.mpx$/, `-${name}.wxml`)
|
|
2562
|
+
meta.inlineTemplateMap[name] = {
|
|
2563
|
+
filePath,
|
|
2564
|
+
content
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2533
2568
|
processingTemplate = false
|
|
2534
2569
|
return true
|
|
2535
2570
|
}
|
|
@@ -2679,6 +2714,7 @@ function processMpxTagName (el) {
|
|
|
2679
2714
|
}
|
|
2680
2715
|
|
|
2681
2716
|
function processElement (el, root, options, meta) {
|
|
2717
|
+
const initialTag = el.tag // 预存,在这个阶段增加_fakeTemplate值会影响web小程序元素trans web元素
|
|
2682
2718
|
processAtMode(el)
|
|
2683
2719
|
// 如果已经标记了这个元素要被清除,直接return跳过后续处理步骤
|
|
2684
2720
|
if (el._matchStatus === statusEnum.MISMATCH) {
|
|
@@ -2705,10 +2741,17 @@ function processElement (el, root, options, meta) {
|
|
|
2705
2741
|
const transAli = mode === 'ali' && srcMode === 'wx'
|
|
2706
2742
|
|
|
2707
2743
|
if (isWeb(mode)) {
|
|
2744
|
+
if (initialTag === 'block') {
|
|
2745
|
+
el._fakeTemplate = true // 该值是在template2vue中处理block转换的template的情况
|
|
2746
|
+
}
|
|
2708
2747
|
// 收集内建组件
|
|
2709
2748
|
processBuiltInComponents(el, meta)
|
|
2710
2749
|
// 预处理代码维度条件编译
|
|
2711
2750
|
processIfWeb(el)
|
|
2751
|
+
// 预处理template逻辑
|
|
2752
|
+
processTemplate(el)
|
|
2753
|
+
// 预处理import逻辑
|
|
2754
|
+
processImport(el, meta)
|
|
2712
2755
|
processScoped(el)
|
|
2713
2756
|
processEventWeb(el)
|
|
2714
2757
|
// processWebExternalClassesHack(el, options)
|
|
@@ -2771,8 +2814,9 @@ function processElement (el, root, options, meta) {
|
|
|
2771
2814
|
function closeElement (el, options, meta) {
|
|
2772
2815
|
postProcessAtMode(el)
|
|
2773
2816
|
postProcessWxs(el, meta)
|
|
2774
|
-
|
|
2775
2817
|
if (isWeb(mode)) {
|
|
2818
|
+
// 处理web下template逻辑
|
|
2819
|
+
postProcessTemplate(el, meta, options)
|
|
2776
2820
|
// 处理代码维度条件编译移除死分支
|
|
2777
2821
|
postProcessIf(el)
|
|
2778
2822
|
return
|
|
@@ -2783,7 +2827,7 @@ function closeElement (el, options, meta) {
|
|
|
2783
2827
|
return
|
|
2784
2828
|
}
|
|
2785
2829
|
|
|
2786
|
-
const isTemplate = postProcessTemplate(el) || processingTemplate
|
|
2830
|
+
const isTemplate = postProcessTemplate(el, meta) || processingTemplate
|
|
2787
2831
|
if (!isTemplate) {
|
|
2788
2832
|
if (!isNative) {
|
|
2789
2833
|
postProcessComponentIs(el, (child) => {
|
|
@@ -2905,6 +2949,11 @@ function serialize (root) {
|
|
|
2905
2949
|
result += node.text
|
|
2906
2950
|
}
|
|
2907
2951
|
}
|
|
2952
|
+
if (mode === 'web') {
|
|
2953
|
+
if ((node.tag === 'template' && node.attrsMap && node.attrsMap.name) || node.tag === 'import') {
|
|
2954
|
+
return result
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2908
2957
|
|
|
2909
2958
|
if (node.type === 1) {
|
|
2910
2959
|
if (node.tag !== 'temp-node') {
|
|
@@ -3209,6 +3258,7 @@ module.exports = {
|
|
|
3209
3258
|
genNode,
|
|
3210
3259
|
makeAttrsMap,
|
|
3211
3260
|
stringifyAttr,
|
|
3261
|
+
vbindMustache,
|
|
3212
3262
|
parseMustache,
|
|
3213
3263
|
parseMustacheWithContext,
|
|
3214
3264
|
stringifyWithResolveComputed,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*
|
|
2
|
+
对template.wxml文件做截取
|
|
3
|
+
@source原始小程序文件
|
|
4
|
+
@name 要匹配的该name的template
|
|
5
|
+
*/
|
|
6
|
+
module.exports = function (source, name) {
|
|
7
|
+
// 使用正则表达式匹配具有 name 的 template 标签及其所有子元素
|
|
8
|
+
// 正则表达式使用非贪婪匹配来递归匹配嵌套的 template
|
|
9
|
+
const regex = new RegExp(`(<template[^>]*\\bname=["|']${name}["|'][^>]*>).*?`, 'g')
|
|
10
|
+
|
|
11
|
+
let startIndex = 0
|
|
12
|
+
let endIndex = 0
|
|
13
|
+
const match = regex.exec(source)
|
|
14
|
+
// 逐个处理匹配到的 template 标签及其内容
|
|
15
|
+
if (match) {
|
|
16
|
+
const matchRes = match[0]
|
|
17
|
+
const reg = /<\/?template\s*[^>]*>/g
|
|
18
|
+
let n = 0
|
|
19
|
+
startIndex = match.index
|
|
20
|
+
endIndex = startIndex + matchRes.length
|
|
21
|
+
let html = source.slice(endIndex)
|
|
22
|
+
while (html) {
|
|
23
|
+
const matchRes = html.match(reg)
|
|
24
|
+
if (matchRes.length) {
|
|
25
|
+
const matchTemp = matchRes[0]
|
|
26
|
+
const matchIndex = html.indexOf(matchTemp)
|
|
27
|
+
const matchLength = matchTemp.length
|
|
28
|
+
const cutLength = matchIndex + matchLength
|
|
29
|
+
if (matchTemp.startsWith('</template>')) {
|
|
30
|
+
if (n === 0) {
|
|
31
|
+
endIndex += cutLength
|
|
32
|
+
break
|
|
33
|
+
} else {
|
|
34
|
+
n--
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
n++
|
|
38
|
+
}
|
|
39
|
+
endIndex += cutLength
|
|
40
|
+
html = html.slice(cutLength)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
return ''
|
|
45
|
+
}
|
|
46
|
+
return source.slice(startIndex, endIndex)
|
|
47
|
+
}
|
package/lib/web/index.js
CHANGED
|
@@ -108,6 +108,8 @@ module.exports = function ({
|
|
|
108
108
|
builtInComponentsMap: templateRes.builtInComponentsMap,
|
|
109
109
|
genericsInfo: templateRes.genericsInfo,
|
|
110
110
|
wxsModuleMap: templateRes.wxsModuleMap,
|
|
111
|
+
templateSrcList: templateRes.templateSrcList,
|
|
112
|
+
inlineTemplateMap: templateRes.inlineTemplateMap,
|
|
111
113
|
localComponentsMap: jsonRes.localComponentsMap
|
|
112
114
|
}, callback)
|
|
113
115
|
}
|
package/lib/web/processScript.js
CHANGED
|
@@ -3,6 +3,8 @@ const loaderUtils = require('loader-utils')
|
|
|
3
3
|
const normalize = require('../utils/normalize')
|
|
4
4
|
const shallowStringify = require('../utils/shallow-stringify')
|
|
5
5
|
const optionProcessorPath = normalize.lib('runtime/optionProcessor')
|
|
6
|
+
const wxmlTemplateLoader = normalize.lib('web/wxml-template-loader')
|
|
7
|
+
const WriteVfsDependency = require('../dependencies/WriteVfsDependency')
|
|
6
8
|
const {
|
|
7
9
|
buildComponentsMap,
|
|
8
10
|
getRequireScript,
|
|
@@ -22,18 +24,20 @@ module.exports = function (script, {
|
|
|
22
24
|
builtInComponentsMap,
|
|
23
25
|
genericsInfo,
|
|
24
26
|
wxsModuleMap,
|
|
27
|
+
templateSrcList,
|
|
28
|
+
inlineTemplateMap,
|
|
25
29
|
localComponentsMap
|
|
26
30
|
}, callback) {
|
|
27
|
-
const { projectRoot, appInfo, webConfig } = loaderContext.getMpx()
|
|
31
|
+
const { projectRoot, appInfo, webConfig, __vfs: vfs, parentLocalComponentsMap } = loaderContext.getMpx()
|
|
28
32
|
|
|
29
33
|
let output = '/* script */\n'
|
|
30
|
-
|
|
31
34
|
let scriptSrcMode = srcMode
|
|
32
35
|
if (script) {
|
|
33
36
|
scriptSrcMode = script.mode || scriptSrcMode
|
|
34
37
|
} else {
|
|
35
38
|
script = { tag: 'script' }
|
|
36
39
|
}
|
|
40
|
+
|
|
37
41
|
output += genComponentTag(script, {
|
|
38
42
|
attrs (script) {
|
|
39
43
|
const attrs = Object.assign({}, script.attrs)
|
|
@@ -58,17 +62,36 @@ module.exports = function (script, {
|
|
|
58
62
|
content += ` wxsModules.${module} = ${expression}\n`
|
|
59
63
|
})
|
|
60
64
|
}
|
|
61
|
-
|
|
65
|
+
content += 'const templateModules = {}\n'
|
|
66
|
+
if (templateSrcList?.length) { // import标签处理
|
|
67
|
+
templateSrcList?.forEach((item) => {
|
|
68
|
+
content += `
|
|
69
|
+
const tempLoaderResult = require(${stringifyRequest(this, `!!${wxmlTemplateLoader}!${item}`)})\n
|
|
70
|
+
Object.assign(templateModules, tempLoaderResult)\n`
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
// 把wxml要的localComponentsMap merge到parentLocalComponentsMap中这样在 template2vue中就可以拿到对应的值
|
|
74
|
+
Object.assign(parentLocalComponentsMap, localComponentsMap)
|
|
62
75
|
// 获取组件集合
|
|
63
76
|
const componentsMap = buildComponentsMap({ localComponentsMap, builtInComponentsMap, loaderContext, jsonConfig })
|
|
64
|
-
|
|
65
77
|
// 获取pageConfig
|
|
66
78
|
const pageConfig = {}
|
|
67
79
|
if (ctorType === 'page') {
|
|
68
80
|
Object.assign(pageConfig, jsonConfig)
|
|
69
81
|
delete pageConfig.usingComponents
|
|
70
82
|
}
|
|
71
|
-
|
|
83
|
+
if (inlineTemplateMap) { // 处理行内template(只有属性为name的情况)
|
|
84
|
+
const inlineTemplateMapLists = Object.keys(inlineTemplateMap)
|
|
85
|
+
if (inlineTemplateMapLists.length) {
|
|
86
|
+
inlineTemplateMapLists.forEach((name) => {
|
|
87
|
+
const { filePath, content } = inlineTemplateMap[name]
|
|
88
|
+
loaderContext._module.addPresentationalDependency(new WriteVfsDependency(filePath, content)) // 处理缓存报错的情况
|
|
89
|
+
vfs.writeModule(filePath, content) // 截取template写入文件
|
|
90
|
+
const expression = `getComponent(require(${stringifyRequest(loaderContext, `${filePath}?is=${name}&localComponentsMap=${encodeURIComponent(JSON.stringify(localComponentsMap))}&isTemplate`)}))`
|
|
91
|
+
componentsMap[name] = expression
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
}
|
|
72
95
|
content += buildGlobalParams({ moduleId, scriptSrcMode, loaderContext, isProduction, webConfig, hasApp })
|
|
73
96
|
content += getRequireScript({ ctorType, script, loaderContext })
|
|
74
97
|
content += `
|
|
@@ -78,7 +101,7 @@ module.exports = function (script, {
|
|
|
78
101
|
outputPath: ${JSON.stringify(outputPath)},
|
|
79
102
|
pageConfig: ${JSON.stringify(pageConfig)},
|
|
80
103
|
// @ts-ignore
|
|
81
|
-
componentsMap: ${shallowStringify(componentsMap)},
|
|
104
|
+
componentsMap: Object.assign(${shallowStringify(componentsMap)}, templateModules),
|
|
82
105
|
componentGenerics: ${JSON.stringify(componentGenerics)},
|
|
83
106
|
genericsInfo: ${JSON.stringify(genericsInfo)},
|
|
84
107
|
wxsMixin: getWxsMixin(wxsModules),
|
|
@@ -87,7 +110,6 @@ module.exports = function (script, {
|
|
|
87
110
|
return content
|
|
88
111
|
}
|
|
89
112
|
})
|
|
90
|
-
|
|
91
113
|
callback(null, {
|
|
92
114
|
output
|
|
93
115
|
})
|
|
@@ -31,7 +31,7 @@ module.exports = function (template, {
|
|
|
31
31
|
const { resourcePath, rawResourcePath } = parseRequest(loaderContext.resource)
|
|
32
32
|
const builtInComponentsMap = {}
|
|
33
33
|
|
|
34
|
-
let wxsModuleMap, genericsInfo
|
|
34
|
+
let wxsModuleMap, genericsInfo, inlineTemplateMap, templateSrcList
|
|
35
35
|
let output = '/* template */\n'
|
|
36
36
|
|
|
37
37
|
if (ctorType === 'app') {
|
|
@@ -54,7 +54,6 @@ module.exports = function (template, {
|
|
|
54
54
|
if (template.lang) {
|
|
55
55
|
return callback(new Error('[mpx loader][' + loaderContext.resource + ']: ' + 'template lang is not supported in trans web mode temporarily, we will support it in the future!'))
|
|
56
56
|
}
|
|
57
|
-
|
|
58
57
|
output += genComponentTag(template, (template) => {
|
|
59
58
|
if (ctorType === 'app') {
|
|
60
59
|
return template.content
|
|
@@ -104,6 +103,12 @@ module.exports = function (template, {
|
|
|
104
103
|
wxsContentMap[`${rawResourcePath}~${module}`] = meta.wxsContentMap[module]
|
|
105
104
|
}
|
|
106
105
|
}
|
|
106
|
+
if (meta.inlineTemplateMap) {
|
|
107
|
+
inlineTemplateMap = meta.inlineTemplateMap
|
|
108
|
+
}
|
|
109
|
+
if (meta.templateSrcList?.length) {
|
|
110
|
+
templateSrcList = meta.templateSrcList
|
|
111
|
+
}
|
|
107
112
|
if (meta.builtInComponentsMap) {
|
|
108
113
|
Object.keys(meta.builtInComponentsMap).forEach((name) => {
|
|
109
114
|
builtInComponentsMap[name] = {
|
|
@@ -114,15 +119,16 @@ module.exports = function (template, {
|
|
|
114
119
|
if (meta.genericsInfo) {
|
|
115
120
|
genericsInfo = meta.genericsInfo
|
|
116
121
|
}
|
|
117
|
-
return templateCompiler.serialize(root)
|
|
122
|
+
return templateCompiler.serialize(root, moduleId) // 增加moduleId给到template2vue拿到正确的scopedId
|
|
118
123
|
}
|
|
119
124
|
})
|
|
120
125
|
output += '\n'
|
|
121
126
|
}
|
|
122
|
-
|
|
123
127
|
callback(null, {
|
|
124
128
|
output,
|
|
125
129
|
builtInComponentsMap,
|
|
130
|
+
inlineTemplateMap,
|
|
131
|
+
templateSrcList,
|
|
126
132
|
genericsInfo,
|
|
127
133
|
wxsModuleMap
|
|
128
134
|
})
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
const templateCompiler = require('../template-compiler/compiler')
|
|
2
|
+
const parseRequest = require('../utils/parse-request')
|
|
3
|
+
const addQuery = require('../utils/add-query')
|
|
4
|
+
const { buildComponentsMap } = require('./script-helper')
|
|
5
|
+
const loaderUtils = require('loader-utils')
|
|
6
|
+
const normalize = require('../utils/normalize')
|
|
7
|
+
const domTagConfig = require('../utils/dom-tag-config')
|
|
8
|
+
const optionProcessorPath = normalize.lib('runtime/optionProcessor')
|
|
9
|
+
const shallowStringify = require('../utils/shallow-stringify')
|
|
10
|
+
const { stringifyRequest } = require('./script-helper')
|
|
11
|
+
const parseQuery = require('loader-utils').parseQuery
|
|
12
|
+
const wxmlTemplateLoader = normalize.lib('web/wxml-template-loader')
|
|
13
|
+
|
|
14
|
+
const getRefVarNames = function (str = '', discardProp) { // 获取元素属性上用到的动态数据keyname
|
|
15
|
+
const regex = /\(([a-zA-Z_$]\w*)\)/g
|
|
16
|
+
const matches = str.match(regex) || []
|
|
17
|
+
const variableNames = []
|
|
18
|
+
matches.forEach(name => {
|
|
19
|
+
const getName = /\((\w+)\)/.exec(name)
|
|
20
|
+
if (!discardProp.includes(getName[1]) && getName[1]) {
|
|
21
|
+
variableNames.push(getName[1].trim())
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
return variableNames
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const getTextVarName = function (str = '', discardProp) { // 获取文本中的动态数据keyname
|
|
28
|
+
const regex = /\{\{([^{}]+?)(?:\..*?)?\}\}/g
|
|
29
|
+
const variables = []
|
|
30
|
+
let match
|
|
31
|
+
|
|
32
|
+
while ((match = regex.exec(str)) !== null) {
|
|
33
|
+
const inner = match[1] // 匹配 {{...}} 内部内容
|
|
34
|
+
const varName = inner.split('.')[0]
|
|
35
|
+
if (!discardProp.includes(varName) && varName) {
|
|
36
|
+
variables.push(varName.trim())
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return variables
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 所有的props是在遍历模版的时候收集的,需要把true/false/for上面定义的item index剔除掉
|
|
43
|
+
const addDiscardProp = function (attrList, discardProp) {
|
|
44
|
+
for (let i = 0; i < attrList.length; i++) {
|
|
45
|
+
if (attrList[i].name === 'v-for') {
|
|
46
|
+
const regex = /\(([^)]+)\)/
|
|
47
|
+
const match = attrList[i].value?.match(regex)
|
|
48
|
+
if (match) {
|
|
49
|
+
const discardValue = match[1].split(',').map(s => s.trim()) || []
|
|
50
|
+
discardProp.push(...discardValue)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const getEventName = function (eventStr = '') { // 获取事件用到的动态数据keyname 返回数组是避免将空值写入prop
|
|
57
|
+
const match = eventStr.match(/\[\[\s*"([^"]*)"\s*\]\]/)
|
|
58
|
+
if (match) {
|
|
59
|
+
const extractedValue = match[1]
|
|
60
|
+
const trimmedValue = extractedValue
|
|
61
|
+
return [trimmedValue]
|
|
62
|
+
}
|
|
63
|
+
return []
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = function (content) {
|
|
67
|
+
const mpx = this.getMpx()
|
|
68
|
+
const {
|
|
69
|
+
wxsContentMap,
|
|
70
|
+
projectRoot
|
|
71
|
+
} = mpx
|
|
72
|
+
this._compiler = true
|
|
73
|
+
const query = parseQuery(this.resourceQuery)
|
|
74
|
+
if (!query.is) {
|
|
75
|
+
return content
|
|
76
|
+
}
|
|
77
|
+
let parentLocalComponentsMap = {}
|
|
78
|
+
try {
|
|
79
|
+
parentLocalComponentsMap = JSON.parse(query.localComponentsMap) // 拿取父组件上面的所有本地组件
|
|
80
|
+
} catch (e) {}
|
|
81
|
+
const { resourcePath, rawResourcePath } = parseRequest(this.resource)
|
|
82
|
+
const props = ['_data_v_id']
|
|
83
|
+
const { root, meta } = templateCompiler.parse(content, { // 调用已有的parse方法处理模版
|
|
84
|
+
warn: (msg) => {
|
|
85
|
+
this.emitWarning(
|
|
86
|
+
new Error('[template compiler][' + this.resource + ']: ' + msg)
|
|
87
|
+
)
|
|
88
|
+
},
|
|
89
|
+
error: (msg) => {
|
|
90
|
+
this.emitError(
|
|
91
|
+
new Error('[template compiler][' + this.resource + ']: ' + msg)
|
|
92
|
+
)
|
|
93
|
+
},
|
|
94
|
+
isTemp2vue: true,
|
|
95
|
+
mode: 'web',
|
|
96
|
+
srcMode: 'wx',
|
|
97
|
+
filePath: resourcePath,
|
|
98
|
+
usingComponents: []
|
|
99
|
+
})
|
|
100
|
+
const builtInComponentsMap = {}
|
|
101
|
+
if (meta.builtInComponentsMap) {
|
|
102
|
+
Object.keys(meta.builtInComponentsMap).forEach((name) => {
|
|
103
|
+
builtInComponentsMap[name] = {
|
|
104
|
+
resource: addQuery(meta.builtInComponentsMap[name], { isComponent: true })
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (meta.wxsContentMap) {
|
|
110
|
+
for (const module in meta.wxsContentMap) {
|
|
111
|
+
wxsContentMap[`${rawResourcePath}~${module}`] = meta.wxsContentMap[module]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const eventReg = /^@[a-zA-Z]+/
|
|
115
|
+
let isFindRoot = false
|
|
116
|
+
const componentNames = [] // 记录引用多少个组件
|
|
117
|
+
const localComponentsTags = []
|
|
118
|
+
function serialize (root) {
|
|
119
|
+
function walk (node, discardProp) {
|
|
120
|
+
let result = ''
|
|
121
|
+
if (node) {
|
|
122
|
+
if (node.type === 3) {
|
|
123
|
+
if (node.isComment) {
|
|
124
|
+
result += '<!--' + node.text + '-->'
|
|
125
|
+
} else {
|
|
126
|
+
const text = getTextVarName(node.text, discardProp) || []
|
|
127
|
+
props.push(...text)
|
|
128
|
+
result += node.text
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (node.type === 1) {
|
|
132
|
+
if (node.tag === 'wxs' || node.tag === 'import') { // wxml文件里不支持import wxs后续支持
|
|
133
|
+
return ''
|
|
134
|
+
} else if (node.tag !== 'temp-node') {
|
|
135
|
+
if (node.tag === 'component') { // 提前处理component上的bind逻辑,确保传入_data_v_id
|
|
136
|
+
if (!node.attrsMap['v-bind']) {
|
|
137
|
+
node.attrsList.push({
|
|
138
|
+
name: 'v-bind',
|
|
139
|
+
value: '{_data_v_id}'
|
|
140
|
+
})
|
|
141
|
+
} else {
|
|
142
|
+
node.attrsList.forEach(function (attr) {
|
|
143
|
+
if (attr.name === 'v-bind') {
|
|
144
|
+
attr.value = attr.value.replace('}', ', _data_v_id}')
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (node.tag === 'template' && !node._fakeTemplate) {
|
|
150
|
+
if (node.attrsMap.name) { // template name处理逻辑
|
|
151
|
+
if (isFindRoot) {
|
|
152
|
+
componentNames.push(node.attrsMap.name)
|
|
153
|
+
return ''
|
|
154
|
+
}
|
|
155
|
+
isFindRoot = true
|
|
156
|
+
result += '<' + node.tag
|
|
157
|
+
} else { // 其他template逻辑全部丢弃
|
|
158
|
+
return ''
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
const { isBuildInTag, isOriginTag } = domTagConfig
|
|
162
|
+
if (!isBuildInTag(node.tag) && !isOriginTag(node.tag)) {
|
|
163
|
+
localComponentsTags.push(node.tag)
|
|
164
|
+
}
|
|
165
|
+
result += '<' + node.tag
|
|
166
|
+
const tagProps = []
|
|
167
|
+
addDiscardProp(node.attrsList, discardProp)
|
|
168
|
+
node.attrsList.forEach(function (attr) {
|
|
169
|
+
if (attr.name === ':class') {
|
|
170
|
+
if (attr.value.trim().startsWith('[') && attr.value.trim().endsWith(']')) { // 数组情况下_data_v_id直接插在最后面
|
|
171
|
+
attr.value = attr.value.replace(']', ', _data_v_id]')
|
|
172
|
+
} else if (attr.value) {
|
|
173
|
+
attr.value = `[${attr.value}, _data_v_id]` // 非数组情况下包装成数组后_data_v_id直接插在最后面
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const value = attr.value
|
|
177
|
+
if (eventReg.exec(attr.name)) { // 事件
|
|
178
|
+
const result = getEventName(attr.value)
|
|
179
|
+
tagProps.push(...result)
|
|
180
|
+
} else { // 属性
|
|
181
|
+
const result = getRefVarNames(value, discardProp)
|
|
182
|
+
tagProps.push(...result)
|
|
183
|
+
}
|
|
184
|
+
result += ' ' + attr.name
|
|
185
|
+
if (value != null) {
|
|
186
|
+
result += '=' + templateCompiler.stringifyAttr(value)
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
props.push(...tagProps)
|
|
190
|
+
}
|
|
191
|
+
if (node.unary) {
|
|
192
|
+
result += '/>'
|
|
193
|
+
} else {
|
|
194
|
+
result += '>'
|
|
195
|
+
node.children.forEach(function (child) {
|
|
196
|
+
result += walk(child, discardProp)
|
|
197
|
+
})
|
|
198
|
+
result += '</' + node.tag + '>'
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
node.children.forEach(function (child) {
|
|
202
|
+
result += walk(child, discardProp)
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
discardProp.splice(2) // 清理掉本次循环记录的数据避免污染其他同级的props判断
|
|
208
|
+
return result
|
|
209
|
+
}
|
|
210
|
+
return walk(root, ['true', 'false'])
|
|
211
|
+
}
|
|
212
|
+
const tempCompMaps = []
|
|
213
|
+
const path = this.resourcePath || ''
|
|
214
|
+
const template = serialize(root)
|
|
215
|
+
componentNames.forEach((item) => {
|
|
216
|
+
tempCompMaps[item] = {
|
|
217
|
+
resource: `${path.replace(query.is, item)}?is=${item}&isTemplate`
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const localComponentsMap = {}
|
|
222
|
+
localComponentsTags.forEach((item) => { // 做一次过滤避免不必要的自定义组件加载
|
|
223
|
+
if (parentLocalComponentsMap[item]) {
|
|
224
|
+
localComponentsMap[item] = parentLocalComponentsMap[item]
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
const componentsMap = buildComponentsMap({ localComponentsMap, builtInComponentsMap, loaderContext: this, jsonConfig: {} })
|
|
228
|
+
let script = `\n<script>\n
|
|
229
|
+
import proxyEventMixin from '@mpxjs/core/src/platform/builtInMixins/proxyEventMixin.web.js'
|
|
230
|
+
import MpxProxy from '@mpxjs/core/src/core/proxy.js'
|
|
231
|
+
const {getComponent} = require(${stringifyRequest(this, optionProcessorPath)})\n`
|
|
232
|
+
script += 'const templateModules = {}\n'
|
|
233
|
+
meta.templateSrcList?.forEach((item) => {
|
|
234
|
+
script += `
|
|
235
|
+
const tempLoaderResult = require(${stringifyRequest(this, `!!${wxmlTemplateLoader}!${item}`)})\n
|
|
236
|
+
Object.assign(templateModules, tempLoaderResult)\n`
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
// 注入wxs模块
|
|
240
|
+
const wxsModuleMap = meta.wxsModuleMap
|
|
241
|
+
script += ' var wxsModules = {}\n'
|
|
242
|
+
const finalProp = [...(new Set(props))]
|
|
243
|
+
if (wxsModuleMap) {
|
|
244
|
+
Object.keys(wxsModuleMap).forEach((module) => {
|
|
245
|
+
const src = loaderUtils.urlToRequest(wxsModuleMap[module], projectRoot)
|
|
246
|
+
const expression = `require(${stringifyRequest(this, src)})`
|
|
247
|
+
const index = finalProp.indexOf(module)
|
|
248
|
+
if (index > -1) { // 干掉模版中收集的wxs的字段
|
|
249
|
+
finalProp.splice(index, 1)
|
|
250
|
+
}
|
|
251
|
+
script += ` wxsModules.${module} = ${expression}\n`
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
script += `export default {
|
|
255
|
+
name: '${query.is}',
|
|
256
|
+
props: ${JSON.stringify(finalProp)},
|
|
257
|
+
mixins: [proxyEventMixin()],
|
|
258
|
+
beforeCreate () {
|
|
259
|
+
this.__mpxProxy = new MpxProxy({}, this, true)
|
|
260
|
+
this.__mpxProxy.created()
|
|
261
|
+
Object.keys(wxsModules).forEach((key) => {
|
|
262
|
+
if (key in this) {
|
|
263
|
+
console.error('[Mpx runtime error]: The wxs module key ['+key+'}] exist in the component/page instance already, please check and rename it!')
|
|
264
|
+
} else {
|
|
265
|
+
this[key] = wxsModules[key]
|
|
266
|
+
}
|
|
267
|
+
})
|
|
268
|
+
},
|
|
269
|
+
components: Object.assign(${shallowStringify(componentsMap)}, templateModules),
|
|
270
|
+
}
|
|
271
|
+
</script>`
|
|
272
|
+
const text = template + script
|
|
273
|
+
if (query.type === 'template') {
|
|
274
|
+
return template
|
|
275
|
+
} else if (query.type === 'script') {
|
|
276
|
+
return script
|
|
277
|
+
} else {
|
|
278
|
+
return text
|
|
279
|
+
}
|
|
280
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const normalize = require('@mpxjs/webpack-plugin/lib/utils/normalize')
|
|
2
|
+
const optionProcessorPath = normalize.lib('runtime/optionProcessor')
|
|
3
|
+
const shallowStringify = require('../utils/shallow-stringify')
|
|
4
|
+
const getTemplateContent = require('../utils/get-template-content')
|
|
5
|
+
const { stringifyRequest } = require('@mpxjs/webpack-plugin/lib/web/script-helper')
|
|
6
|
+
const WriteVfsDependency = require('../dependencies/WriteVfsDependency')
|
|
7
|
+
|
|
8
|
+
module.exports = function (content) {
|
|
9
|
+
const regex = /<template[^>]*\sname\s*=\s*"([^"]*)"[^>]*>/g
|
|
10
|
+
const mpx = this.getMpx()
|
|
11
|
+
let match
|
|
12
|
+
const templateNames = []
|
|
13
|
+
|
|
14
|
+
while ((match = regex.exec(content)) !== null) {
|
|
15
|
+
templateNames.push(match[1])
|
|
16
|
+
}
|
|
17
|
+
const templateMaps = {}
|
|
18
|
+
templateNames.forEach((name, index) => {
|
|
19
|
+
const cutContent = getTemplateContent(content, name)
|
|
20
|
+
const resourcePath = this.resourcePath.replace(/.wxml$/, `-${name}.wxml`)
|
|
21
|
+
this._module.addPresentationalDependency(new WriteVfsDependency(resourcePath, cutContent))
|
|
22
|
+
mpx.__vfs.writeModule(resourcePath, cutContent)
|
|
23
|
+
templateMaps[name] = `getComponent(require(${stringifyRequest(this, `${resourcePath}?is=${name}&localComponentsMap=${encodeURIComponent(JSON.stringify(mpx.parentLocalComponentsMap))}&isTemplate`)}))` // template2vue是在外部配置没办法拿到parentLocalComponentsMap,所以通过query传递
|
|
24
|
+
})
|
|
25
|
+
return `
|
|
26
|
+
const {getComponent} = require(${stringifyRequest(this, optionProcessorPath)})\n
|
|
27
|
+
module.exports = ${shallowStringify(templateMaps)}
|
|
28
|
+
`
|
|
29
|
+
}
|