@mpxjs/webpack-plugin 2.10.18 → 2.10.20
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 +25 -6
- 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/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 +4 -3
- package/lib/platform/template/normalize-component-rules.js +7 -9
- package/lib/platform/template/wx/component-config/camera.js +12 -0
- 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 +85 -41
- package/lib/react/style-helper.js +120 -85
- package/lib/react/template-loader.js +148 -0
- package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-camera.d.ts +31 -0
- package/lib/runtime/components/react/dist/mpx-camera.jsx +270 -0
- package/lib/runtime/components/react/dist/mpx-image.d.ts +0 -1
- package/lib/runtime/components/react/dist/mpx-image.jsx +1 -2
- package/lib/runtime/components/react/dist/mpx-picker/type.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +92 -15
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +1 -1
- package/lib/runtime/components/react/dist/utils.jsx +3 -2
- package/lib/runtime/components/react/mpx-async-suspense.tsx +2 -1
- package/lib/runtime/components/react/mpx-camera.tsx +358 -0
- package/lib/runtime/components/react/mpx-image.tsx +1 -3
- package/lib/runtime/components/react/mpx-picker/type.ts +1 -1
- package/lib/runtime/components/react/mpx-scroll-view.tsx +106 -16
- package/lib/runtime/components/react/mpx-web-view.tsx +1 -1
- package/lib/runtime/components/react/utils.tsx +3 -2
- 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/style-compiler/index.js +2 -0
- package/lib/style-compiler/plugins/remove-strip-conditional-comments.js +14 -0
- package/lib/style-compiler/strip-conditional.js +40 -26
- package/lib/template-compiler/compiler.js +274 -116
- 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/dom-tag-config.js +1 -1
- 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 +2 -0
- package/lib/web/processJSON.js +7 -4
- package/lib/web/processScript.js +41 -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 +3 -2
- 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
|
}
|
|
@@ -91,7 +91,7 @@ const isBuildInReactTag = makeMap(
|
|
|
91
91
|
'mpx-movable-area,mpx-label,mpx-input,' +
|
|
92
92
|
'mpx-image,mpx-form,mpx-checkbox,mpx-checkbox-group,mpx-button,' +
|
|
93
93
|
'mpx-rich-text,mpx-picker-view-column,mpx-picker-view,mpx-picker,' +
|
|
94
|
-
'mpx-icon,mpx-canvas'
|
|
94
|
+
'mpx-icon,mpx-canvas,mpx-camera'
|
|
95
95
|
)
|
|
96
96
|
|
|
97
97
|
const isSpace = makeMap('ensp,emsp,nbsp')
|
|
@@ -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
|
@@ -103,6 +103,7 @@ module.exports = function ({
|
|
|
103
103
|
ctorType,
|
|
104
104
|
srcMode,
|
|
105
105
|
moduleId,
|
|
106
|
+
hasScoped,
|
|
106
107
|
isProduction,
|
|
107
108
|
componentGenerics,
|
|
108
109
|
jsonConfig: jsonRes.jsonObj,
|
|
@@ -110,6 +111,7 @@ module.exports = function ({
|
|
|
110
111
|
builtInComponentsMap: templateRes.builtInComponentsMap,
|
|
111
112
|
genericsInfo: templateRes.genericsInfo,
|
|
112
113
|
wxsModuleMap: templateRes.wxsModuleMap,
|
|
114
|
+
wxTemplateComponentsInfo: templateRes.wxTemplateComponentsInfo,
|
|
113
115
|
localComponentsMap: jsonRes.localComponentsMap
|
|
114
116
|
}, callback)
|
|
115
117
|
}
|
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
|
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,8 +49,14 @@ module.exports = function (script, {
|
|
|
46
49
|
delete attrs.setup
|
|
47
50
|
return attrs
|
|
48
51
|
},
|
|
49
|
-
|
|
50
|
-
|
|
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 = `\n import { ${optionProcessorImports.join(', ')} } from ${stringifyRequest(loaderContext, optionProcessorPath)}\n`
|
|
51
60
|
let hasApp = true
|
|
52
61
|
if (!appInfo.name) {
|
|
53
62
|
hasApp = false
|
|
@@ -65,6 +74,30 @@ module.exports = function (script, {
|
|
|
65
74
|
// 获取组件集合
|
|
66
75
|
const componentsMap = buildComponentsMap({ localComponentsMap, builtInComponentsMap, loaderContext, jsonConfig })
|
|
67
76
|
|
|
77
|
+
// 注入 wx template 子组件(<template name> / <import src>)
|
|
78
|
+
let wxTemplateComponentsExpr = ''
|
|
79
|
+
if (hasWxTemplate) {
|
|
80
|
+
const parts = (wxTemplateComponentsInfo.imports || []).slice()
|
|
81
|
+
const localsExprs = (wxTemplateComponentsInfo.locals || []).map((local) => {
|
|
82
|
+
const emitError = (msg) => {
|
|
83
|
+
loaderContext.emitError(new Error('[Mpx template error][' + loaderContext.resource + ']: ' + msg))
|
|
84
|
+
}
|
|
85
|
+
const compiled = compileTemplateFragment(local.template, {
|
|
86
|
+
emitError,
|
|
87
|
+
definitionName: local.name,
|
|
88
|
+
resourcePath: loaderContext.resourcePath,
|
|
89
|
+
isProduction
|
|
90
|
+
})
|
|
91
|
+
const inner = `name: ${JSON.stringify(local.name)}`
|
|
92
|
+
return `${JSON.stringify(local.name)}: ${wrapCreateTemplateComponentWithBlock(compiled.block, inner)}`
|
|
93
|
+
})
|
|
94
|
+
if (localsExprs.length) {
|
|
95
|
+
parts.push(`{${localsExprs.join(',')}}`)
|
|
96
|
+
}
|
|
97
|
+
wxTemplateComponentsExpr = `Object.assign({}, ${parts.join(', ')})`
|
|
98
|
+
content += ` var wxTemplateComponentsMap = ${wxTemplateComponentsExpr}\n`
|
|
99
|
+
}
|
|
100
|
+
|
|
68
101
|
// 获取pageConfig
|
|
69
102
|
const pageConfig = {}
|
|
70
103
|
if (ctorType === 'page') {
|
|
@@ -77,14 +110,19 @@ module.exports = function (script, {
|
|
|
77
110
|
content += buildI18n({ i18n, loaderContext })
|
|
78
111
|
}
|
|
79
112
|
content += getRequireScript({ ctorType, script, loaderContext })
|
|
113
|
+
const componentsMapExpr = hasWxTemplate
|
|
114
|
+
? `Object.assign({}, ${shallowStringify(componentsMap)}, wxTemplateComponentsMap)`
|
|
115
|
+
: shallowStringify(componentsMap)
|
|
80
116
|
content += `
|
|
81
117
|
// @ts-ignore
|
|
82
118
|
export default processComponentOption({
|
|
83
119
|
option: global.__mpxOptionsMap[${JSON.stringify(moduleId)}],
|
|
84
120
|
ctorType: ${JSON.stringify(ctorType)},
|
|
121
|
+
moduleId: ${JSON.stringify(moduleId)},
|
|
122
|
+
hasScoped: ${JSON.stringify(!!hasScoped)},
|
|
85
123
|
outputPath: ${JSON.stringify(outputPath)},
|
|
86
124
|
pageConfig: ${JSON.stringify(pageConfig)},
|
|
87
|
-
componentsMap: ${
|
|
125
|
+
componentsMap: ${componentsMapExpr},
|
|
88
126
|
componentGenerics: ${JSON.stringify(componentGenerics)},
|
|
89
127
|
genericsInfo: ${JSON.stringify(genericsInfo)},
|
|
90
128
|
wxsMixin: getWxsMixin(wxsModules),
|
|
@@ -3,6 +3,7 @@ const genComponentTag = require('../utils/gen-component-tag')
|
|
|
3
3
|
const addQuery = require('../utils/add-query')
|
|
4
4
|
const parseRequest = require('../utils/parse-request')
|
|
5
5
|
const { matchCondition } = require('../utils/match-condition')
|
|
6
|
+
const { getWxTemplateComponentName, serializeWxTemplateDefinition, buildWebTemplateImportMergeExpr } = require('./template-shared')
|
|
6
7
|
|
|
7
8
|
module.exports = function (template, {
|
|
8
9
|
loaderContext,
|
|
@@ -18,21 +19,24 @@ module.exports = function (template, {
|
|
|
18
19
|
}, callback) {
|
|
19
20
|
const mpx = loaderContext.getMpx()
|
|
20
21
|
const {
|
|
22
|
+
projectRoot,
|
|
21
23
|
mode,
|
|
22
24
|
env,
|
|
23
25
|
defs,
|
|
24
26
|
wxsContentMap,
|
|
25
27
|
decodeHTMLText,
|
|
26
28
|
externalClasses,
|
|
27
|
-
checkUsingComponents,
|
|
28
29
|
webConfig,
|
|
29
30
|
autoVirtualHostRules,
|
|
30
|
-
forceProxyEventRules
|
|
31
|
+
forceProxyEventRules,
|
|
32
|
+
checkUsingComponentsRules,
|
|
33
|
+
globalComponents
|
|
31
34
|
} = mpx
|
|
32
35
|
const { resourcePath, rawResourcePath } = parseRequest(loaderContext.resource)
|
|
33
36
|
const builtInComponentsMap = {}
|
|
34
37
|
|
|
35
38
|
let wxsModuleMap, genericsInfo
|
|
39
|
+
let wxTemplateComponentsInfo
|
|
36
40
|
let output = '/* template */\n'
|
|
37
41
|
|
|
38
42
|
if (ctorType === 'app') {
|
|
@@ -64,16 +68,17 @@ module.exports = function (template, {
|
|
|
64
68
|
}
|
|
65
69
|
if (template.content) {
|
|
66
70
|
const templateSrcMode = template.mode || srcMode
|
|
67
|
-
const warn = (msg) => {
|
|
71
|
+
const warn = (msg, loc) => {
|
|
68
72
|
loaderContext.emitWarning(
|
|
69
|
-
new Error('[Mpx template error][' + loaderContext.
|
|
73
|
+
new Error('[Mpx template error][' + (loc || loaderContext.resourcePath) + ']: ' + msg)
|
|
70
74
|
)
|
|
71
75
|
}
|
|
72
|
-
const error = (msg) => {
|
|
76
|
+
const error = (msg, loc) => {
|
|
73
77
|
loaderContext.emitError(
|
|
74
|
-
new Error('[Mpx template error][' + loaderContext.
|
|
78
|
+
new Error('[Mpx template error][' + (loc || loaderContext.resourcePath) + ']: ' + msg)
|
|
75
79
|
)
|
|
76
80
|
}
|
|
81
|
+
const hasVirtualHost = matchCondition(resourcePath, autoVirtualHostRules)
|
|
77
82
|
const { root, meta } = templateCompiler.parse(template.content, {
|
|
78
83
|
warn,
|
|
79
84
|
error,
|
|
@@ -92,13 +97,14 @@ module.exports = function (template, {
|
|
|
92
97
|
moduleId,
|
|
93
98
|
filePath: rawResourcePath,
|
|
94
99
|
i18n: null,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
globalComponents: [],
|
|
100
|
+
// 与 template-compiler/index 一致:usingComponentsInfo 已合并 globalComponentsInfo,此处白名单避免对仅 app 注册的组件误报「未使用」
|
|
101
|
+
globalComponents: Object.keys(globalComponents || {}),
|
|
98
102
|
// web模式下实现抽象组件
|
|
99
103
|
componentGenerics,
|
|
100
|
-
hasVirtualHost
|
|
101
|
-
forceProxyEvent: matchCondition(resourcePath, forceProxyEventRules)
|
|
104
|
+
hasVirtualHost,
|
|
105
|
+
forceProxyEvent: matchCondition(resourcePath, forceProxyEventRules),
|
|
106
|
+
checkUsingComponents: matchCondition(resourcePath, checkUsingComponentsRules),
|
|
107
|
+
customBuiltInComponents: webConfig && webConfig.customBuiltInComponents
|
|
102
108
|
})
|
|
103
109
|
if (meta.wxsModuleMap) {
|
|
104
110
|
wxsModuleMap = meta.wxsModuleMap
|
|
@@ -108,16 +114,51 @@ module.exports = function (template, {
|
|
|
108
114
|
wxsContentMap[`${rawResourcePath}~${module}`] = meta.wxsContentMap[module]
|
|
109
115
|
}
|
|
110
116
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
117
|
+
const builtInPaths = meta.builtInComponentsMap || {}
|
|
118
|
+
Object.keys(builtInPaths).forEach((name) => {
|
|
119
|
+
builtInComponentsMap[name] = {
|
|
120
|
+
resource: addQuery(builtInPaths[name], { isComponent: true })
|
|
121
|
+
}
|
|
122
|
+
})
|
|
118
123
|
if (meta.genericsInfo) {
|
|
119
124
|
genericsInfo = meta.genericsInfo
|
|
120
125
|
}
|
|
126
|
+
|
|
127
|
+
// virtualHost 下多根节点需要编译期报错(子组件必须单根)
|
|
128
|
+
if (hasVirtualHost && ctorType === 'component') {
|
|
129
|
+
const realRootChildren = root.children.filter(c => c.type === 1 && c.tag !== 'temp-node')
|
|
130
|
+
if (realRootChildren.length > 1) {
|
|
131
|
+
error('Web: when virtualHost is enabled, the component template must have a single root element; please wrap with one root element.')
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 收集 imports / 本地 templates,供 processScript 生成 wxTemplateComponentsMap
|
|
136
|
+
const hasImports = !!(meta.imports && meta.imports.length)
|
|
137
|
+
const hasLocals = !!(meta.templates && Object.keys(meta.templates).length)
|
|
138
|
+
if (hasImports || hasLocals) {
|
|
139
|
+
const locals = []
|
|
140
|
+
if (meta.templates) {
|
|
141
|
+
Object.keys(meta.templates).forEach((name) => {
|
|
142
|
+
const tplNode = meta.templates[name]
|
|
143
|
+
const tpl = serializeWxTemplateDefinition(tplNode, error, name)
|
|
144
|
+
locals.push({
|
|
145
|
+
name: getWxTemplateComponentName(name),
|
|
146
|
+
template: tpl
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
const importMergeExprs = []
|
|
151
|
+
if (meta.imports) {
|
|
152
|
+
meta.imports.forEach((importSrc) => {
|
|
153
|
+
importMergeExprs.push(buildWebTemplateImportMergeExpr(loaderContext, importSrc, projectRoot))
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
wxTemplateComponentsInfo = {
|
|
157
|
+
imports: importMergeExprs,
|
|
158
|
+
locals
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
121
162
|
return templateCompiler.serialize(root)
|
|
122
163
|
}
|
|
123
164
|
})
|
|
@@ -128,6 +169,7 @@ module.exports = function (template, {
|
|
|
128
169
|
output,
|
|
129
170
|
builtInComponentsMap,
|
|
130
171
|
genericsInfo,
|
|
131
|
-
wxsModuleMap
|
|
172
|
+
wxsModuleMap,
|
|
173
|
+
wxTemplateComponentsInfo
|
|
132
174
|
})
|
|
133
175
|
}
|