Skip to content

Commit bd331b0

Browse files
committed
perf(h5): 将 Vapor 框架结构标签编入静态模板
1 parent 379272e commit bd331b0

4 files changed

Lines changed: 367 additions & 261 deletions

File tree

‎packages/uni-h5/__tests__/componentEntry.spec.ts‎

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
import fs from 'fs'
22
import path from 'path'
3+
import { execFileSync } from 'child_process'
4+
import ts from 'typescript'
35
import jscc from 'rollup-plugin-jscc'
46
import { compileScript, compileTemplate, parse } from '@vue/compiler-sfc'
7+
import {
8+
H5_BUILT_IN_TAGS,
9+
TAGS,
10+
isH5CustomElement,
11+
isH5NativeTag,
12+
} from '../../uni-shared/src/tags'
513
import { preprocess } from '../../uni-preprocess'
614

715
const root = path.resolve(__dirname, '..')
@@ -137,3 +145,109 @@ describe('Web 框架组件入口', () => {
137145
expect(entry).not.toContain('uni-components/src/index-vapor')
138146
})
139147
})
148+
149+
describe('框架构建的结构标签分类', () => {
150+
// 直接读取构建配置中的函数,避免测试复制分类逻辑或执行配置的源码同步副作用。
151+
const source = fs.readFileSync(path.join(root, 'vite.config.ts'), 'utf8')
152+
const ast = ts.createSourceFile(
153+
'vite.config.ts',
154+
source,
155+
ts.ScriptTarget.Latest,
156+
true
157+
)
158+
const functions = ast.statements
159+
.filter(
160+
(node) =>
161+
ts.isFunctionDeclaration(node) &&
162+
['realIsH5NativeTag', 'realIsH5CustomElement'].includes(
163+
node.name?.text || ''
164+
)
165+
)
166+
.map((node) => node.getText(ast))
167+
.join('\n')
168+
const code = ts.transpileModule(functions, {}).outputText
169+
const getOptions = (isX: boolean, isX_VAPOR: boolean) =>
170+
new Function(
171+
'TAGS',
172+
'isH5NativeTag',
173+
'isH5CustomElement',
174+
'isX',
175+
'isX_VAPOR',
176+
`${code}; return { isNativeTag: realIsH5NativeTag, isCustomElement: realIsH5CustomElement }`
177+
)(TAGS, isH5NativeTag, isH5CustomElement, isX, isX_VAPOR)
178+
179+
test('SFC 构建配置使用框架专用标签判断', () => {
180+
expect(source).toContain('isNativeTag: realIsH5NativeTag')
181+
expect(source).toContain('isCustomElement: realIsH5CustomElement')
182+
})
183+
184+
test.each([false, true])('非 Vapor 分类不变(X=%s)', (isX) => {
185+
const options = getOptions(isX, false)
186+
for (const tag of [
187+
...TAGS,
188+
...H5_BUILT_IN_TAGS,
189+
'div',
190+
'span',
191+
'svg',
192+
'UnknownComponent',
193+
]) {
194+
expect(options.isNativeTag(tag)).toBe(isH5NativeTag(tag))
195+
expect(options.isCustomElement(tag)).toBe(isH5CustomElement(tag, isX))
196+
}
197+
})
198+
199+
test('Vapor 仅将结构标签改为普通元素', () => {
200+
const options = getOptions(true, true)
201+
for (const tag of TAGS) {
202+
expect(options.isNativeTag(tag)).toBe(true)
203+
expect(options.isCustomElement(tag)).toBe(false)
204+
}
205+
for (const tag of [...H5_BUILT_IN_TAGS, 'div', 'svg', 'UnknownComponent']) {
206+
expect(options.isNativeTag(tag)).toBe(isH5NativeTag(tag))
207+
expect(options.isCustomElement(tag)).toBe(isH5CustomElement(tag, true))
208+
}
209+
})
210+
211+
test('实际 Vapor 编译保留 slot、ref、动态属性和真正自定义元素', () => {
212+
const result = JSON.parse(
213+
execFileSync(
214+
process.execPath,
215+
[
216+
'-e',
217+
`
218+
const fs = require('fs');
219+
const { code, tags } = JSON.parse(fs.readFileSync(0, 'utf8'));
220+
require('./packages/uni-cli-shared/dist/hbx/alias').initWebVaporAliases();
221+
const { compile } = require('@dcloudio/compiler-vapor-web');
222+
const { isH5NativeTag, isH5CustomElement } = require('./packages/uni-shared/dist/uni-shared.cjs.js');
223+
const options = new Function('TAGS', 'isH5NativeTag', 'isH5CustomElement', 'isX', 'isX_VAPOR',
224+
code + '; return { isNativeTag: realIsH5NativeTag, isCustomElement: realIsH5CustomElement }'
225+
)(tags, isH5NativeTag, isH5CustomElement, true, true);
226+
process.stdout.write(JSON.stringify([
227+
compile('<uni-page-wrapper ref="wrapper" v-bind="props"><uni-page-body><slot /></uni-page-body></uni-page-wrapper>', options).code,
228+
compile('<uni-layout><uni-main v-if="visible"><div>{{msg}}</div></uni-main><uni-input :value="value" /></uni-layout>', options).code
229+
]));
230+
`,
231+
],
232+
{
233+
cwd: path.resolve(root, '../..'),
234+
input: JSON.stringify({ code, tags: TAGS }),
235+
encoding: 'utf8',
236+
}
237+
)
238+
) as string[]
239+
expect(result[0]).toContain('_template("<uni-page-wrapper')
240+
expect(result[0]).toContain('<uni-page-body>')
241+
expect(result[0]).not.toContain('createPlainElement')
242+
expect(result[0]).toContain('createSlot')
243+
expect(result[0]).toContain('setDynamicProps')
244+
expect(result[0]).toContain('wrapper')
245+
expect(result[1]).toContain('_template("<uni-layout')
246+
expect(result[1]).toContain('_template("<uni-main')
247+
expect(result[1]).toContain('_createPlainElement("uni-input"')
248+
expect(result[1]).toContain('createIf')
249+
for (const output of result) {
250+
expect(output).not.toContain('resolveComponent')
251+
}
252+
})
253+
})

0 commit comments

Comments
 (0)