@mpxjs/webpack-plugin 2.10.19 → 2.10.21
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/ResolveDependency.js +2 -2
- package/lib/index.js +38 -7
- package/lib/json-compiler/helper.js +11 -10
- package/lib/json-compiler/index.js +7 -4
- package/lib/json-compiler/plugin.js +4 -4
- package/lib/loader.js +4 -4
- package/lib/native-loader.js +4 -4
- package/lib/parser.js +1 -1
- package/lib/platform/create-diagnostic.js +168 -0
- package/lib/platform/index.js +16 -3
- package/lib/platform/json/wx/index.js +66 -17
- package/lib/platform/run-rules.js +9 -5
- package/lib/platform/style/wx/index.js +82 -33
- package/lib/platform/template/normalize-component-rules.js +7 -9
- package/lib/platform/template/wx/component-config/block.js +2 -1
- package/lib/platform/template/wx/component-config/custom-built-in-component.js +34 -0
- package/lib/platform/template/wx/component-config/index.js +18 -3
- package/lib/platform/template/wx/component-config/input.js +1 -7
- package/lib/platform/template/wx/component-config/movable-view.js +1 -7
- package/lib/platform/template/wx/component-config/text.js +1 -1
- package/lib/platform/template/wx/component-config/textarea.js +1 -25
- package/lib/platform/template/wx/component-config/unsupported.js +1 -1
- package/lib/platform/template/wx/index.js +48 -34
- package/lib/react/processJSON.js +7 -4
- package/lib/react/processStyles.js +22 -8
- package/lib/react/processTemplate.js +98 -41
- package/lib/react/style-helper.js +121 -86
- package/lib/react/template-loader.js +161 -0
- package/lib/runtime/components/react/context.ts +8 -1
- package/lib/runtime/components/react/dist/context.d.ts +6 -1
- package/lib/runtime/components/react/dist/context.js +1 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +1 -0
- package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-button.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-button.jsx +6 -5
- package/lib/runtime/components/react/dist/mpx-camera.jsx +1 -0
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +4 -1
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +2 -1
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +6 -4
- package/lib/runtime/components/react/dist/mpx-form.jsx +3 -3
- package/lib/runtime/components/react/dist/mpx-icon/index.jsx +5 -1
- package/lib/runtime/components/react/dist/mpx-image.d.ts +3 -3
- package/lib/runtime/components/react/dist/mpx-image.jsx +45 -12
- package/lib/runtime/components/react/dist/mpx-inline-text.jsx +10 -6
- package/lib/runtime/components/react/dist/mpx-input.jsx +17 -4
- package/lib/runtime/components/react/dist/mpx-label.jsx +6 -4
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +19 -4
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +12 -2
- package/lib/runtime/components/react/dist/mpx-picker/type.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +7 -4
- package/lib/runtime/components/react/dist/mpx-portal/index.jsx +5 -1
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +4 -1
- package/lib/runtime/components/react/dist/mpx-radio.jsx +5 -4
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +3 -1
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +13 -4
- package/lib/runtime/components/react/dist/mpx-simple-text.jsx +52 -6
- package/lib/runtime/components/react/dist/mpx-simple-view.jsx +36 -6
- package/lib/runtime/components/react/dist/mpx-slider.jsx +2 -1
- package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +8 -4
- package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +6 -4
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +7 -4
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +15 -4
- package/lib/runtime/components/react/dist/mpx-switch.jsx +4 -1
- package/lib/runtime/components/react/dist/mpx-text.jsx +57 -12
- package/lib/runtime/components/react/dist/mpx-video.d.ts +2 -1
- package/lib/runtime/components/react/dist/mpx-video.jsx +10 -4
- package/lib/runtime/components/react/dist/mpx-view.jsx +42 -7
- package/lib/runtime/components/react/dist/utils.d.ts +21 -11
- package/lib/runtime/components/react/dist/utils.jsx +105 -35
- package/lib/runtime/components/react/getInnerListeners.ts +1 -0
- package/lib/runtime/components/react/mpx-async-suspense.tsx +2 -1
- package/lib/runtime/components/react/mpx-button.tsx +6 -5
- package/lib/runtime/components/react/mpx-camera.tsx +1 -0
- package/lib/runtime/components/react/mpx-canvas/index.tsx +4 -1
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +2 -1
- package/lib/runtime/components/react/mpx-checkbox.tsx +6 -4
- package/lib/runtime/components/react/mpx-form.tsx +3 -3
- package/lib/runtime/components/react/mpx-icon/index.tsx +5 -1
- package/lib/runtime/components/react/mpx-image.tsx +57 -20
- package/lib/runtime/components/react/mpx-inline-text.tsx +12 -7
- package/lib/runtime/components/react/mpx-input.tsx +17 -4
- package/lib/runtime/components/react/mpx-label.tsx +6 -4
- package/lib/runtime/components/react/mpx-movable-view.tsx +20 -4
- package/lib/runtime/components/react/mpx-picker/index.tsx +12 -2
- package/lib/runtime/components/react/mpx-picker/type.ts +1 -1
- package/lib/runtime/components/react/mpx-picker-view/index.tsx +8 -4
- package/lib/runtime/components/react/mpx-portal/index.tsx +5 -1
- package/lib/runtime/components/react/mpx-radio-group.tsx +4 -1
- package/lib/runtime/components/react/mpx-radio.tsx +5 -4
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +3 -1
- package/lib/runtime/components/react/mpx-scroll-view.tsx +13 -4
- package/lib/runtime/components/react/mpx-simple-text.tsx +55 -8
- package/lib/runtime/components/react/mpx-simple-view.tsx +30 -6
- package/lib/runtime/components/react/mpx-slider.tsx +2 -1
- package/lib/runtime/components/react/mpx-sticky-header.tsx +8 -4
- package/lib/runtime/components/react/mpx-sticky-section.tsx +6 -4
- package/lib/runtime/components/react/mpx-swiper-item.tsx +7 -4
- package/lib/runtime/components/react/mpx-swiper.tsx +16 -4
- package/lib/runtime/components/react/mpx-switch.tsx +4 -1
- package/lib/runtime/components/react/mpx-text.tsx +55 -15
- package/lib/runtime/components/react/mpx-video.tsx +11 -5
- package/lib/runtime/components/react/mpx-view.tsx +35 -7
- package/lib/runtime/components/react/types/global.d.ts +4 -0
- package/lib/runtime/components/react/utils.tsx +126 -45
- package/lib/runtime/components/wx/default-component.mpx +9 -0
- package/lib/runtime/components/wx/default-page.mpx +3 -11
- package/lib/runtime/optionProcessor.d.ts +2 -0
- package/lib/runtime/optionProcessor.js +77 -1
- package/lib/runtime/optionProcessorReact.js +5 -0
- package/lib/script-setup-compiler/index.js +1 -1
- package/lib/style-compiler/index.js +2 -0
- package/lib/style-compiler/plugins/remove-strip-conditional-comments.js +14 -0
- package/lib/style-compiler/plugins/trans-special.js +1 -1
- package/lib/style-compiler/strip-conditional.js +40 -26
- package/lib/template-compiler/compiler.js +306 -125
- package/lib/template-compiler/gen-node-react.js +35 -7
- package/lib/template-compiler/index.js +9 -7
- package/lib/utils/const.js +4 -1
- package/lib/utils/gen-component-tag.js +1 -5
- package/lib/utils/normalize-perf-options.js +47 -0
- package/lib/utils/partial-compile-rules.js +27 -0
- package/lib/utils/pre-process-json.js +3 -0
- package/lib/utils/source-location.js +96 -0
- package/lib/web/compile-wx-template-fragment.js +68 -0
- package/lib/web/index.js +3 -0
- package/lib/web/processJSON.js +7 -4
- package/lib/web/processMainScript.js +3 -7
- package/lib/web/processScript.js +43 -8
- package/lib/web/processStyles.js +12 -3
- package/lib/web/processTemplate.js +61 -19
- package/lib/web/template-loader.js +123 -0
- package/lib/web/template-shared.js +48 -0
- package/lib/wxml/loader.js +4 -3
- package/lib/wxss/loader.js +1 -1
- package/lib/wxss/utils.js +6 -4
- package/package.json +12 -4
- package/lib/platform/template/wx/component-config/component.js +0 -41
|
@@ -31,7 +31,24 @@ function mapAttrName (name) {
|
|
|
31
31
|
return name
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
function genTemplate (node) {
|
|
35
|
+
if (!node.children || !node.children.length) return 'function(){}'
|
|
36
|
+
const children = node.children.map(child => genNode(child)).filter(c => c)
|
|
37
|
+
if (!children.length) return 'function(){}'
|
|
38
|
+
|
|
39
|
+
let content
|
|
40
|
+
if (children.length === 1) {
|
|
41
|
+
content = children[0]
|
|
42
|
+
} else {
|
|
43
|
+
// 模版存在多个根节点时,使用 block 包裹
|
|
44
|
+
content = `createElement(getComponent("block"), null, ${children.join(', ')})`
|
|
45
|
+
}
|
|
46
|
+
// data 作为 this 传入,createElement, getComponent 作为参数传入
|
|
47
|
+
return `function(createElement, getComponent){return ${content}}`
|
|
48
|
+
}
|
|
49
|
+
|
|
34
50
|
function genNode (node, isRoot = false) {
|
|
51
|
+
if (node.isDeleted) return ''
|
|
35
52
|
let exp = ''
|
|
36
53
|
if (node) {
|
|
37
54
|
if (node.type === 3) {
|
|
@@ -46,11 +63,20 @@ function genNode (node, isRoot = false) {
|
|
|
46
63
|
if (node.type === 1) {
|
|
47
64
|
if (node.tag !== 'temp-node') {
|
|
48
65
|
if (node.for && !node.forProcessed) {
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
66
|
+
return genFor(node)
|
|
67
|
+
}
|
|
68
|
+
if (node.if && !node.ifProcessed) {
|
|
69
|
+
return genIf(node)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (node.tag === 'template') {
|
|
73
|
+
if (node.templateInfo) {
|
|
74
|
+
const data = node.templateInfo.data || '{}'
|
|
75
|
+
// 模版中需要支持宿主组件的事件响应,同时天然支持__iter/__getSlot等帮助函数,故使用Object.create(this)创建作用域
|
|
76
|
+
exp += `(typeof getTemplate === "function" && getTemplate(${node.templateInfo.is}) || function(){}).call(Object.assign(Object.create(this), ${data}), createElement, getComponent)`
|
|
77
|
+
}
|
|
78
|
+
} else if (node.tag !== 'temp-node') {
|
|
79
|
+
const attrExpMap = (node.exps || []).reduce((map, { exp, attrName }) => {
|
|
54
80
|
if (attrName) {
|
|
55
81
|
map[attrName] = exp
|
|
56
82
|
}
|
|
@@ -85,7 +111,6 @@ function genNode (node, isRoot = false) {
|
|
|
85
111
|
}
|
|
86
112
|
exp += ')'
|
|
87
113
|
}
|
|
88
|
-
}
|
|
89
114
|
} else {
|
|
90
115
|
const nodes = node.children.map((child) => {
|
|
91
116
|
return genNode(child)
|
|
@@ -102,4 +127,7 @@ function genNode (node, isRoot = false) {
|
|
|
102
127
|
return exp
|
|
103
128
|
}
|
|
104
129
|
|
|
105
|
-
module.exports =
|
|
130
|
+
module.exports = {
|
|
131
|
+
genNode,
|
|
132
|
+
genTemplate
|
|
133
|
+
}
|
|
@@ -33,6 +33,7 @@ module.exports = function (raw) {
|
|
|
33
33
|
const hasScoped = queryObj.hasScoped
|
|
34
34
|
const runtimeCompile = queryObj.isDynamic
|
|
35
35
|
const moduleId = queryObj.moduleId || mpx.getModuleId(resourcePath, false, queryObj.moduleId ? null : this)
|
|
36
|
+
const isStatic = queryObj.isStatic
|
|
36
37
|
|
|
37
38
|
let optimizeRenderLevel = 0
|
|
38
39
|
for (const rule of optimizeRenderRules) {
|
|
@@ -42,15 +43,15 @@ module.exports = function (raw) {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
const warn = (msg) => {
|
|
46
|
+
const warn = (msg, loc) => {
|
|
46
47
|
this.emitWarning(
|
|
47
|
-
new Error('[Mpx template warning][' + this.
|
|
48
|
+
new Error('[Mpx template warning][' + (loc || this.resourcePath) + ']: ' + msg)
|
|
48
49
|
)
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
const error = (msg) => {
|
|
52
|
+
const error = (msg, loc) => {
|
|
52
53
|
this.emitError(
|
|
53
|
-
new Error('[Mpx template error][' + this.
|
|
54
|
+
new Error('[Mpx template error][' + (loc || this.resourcePath) + ']: ' + msg)
|
|
54
55
|
)
|
|
55
56
|
}
|
|
56
57
|
|
|
@@ -75,10 +76,10 @@ module.exports = function (raw) {
|
|
|
75
76
|
// 这里需传递rawResourcePath和wxsContentMap保持一致
|
|
76
77
|
filePath: rawResourcePath,
|
|
77
78
|
i18n,
|
|
78
|
-
|
|
79
|
-
globalComponents: Object.keys(mpx.globalComponents),
|
|
79
|
+
globalComponents: Object.keys(mpx.globalComponents || {}),
|
|
80
80
|
forceProxyEvent: matchCondition(resourcePath, mpx.forceProxyEventRules) || runtimeCompile,
|
|
81
81
|
hasVirtualHost: matchCondition(resourcePath, mpx.autoVirtualHostRules),
|
|
82
|
+
checkUsingComponents: matchCondition(resourcePath, mpx.checkUsingComponentsRules),
|
|
82
83
|
dynamicTemplateRuleRunner: mpx.dynamicTemplateRuleRunner
|
|
83
84
|
})
|
|
84
85
|
|
|
@@ -89,7 +90,8 @@ module.exports = function (raw) {
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
let result = runtimeCompile ? '' : compiler.serialize(root)
|
|
92
|
-
if (isNative) {
|
|
93
|
+
if (isNative || isStatic) {
|
|
94
|
+
// 对于原生小程序组件和静态模版无需注入运行时信息,直接返回模版编译结果
|
|
93
95
|
return result
|
|
94
96
|
}
|
|
95
97
|
|
package/lib/utils/const.js
CHANGED
|
@@ -7,5 +7,8 @@ module.exports = {
|
|
|
7
7
|
MPX_ROOT_VIEW: 'mpx-root-view', // 根节点类名
|
|
8
8
|
MPX_APP_MODULE_ID: 'mpx-app-scope', // app文件moduleId
|
|
9
9
|
PARENT_MODULE_ID: '__pid',
|
|
10
|
-
MPX_TAG_PAGE_SELECTOR: 'mpx-page'
|
|
10
|
+
MPX_TAG_PAGE_SELECTOR: 'mpx-page',
|
|
11
|
+
// web / template is:具名 wx 模版子组件标签前缀(与 compiler 中 AST 替换一致)
|
|
12
|
+
MPX_TEMPLATE_COMPONENT_PREFIX: 'mpx-tpl-',
|
|
13
|
+
STYLE_PAD_PLACEHOLDER: 'mpx-style-pad-placeholder'
|
|
11
14
|
}
|
|
@@ -20,10 +20,6 @@ function genComponentTag (part, processor = {}) {
|
|
|
20
20
|
content: processor
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
if (part.content) {
|
|
24
|
-
// unpad
|
|
25
|
-
part.content = '\n' + part.content.replace(/^\n*/m, '')
|
|
26
|
-
}
|
|
27
23
|
|
|
28
24
|
const tag = processor.tag ? processor.tag(part) : part.tag
|
|
29
25
|
const attrs = processor.attrs ? processor.attrs(part) : part.attrs
|
|
@@ -35,7 +31,7 @@ function genComponentTag (part, processor = {}) {
|
|
|
35
31
|
result += stringifyAttrs(attrs)
|
|
36
32
|
}
|
|
37
33
|
if (content) {
|
|
38
|
-
result +=
|
|
34
|
+
result += `>\n${content}\n</${tag}>`
|
|
39
35
|
} else {
|
|
40
36
|
result += '/>'
|
|
41
37
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// 当前已知分组列表,未来新增分组扩这个数组 + 同步加 declare 即可。
|
|
4
|
+
// @mpxjs/perf 包零感知分组——分组逻辑只存在于 webpack-plugin 这一侧。
|
|
5
|
+
const PERF_GROUPS = ['framework', 'user']
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 把用户配置 { enable, probes } 归一化成「总开关 + 各分组开关」。
|
|
9
|
+
*
|
|
10
|
+
* 输出形如:
|
|
11
|
+
* { enable: true, framework: true, user: false }
|
|
12
|
+
*
|
|
13
|
+
* - `enable: false` 或不传 perf → 全关。
|
|
14
|
+
* - `enable: true && probes: []` → 等价于 enable: false(没有分组要开就视为关闭)。
|
|
15
|
+
* - probes 中出现未知分组名 → 抛错(避免 typo 静默失效)。
|
|
16
|
+
*/
|
|
17
|
+
function normalizePerfOptions (raw) {
|
|
18
|
+
if (!raw || raw.enable !== true) {
|
|
19
|
+
const off = { enable: false }
|
|
20
|
+
for (let i = 0; i < PERF_GROUPS.length; i++) off[PERF_GROUPS[i]] = false
|
|
21
|
+
return off
|
|
22
|
+
}
|
|
23
|
+
const probes = Array.isArray(raw.probes) ? raw.probes : []
|
|
24
|
+
for (let i = 0; i < probes.length; i++) {
|
|
25
|
+
if (PERF_GROUPS.indexOf(probes[i]) === -1) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`[mpx perf] unknown probe "${probes[i]}"; known probes: ${PERF_GROUPS.join(', ')}`
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const result = {}
|
|
32
|
+
let anyOn = false
|
|
33
|
+
for (let i = 0; i < PERF_GROUPS.length; i++) {
|
|
34
|
+
const k = PERF_GROUPS[i]
|
|
35
|
+
const on = probes.indexOf(k) !== -1
|
|
36
|
+
result[k] = on
|
|
37
|
+
if (on) anyOn = true
|
|
38
|
+
}
|
|
39
|
+
// 派生总开关:任一分组打开 → enable 才真正有效。
|
|
40
|
+
result.enable = anyOn
|
|
41
|
+
return result
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = {
|
|
45
|
+
PERF_GROUPS,
|
|
46
|
+
normalizePerfOptions
|
|
47
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const { matchCondition } = require('./match-condition')
|
|
2
|
+
|
|
3
|
+
const hasTypedRules = rules => !!(rules && (rules.pages || rules.page || rules.components || rules.component))
|
|
4
|
+
|
|
5
|
+
const getPartialCompileRules = (rules, type) => {
|
|
6
|
+
if (!rules) return null
|
|
7
|
+
|
|
8
|
+
if (type === 'page') {
|
|
9
|
+
return rules.pages || rules.page || (hasTypedRules(rules) ? null : rules)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (type === 'component') {
|
|
13
|
+
return rules.components || rules.component || null
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const isPartialCompileExcluded = (resourcePath, rules, type) => {
|
|
20
|
+
const targetRules = getPartialCompileRules(rules, type)
|
|
21
|
+
return !!(targetRules && !matchCondition(resourcePath, targetRules))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
getPartialCompileRules,
|
|
26
|
+
isPartialCompileExcluded
|
|
27
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const { codeFrameColumns } = require('@babel/code-frame')
|
|
3
|
+
const { SourceMapConsumer } = require('source-map')
|
|
4
|
+
|
|
5
|
+
function offsetToPosition (source, offset) {
|
|
6
|
+
const before = source.slice(0, offset)
|
|
7
|
+
const lines = before.split(/\r\n|\r|\n/)
|
|
8
|
+
return {
|
|
9
|
+
line: lines.length,
|
|
10
|
+
column: lines[lines.length - 1].length + 1
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function offsetToLoc (source, start, end) {
|
|
15
|
+
const loc = {
|
|
16
|
+
start: offsetToPosition(source, start)
|
|
17
|
+
}
|
|
18
|
+
if (end != null) {
|
|
19
|
+
loc.end = offsetToPosition(source, end)
|
|
20
|
+
}
|
|
21
|
+
return loc
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function normalizeLoc (loc) {
|
|
25
|
+
if (!loc) return
|
|
26
|
+
if (loc.start) return loc
|
|
27
|
+
if (loc.line) {
|
|
28
|
+
return {
|
|
29
|
+
start: {
|
|
30
|
+
line: loc.line,
|
|
31
|
+
column: loc.column || 1
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function createCodeFrame (source, loc) {
|
|
38
|
+
loc = normalizeLoc(loc)
|
|
39
|
+
if (!source || !loc || !loc.start) return ''
|
|
40
|
+
return codeFrameColumns(source, loc, {
|
|
41
|
+
highlightCode: false
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function originalPositionFor (map, loc) {
|
|
46
|
+
loc = normalizeLoc(loc)
|
|
47
|
+
if (!map || !loc || !loc.start) return
|
|
48
|
+
if (typeof map === 'string') {
|
|
49
|
+
try {
|
|
50
|
+
map = JSON.parse(map)
|
|
51
|
+
} catch (e) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
let consumer
|
|
56
|
+
try {
|
|
57
|
+
consumer = new SourceMapConsumer(map)
|
|
58
|
+
} catch (e) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
const original = consumer.originalPositionFor({
|
|
62
|
+
line: loc.start.line,
|
|
63
|
+
column: Math.max((loc.start.column || 1) - 1, 0)
|
|
64
|
+
})
|
|
65
|
+
if (!original || !original.source || !original.line) return
|
|
66
|
+
const sourceIndex = map.sources && map.sources.indexOf(original.source)
|
|
67
|
+
return {
|
|
68
|
+
file: original.source,
|
|
69
|
+
loc: {
|
|
70
|
+
start: {
|
|
71
|
+
line: original.line,
|
|
72
|
+
column: (original.column || 0) + 1
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
source: sourceIndex > -1 && map.sourcesContent && map.sourcesContent[sourceIndex],
|
|
76
|
+
generatedLoc: loc
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function readSource (file, inputFileSystem) {
|
|
81
|
+
if (!file || !inputFileSystem) return ''
|
|
82
|
+
try {
|
|
83
|
+
return inputFileSystem.readFileSync(path.resolve(file), 'utf-8')
|
|
84
|
+
} catch (e) {
|
|
85
|
+
return ''
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = {
|
|
90
|
+
offsetToPosition,
|
|
91
|
+
offsetToLoc,
|
|
92
|
+
normalizeLoc,
|
|
93
|
+
createCodeFrame,
|
|
94
|
+
originalPositionFor,
|
|
95
|
+
readSource
|
|
96
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 将 serialize 得到的 **wxml template** 定义片段(单根 HTML)在构建期编译为 Vue 2.7 render / staticRenderFns。
|
|
3
|
+
* 与业务依赖的 `vue` 包对齐:使用 `vue/compiler-sfc` 的 `compileTemplate`(同 vue-loader / @vue/compiler-sfc 与 runtime 配对),运行期仅需 `vue.runtime`。
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const path = require('path')
|
|
7
|
+
|
|
8
|
+
function tryRequireVueCompilerSfc () {
|
|
9
|
+
try {
|
|
10
|
+
return require('vue/compiler-sfc')
|
|
11
|
+
} catch (e) {
|
|
12
|
+
try {
|
|
13
|
+
const vueRoot = path.dirname(require.resolve('vue/package.json'))
|
|
14
|
+
return require(path.join(vueRoot, 'compiler-sfc'))
|
|
15
|
+
} catch (e2) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
'[Mpx] Failed to load vue/compiler-sfc. Install vue@^2.7 (same version as your app, e.g. 2.7.16) for Web wxml template compilation.'
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function normalizeCompileErrors (errors) {
|
|
24
|
+
if (!errors || !errors.length) return ''
|
|
25
|
+
return errors.map((e) => (typeof e === 'string' ? e : (e && e.msg) || String(e))).join('\n')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {string} source 单根片段(与 serializeWxTemplateDefinition 输出一致,对应 wxml 侧 `<template name="…">` 体)
|
|
30
|
+
* @param {{ emitError?: (msg: string) => void, definitionName?: string, resourcePath?: string, isProduction?: boolean }} ctx
|
|
31
|
+
* @returns {{ block: string }} `block` 为含 `var render` / `var staticRenderFns` 的脚本片段(与 compileTemplate 的 `code` 一致)
|
|
32
|
+
*/
|
|
33
|
+
function compileTemplateFragment (source, ctx) {
|
|
34
|
+
const { compileTemplate } = tryRequireVueCompilerSfc()
|
|
35
|
+
const filename = ctx.resourcePath || `wxml-template-${ctx.definitionName || 'anon'}.html`
|
|
36
|
+
const result = compileTemplate({
|
|
37
|
+
source,
|
|
38
|
+
filename,
|
|
39
|
+
isProduction: ctx.isProduction
|
|
40
|
+
})
|
|
41
|
+
const where = ctx.definitionName
|
|
42
|
+
? `wxml template "${ctx.definitionName}"`
|
|
43
|
+
: (ctx.resourcePath || 'wxml template fragment')
|
|
44
|
+
if (result.errors && result.errors.length) {
|
|
45
|
+
const msg = normalizeCompileErrors(result.errors)
|
|
46
|
+
const full = `Web ${where} compile error: ${msg}`
|
|
47
|
+
if (ctx.emitError) ctx.emitError(full)
|
|
48
|
+
throw new Error(full)
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
block: result.code
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 用 compileTemplate 产出的 `block` 包一层 IIFE,再调用 createTemplateComponent(block 内已声明 `render` / `staticRenderFns`)。
|
|
57
|
+
* 用于将 wxml template 的 Web 侧子组件选项与宿主 `createTemplateComponent` 对接。
|
|
58
|
+
* @param {string} block compileTemplate 返回的 `code`
|
|
59
|
+
* @param {string} innerOptionProps createTemplateComponent 除 render/staticRenderFns 外的选项片段,例如 `name: "x", components: ...`
|
|
60
|
+
*/
|
|
61
|
+
function wrapCreateTemplateComponentWithBlock (block, innerOptionProps) {
|
|
62
|
+
return `(function () {\n${block}\n return createTemplateComponent({ render, staticRenderFns, ${innerOptionProps} })\n})()`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
module.exports = {
|
|
66
|
+
compileTemplateFragment,
|
|
67
|
+
wrapCreateTemplateComponentWithBlock
|
|
68
|
+
}
|
package/lib/web/index.js
CHANGED
|
@@ -77,6 +77,7 @@ module.exports = function ({
|
|
|
77
77
|
},
|
|
78
78
|
(callback) => {
|
|
79
79
|
processStyles(parts.styles, {
|
|
80
|
+
loaderContext,
|
|
80
81
|
ctorType,
|
|
81
82
|
autoScope,
|
|
82
83
|
moduleId
|
|
@@ -103,6 +104,7 @@ module.exports = function ({
|
|
|
103
104
|
ctorType,
|
|
104
105
|
srcMode,
|
|
105
106
|
moduleId,
|
|
107
|
+
hasScoped,
|
|
106
108
|
isProduction,
|
|
107
109
|
componentGenerics,
|
|
108
110
|
jsonConfig: jsonRes.jsonObj,
|
|
@@ -110,6 +112,7 @@ module.exports = function ({
|
|
|
110
112
|
builtInComponentsMap: templateRes.builtInComponentsMap,
|
|
111
113
|
genericsInfo: templateRes.genericsInfo,
|
|
112
114
|
wxsModuleMap: templateRes.wxsModuleMap,
|
|
115
|
+
wxTemplateComponentsInfo: templateRes.wxTemplateComponentsInfo,
|
|
113
116
|
localComponentsMap: jsonRes.localComponentsMap
|
|
114
117
|
}, callback)
|
|
115
118
|
}
|
package/lib/web/processJSON.js
CHANGED
|
@@ -35,15 +35,15 @@ module.exports = function (jsonContent, {
|
|
|
35
35
|
|
|
36
36
|
const context = loaderContext.context
|
|
37
37
|
|
|
38
|
-
const emitWarning = (msg) => {
|
|
38
|
+
const emitWarning = (msg, loc) => {
|
|
39
39
|
loaderContext.emitWarning(
|
|
40
|
-
new Error('[Mpx json warning][' + loaderContext.
|
|
40
|
+
new Error('[Mpx json warning][' + (loc || loaderContext.resourcePath) + ']: ' + msg)
|
|
41
41
|
)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const emitError = (msg) => {
|
|
44
|
+
const emitError = (msg, loc) => {
|
|
45
45
|
loaderContext.emitError(
|
|
46
|
-
new Error('[Mpx json error][' + loaderContext.
|
|
46
|
+
new Error('[Mpx json error][' + (loc || loaderContext.resourcePath) + ']: ' + msg)
|
|
47
47
|
)
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -107,6 +107,9 @@ module.exports = function (jsonContent, {
|
|
|
107
107
|
waterfall: true,
|
|
108
108
|
warn: emitWarning,
|
|
109
109
|
error: emitError,
|
|
110
|
+
diagnostic: {
|
|
111
|
+
file: loaderContext.resourcePath
|
|
112
|
+
},
|
|
110
113
|
data: {
|
|
111
114
|
// polyfill global usingComponents
|
|
112
115
|
globalComponents: mpx.globalComponents
|
|
@@ -21,7 +21,7 @@ module.exports = function ({
|
|
|
21
21
|
tabBarStr,
|
|
22
22
|
localPagesMap
|
|
23
23
|
}, callback) {
|
|
24
|
-
const { i18n, webConfig
|
|
24
|
+
const { i18n, webConfig } = loaderContext.getMpx()
|
|
25
25
|
const { pagesMap, firstPage, globalTabBar } = buildPagesMap({
|
|
26
26
|
localPagesMap,
|
|
27
27
|
loaderContext,
|
|
@@ -37,12 +37,8 @@ module.exports = function ({
|
|
|
37
37
|
jsonConfig
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
-
let output =
|
|
41
|
-
|
|
42
|
-
if (hasUnoCSS) {
|
|
43
|
-
output += 'import \'uno.css\'\n'
|
|
44
|
-
}
|
|
45
|
-
output += `import Vue from 'vue'
|
|
40
|
+
let output = `import '@mpxjs/webpack-plugin/lib/runtime/base.styl'
|
|
41
|
+
import Vue from 'vue'
|
|
46
42
|
import VueRouter from 'vue-router'
|
|
47
43
|
import Mpx from '@mpxjs/core'
|
|
48
44
|
import { processAppOption, getComponent } from ${stringifyRequest(loaderContext, optionProcessorPath)}
|
package/lib/web/processScript.js
CHANGED
|
@@ -10,12 +10,14 @@ const {
|
|
|
10
10
|
stringifyRequest,
|
|
11
11
|
buildI18n
|
|
12
12
|
} = require('./script-helper')
|
|
13
|
+
const { compileTemplateFragment, wrapCreateTemplateComponentWithBlock } = require('./compile-wx-template-fragment')
|
|
13
14
|
|
|
14
15
|
module.exports = function (script, {
|
|
15
16
|
loaderContext,
|
|
16
17
|
ctorType,
|
|
17
18
|
srcMode,
|
|
18
19
|
moduleId,
|
|
20
|
+
hasScoped,
|
|
19
21
|
isProduction,
|
|
20
22
|
componentGenerics,
|
|
21
23
|
jsonConfig,
|
|
@@ -23,6 +25,7 @@ module.exports = function (script, {
|
|
|
23
25
|
builtInComponentsMap,
|
|
24
26
|
genericsInfo,
|
|
25
27
|
wxsModuleMap,
|
|
28
|
+
wxTemplateComponentsInfo,
|
|
26
29
|
localComponentsMap
|
|
27
30
|
}, callback) {
|
|
28
31
|
const { projectRoot, appInfo, webConfig, i18n } = loaderContext.getMpx()
|
|
@@ -46,12 +49,15 @@ module.exports = function (script, {
|
|
|
46
49
|
delete attrs.setup
|
|
47
50
|
return attrs
|
|
48
51
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
content (script) {
|
|
53
|
+
const isProduction = loaderContext.mode === 'production'
|
|
54
|
+
const hasWxTemplate = !!(wxTemplateComponentsInfo &&
|
|
55
|
+
((wxTemplateComponentsInfo.imports && wxTemplateComponentsInfo.imports.length) ||
|
|
56
|
+
(wxTemplateComponentsInfo.locals && wxTemplateComponentsInfo.locals.length)))
|
|
57
|
+
const optionProcessorImports = ['processComponentOption', 'getComponent', 'getWxsMixin']
|
|
58
|
+
if (hasWxTemplate) optionProcessorImports.push('createTemplateComponent')
|
|
59
|
+
let content = ` import { ${optionProcessorImports.join(', ')} } from ${stringifyRequest(loaderContext, optionProcessorPath)}\n`
|
|
60
|
+
const hasApp = !!appInfo.name
|
|
55
61
|
// 注入wxs模块
|
|
56
62
|
content += ' var wxsModules = {}\n'
|
|
57
63
|
if (wxsModuleMap) {
|
|
@@ -65,6 +71,30 @@ module.exports = function (script, {
|
|
|
65
71
|
// 获取组件集合
|
|
66
72
|
const componentsMap = buildComponentsMap({ localComponentsMap, builtInComponentsMap, loaderContext, jsonConfig })
|
|
67
73
|
|
|
74
|
+
// 注入 wx template 子组件(<template name> / <import src>)
|
|
75
|
+
let wxTemplateComponentsExpr = ''
|
|
76
|
+
if (hasWxTemplate) {
|
|
77
|
+
const parts = (wxTemplateComponentsInfo.imports || []).slice()
|
|
78
|
+
const localsExprs = (wxTemplateComponentsInfo.locals || []).map((local) => {
|
|
79
|
+
const emitError = (msg) => {
|
|
80
|
+
loaderContext.emitError(new Error('[Mpx template error][' + loaderContext.resource + ']: ' + msg))
|
|
81
|
+
}
|
|
82
|
+
const compiled = compileTemplateFragment(local.template, {
|
|
83
|
+
emitError,
|
|
84
|
+
definitionName: local.name,
|
|
85
|
+
resourcePath: loaderContext.resourcePath,
|
|
86
|
+
isProduction
|
|
87
|
+
})
|
|
88
|
+
const inner = `name: ${JSON.stringify(local.name)}`
|
|
89
|
+
return `${JSON.stringify(local.name)}: ${wrapCreateTemplateComponentWithBlock(compiled.block, inner)}`
|
|
90
|
+
})
|
|
91
|
+
if (localsExprs.length) {
|
|
92
|
+
parts.push(`{${localsExprs.join(',')}}`)
|
|
93
|
+
}
|
|
94
|
+
wxTemplateComponentsExpr = `Object.assign({}, ${parts.join(', ')})`
|
|
95
|
+
content += ` var wxTemplateComponentsMap = ${wxTemplateComponentsExpr}\n`
|
|
96
|
+
}
|
|
97
|
+
|
|
68
98
|
// 获取pageConfig
|
|
69
99
|
const pageConfig = {}
|
|
70
100
|
if (ctorType === 'page') {
|
|
@@ -77,20 +107,25 @@ module.exports = function (script, {
|
|
|
77
107
|
content += buildI18n({ i18n, loaderContext })
|
|
78
108
|
}
|
|
79
109
|
content += getRequireScript({ ctorType, script, loaderContext })
|
|
110
|
+
const componentsMapExpr = hasWxTemplate
|
|
111
|
+
? `Object.assign({}, ${shallowStringify(componentsMap)}, wxTemplateComponentsMap)`
|
|
112
|
+
: shallowStringify(componentsMap)
|
|
80
113
|
content += `
|
|
81
114
|
// @ts-ignore
|
|
82
115
|
export default processComponentOption({
|
|
83
116
|
option: global.__mpxOptionsMap[${JSON.stringify(moduleId)}],
|
|
84
117
|
ctorType: ${JSON.stringify(ctorType)},
|
|
118
|
+
moduleId: ${JSON.stringify(moduleId)},
|
|
119
|
+
hasScoped: ${JSON.stringify(!!hasScoped)},
|
|
85
120
|
outputPath: ${JSON.stringify(outputPath)},
|
|
86
121
|
pageConfig: ${JSON.stringify(pageConfig)},
|
|
87
|
-
componentsMap: ${
|
|
122
|
+
componentsMap: ${componentsMapExpr},
|
|
88
123
|
componentGenerics: ${JSON.stringify(componentGenerics)},
|
|
89
124
|
genericsInfo: ${JSON.stringify(genericsInfo)},
|
|
90
125
|
wxsMixin: getWxsMixin(wxsModules),
|
|
91
126
|
hasApp: ${hasApp},
|
|
92
127
|
disablePageTransition: ${JSON.stringify(disablePageTransition)},
|
|
93
|
-
})
|
|
128
|
+
})`
|
|
94
129
|
return content
|
|
95
130
|
}
|
|
96
131
|
})
|
package/lib/web/processStyles.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
const genComponentTag = require('../utils/gen-component-tag')
|
|
2
2
|
|
|
3
|
-
module.exports = function (styles,
|
|
3
|
+
module.exports = function (styles, { loaderContext, ctorType, autoScope, moduleId }, callback) {
|
|
4
4
|
let output = '/* styles */\n'
|
|
5
|
+
const { hasUnoCSS, appInfo } = loaderContext.getMpx()
|
|
6
|
+
const hasApp = !!appInfo.name
|
|
5
7
|
if (styles.length) {
|
|
6
8
|
styles.forEach((style) => {
|
|
7
9
|
output += genComponentTag(style, {
|
|
8
10
|
attrs (style) {
|
|
9
11
|
const attrs = Object.assign({}, style.attrs)
|
|
10
|
-
if (
|
|
12
|
+
if (autoScope) attrs.scoped = true
|
|
11
13
|
attrs.mpxStyleOptions = JSON.stringify({
|
|
12
14
|
scoped: attrs.scoped,
|
|
13
15
|
// query中包含module字符串会被新版vue-cli中的默认rules当做css-module处理
|
|
14
|
-
mid:
|
|
16
|
+
mid: moduleId
|
|
15
17
|
})
|
|
16
18
|
delete attrs.scoped
|
|
17
19
|
return attrs
|
|
@@ -19,6 +21,13 @@ module.exports = function (styles, options, callback) {
|
|
|
19
21
|
})
|
|
20
22
|
output += '\n'
|
|
21
23
|
})
|
|
24
|
+
}
|
|
25
|
+
if (hasUnoCSS && (ctorType === 'app' || !hasApp)) {
|
|
26
|
+
// 将unocss的引入放到App style之后,拉齐小程序中unocss覆盖全局样式的行为
|
|
27
|
+
output += genComponentTag({
|
|
28
|
+
tag: 'style',
|
|
29
|
+
content: '@import \'uno.css\';'
|
|
30
|
+
})
|
|
22
31
|
output += '\n'
|
|
23
32
|
}
|
|
24
33
|
callback(null, {
|