提交 373113a3 编写于 作者: fxy060608's avatar fxy060608

feat(ssr): head

上级 f3901790
......@@ -4,6 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<!--head-meta-->
<!--preload-links-->
<script>
document.addEventListener('DOMContentLoaded', function () {
......
......@@ -3,9 +3,9 @@
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "uni -d uni:*",
"build": "uni build -d uni:*",
"dev:ssr": "uni -d uni:* --ssr",
"dev": "uni -d",
"build": "uni build",
"dev:ssr": "uni --ssr",
"build:ssr": "uni build --ssr"
},
"dependencies": {
......
......@@ -7,9 +7,20 @@ export function createApp() {
const store = createStore()
app.use(store)
app.config.warnHandler = function (msg) {
app.config.warnHandler = function (msg, instance) {
if (instance) {
const name = instance.$.type.name
if ('PageMetaHead' === name) {
return
}
const parent = instance.$.parent
if (parent && parent.type.name === 'PageMeta') {
return
}
}
const ssrLogElem = document.getElementById('ssr-log')
ssrLogElem && (ssrLogElem.innerHTML = ssrLogElem.innerHTML + '<br>' + msg)
console.error(msg)
}
return {
app,
......
<template>
<text v-if="item">{{ item.title }}</text>
<text v-else>...</text>
<ssr-cover-image />
<ssr-cover-view />
<ssr-icon />
<ssr-image />
<!-- <ssr-match-media /> -->
<!-- <ssr-movable-area /> -->
<ssr-progress />
<ssr-scroll-view />
<ssr-swiper />
<ssr-text />
<ssr-view />
<ssr-button />
<ssr-canvas />
<ssr-editor />
<ssr-form />
<ssr-label />
<ssr-navigator />
<ssr-rich-text />
<ssr-textarea />
<ssr-slider />
<ssr-map />
<ssr-picker-view />
<ssr-picker />
<ssr-webview />
<ssr-unicloud-db />
<view id="ssr-log"></view>
<page-meta>
<head>
<meta name="keywords" content="uni-app ssr" />
<meta name="description" content="hello uni-app ssr" />
</head>
</page-meta>
<text v-if="item">{{ item.title }}</text>
<text v-else>...</text>
<ssr-cover-image />
<ssr-cover-view />
<ssr-icon />
<ssr-image />
<ssr-match-media />
<!-- <ssr-movable-area /> -->
<ssr-progress />
<ssr-scroll-view />
<ssr-swiper />
<ssr-text />
<ssr-view />
<ssr-button />
<ssr-canvas />
<ssr-editor />
<ssr-form />
<ssr-label />
<ssr-navigator />
<ssr-rich-text />
<ssr-textarea />
<ssr-slider />
<ssr-map />
<ssr-picker-view />
<ssr-picker />
<ssr-webview />
<ssr-unicloud-db />
<!-- <ssr-video /> dataOptions is not a function -->
<view id="ssr-log"></view>
<!-- <ssr-video /> dataOptions is not a function -->
</template>
<script>
......@@ -69,6 +75,13 @@ export default {
</script>
<style>
:deep(iframe) {
top: 200px !important;
}
#ssr-log {
font-size: 20px;
color: red;
}
.content {
display: flex;
flex-direction: column;
......
......@@ -25,6 +25,14 @@ export function initModuleAlias() {
}
}
function supportAutoInstallPlugin() {
return false
}
function sendSignal(lang: string) {
return console.error(`%HXRunUniAPPPluginName%${lang}%HXRunUniAPPPluginName%`)
}
export const moduleAliasFormatter: Formatter = {
test(msg) {
return msg.includes('Preprocessor dependency')
......@@ -43,7 +51,11 @@ export const moduleAliasFormatter: Formatter = {
preprocessor = 'compile-stylus'
}
if (lang) {
return `预编译器错误:代码使用了${lang}语言,但未安装相应的编译器插件,请前往插件市场安装该插件:
const autoInstall = supportAutoInstallPlugin()
autoInstall && sendSignal(preprocessor)
return `预编译器错误:代码使用了${lang}语言,但未安装相应的编译器插件,${
autoInstall ? '正在从' : '请前往'
}插件市场安装该插件:
https://ext.dcloud.net.cn/plugin?name=${preprocessor}`
}
return msg
......
const scopedRE = /\[(data-v-[a-f0-9]{8})\]/gi
export function transformScopedCss(cssCode: string) {
return cssCode.replace(scopedRE, (_, scopedId) => {
return cssCode.replace(/\[(data-v-[a-f0-9]{8})\]/gi, (_, scopedId) => {
return '.' + scopedId
})
}
import { CodegenContext, NodeTransform } from '@vue/compiler-core'
import { NodeTransform } from '@vue/compiler-core'
import { isElementNode } from '../../vite/utils/ast'
export function createTransformTag(
......@@ -14,35 +14,5 @@ export function createTransformTag(
return
}
node.tag = newTag
// SSR 时,已被提前添加到 components 中
if (context.ssr && context.components.has(oldTag)) {
context.components.delete(oldTag)
context.components.add(newTag)
}
}
}
const easycoms: Record<string, string> = {
_component_uni_match_media: '_component_match_media',
_component_page_head_meta: '_component_head',
}
const easycomKeys = Object.keys(easycoms)
export const onContextCreated: (context: CodegenContext) => void = (
context
) => {
if (!context.ssr) {
return
}
// 替换生成的 easycom 变量名
const push = context.push
context.push = (code, node) => {
if (code.includes('_resolveComponent(')) {
const name = easycomKeys.find((name) => code.includes(name))
if (name) {
code = code.replace(name, easycoms[name])
}
}
return push(code, node)
}
}
......@@ -5,5 +5,6 @@
</template>
<script>
export default {
name: 'PageMetaHead',
}
</script>
......@@ -22,6 +22,7 @@ const scrolldoneEvent = {
}
export default {
name: 'PageMeta',
props: {
backgroundTextStyle: {
type: String,
......@@ -53,10 +54,10 @@ export default {
pageStyle: {
type: String,
default: ''
},
enablePullDownRefresh: {
type: [Boolean, String],
default: false
},
enablePullDownRefresh: {
type: [Boolean, String],
default: false
},
rootFontSize: {
type: String,
......@@ -81,8 +82,8 @@ export default {
// 父节点一定是 page
this.$pageVm.$on('hook:onPageScroll', evt => {
this.$emit('scroll', evt)
})
})
// #ifdef APP-PLUS
this._currentWebview = page.$getAppWebview()
if (this.enablePullDownRefresh) {
......@@ -90,7 +91,7 @@ export default {
}
this.$watch('enablePullDownRefresh', (val) => {
this.setPullDownRefresh(this._currentWebview, val)
})
})
// #endif
// props
......@@ -126,14 +127,14 @@ export default {
this.backgroundTextStyle && this.setBackgroundTextStyle()
this.scrollTop && this.pageScrollTo()
},
methods: {
setPullDownRefresh (webview, enabled) {
webview.setStyle({
pullToRefresh: {
support: enabled,
style: plus.os.name === 'Android' ? 'circle' : 'default'
}
})
methods: {
setPullDownRefresh (webview, enabled) {
webview.setStyle({
pullToRefresh: {
support: enabled,
style: plus.os.name === 'Android' ? 'circle' : 'default'
}
})
},
setPageMeta () {
// h5 和 app-plus 设置 rootFontSize
......@@ -187,4 +188,4 @@ export default {
}
}
}
</script>
</script>
......@@ -88,6 +88,12 @@ function renderHeadMeta(ctx) {
return ''
}
return ctx.__teleportBuffers.head
.map((buffer) => buffer.toString())
.map((buffer) =>
buffer
.toString()
.replace(/\s+data-v-[a-f0-9]{8}/gi, '')
.replace('<!--[-->', '')
.replace('<!--]--><!---->', '')
)
.join('\n')
}
......@@ -27,6 +27,7 @@
"@vue/server-renderer": "3.2.21"
},
"devDependencies": {
"@vue/compiler-core": "3.2.21",
"esbuild": "^0.13.2"
}
}
import { NodeTransform, ElementNode, ElementTypes } from '@vue/compiler-core'
import { checkElementNodeTag } from '@dcloudio/uni-cli-shared'
import { ElementNode, NodeTransform } from '@vue/compiler-core'
export const transformPageHead: NodeTransform = (node, context) => {
// 发现是page-meta下的head,替换为page-meta-head
checkElementNodeTag(node, 'head') &&
checkElementNodeTag(context.parent, 'page-meta') &&
(((node as ElementNode).tag = 'page-meta-head'),
((node as ElementNode).tagType = ElementTypes.COMPONENT))
if (checkElementNodeTag(node, 'page-meta')) {
const headNode = node.children.find((child) =>
checkElementNodeTag(child, 'head')
) as ElementNode
if (headNode) {
headNode.tag = 'page-meta-head'
}
return
}
if (
checkElementNodeTag(node, 'head') &&
checkElementNodeTag(context.parent, 'page-meta')
) {
;(node as ElementNode).tag = 'page-meta-head'
}
}
......@@ -10,9 +10,12 @@ import {
parseRpx2UnitOnce,
resolveBuiltIn,
getBuiltInPaths,
transformMatchMedia,
} from '@dcloudio/uni-cli-shared'
import { ConfigEnv, ResolvedConfig, UserConfig } from 'vite'
import resolve from 'resolve'
import { resolveComponentType } from '@vue/compiler-dom'
import { transformPageHead } from '../plugin/transforms/transformPageHead'
export function isSsr(
command: ConfigEnv['command'],
......@@ -134,10 +137,24 @@ export function rewriteSsrResolve(mode?: 2 | 3) {
export function rewriteSsrNativeTag() {
// @ts-ignore
const { parserOptions } = require(resolveBuiltIn('@vue/compiler-dom'))
const compilerDom = require(resolveBuiltIn('@vue/compiler-dom'))
// TODO compiler-ssr时,传入的 isNativeTag 会被 @vue/compiler-dom 的 isNativeTag 覆盖
// https://github.com/vuejs/vue-next/blob/master/packages/compiler-ssr/src/index.ts#L36
parserOptions.isNativeTag = isH5NativeTag
compilerDom.parserOptions.isNativeTag = isH5NativeTag
// ssr 时,ssrTransformComponent 执行时机很早,导致无法正确重写 tag,故通过 resolveComponentType 解决重写
const oldResolveComponentType =
compilerDom.resolveComponentType as typeof resolveComponentType
const newResolveComponentType: typeof resolveComponentType = function (
node,
context,
ssr
) {
transformPageHead(node, context)
transformMatchMedia(node, context)
return oldResolveComponentType(node, context, ssr)
}
compilerDom.resolveComponentType = newResolveComponentType
}
export function rewriteSsrRenderStyle(inputDir: string) {
......
......@@ -7676,6 +7676,8 @@ function warn$1(msg, ...args) {
const appWarnHandler = instance && instance.appContext.config.warnHandler;
const trace = getComponentTrace();
if (appWarnHandler) {
// fixed by xxxxxx Cannot convert a Symbol value to a string
args[0] = String(args[0]);
callWithErrorHandling(appWarnHandler, instance, 11 /* APP_WARN_HANDLER */, [
msg + args.join(''),
instance && instance.proxy,
......
......@@ -9856,6 +9856,8 @@ function warn$1(msg, ...args) {
const appWarnHandler = instance && instance.appContext.config.warnHandler;
const trace = getComponentTrace();
if (appWarnHandler) {
// fixed by xxxxxx Cannot convert a Symbol value to a string
args[0] = String(args[0]);
callWithErrorHandling(appWarnHandler, instance, 11 /* APP_WARN_HANDLER */, [
msg + args.join(''),
instance && instance.proxy,
......
......@@ -9964,6 +9964,8 @@ function warn$1(msg, ...args) {
const appWarnHandler = instance && instance.appContext.config.warnHandler;
const trace = getComponentTrace();
if (appWarnHandler) {
// fixed by xxxxxx Cannot convert a Symbol value to a string
args[0] = String(args[0]);
callWithErrorHandling(appWarnHandler, instance, 11 /* APP_WARN_HANDLER */, [
msg + args.join(''),
instance && instance.proxy,
......
......@@ -7777,6 +7777,8 @@ function warn$1(msg, ...args) {
const appWarnHandler = instance && instance.appContext.config.warnHandler;
const trace = getComponentTrace();
if (appWarnHandler) {
// fixed by xxxxxx Cannot convert a Symbol value to a string
args[0] = String(args[0]);
callWithErrorHandling(appWarnHandler, instance, 11 /* APP_WARN_HANDLER */, [
msg + args.join(''),
instance && instance.proxy,
......
......@@ -6847,11 +6847,30 @@ function initHistory() {
var index$f = {
install(app) {
initApp$1(app);
app.config.warnHandler = warnHandler;
if (__UNI_FEATURE_PAGES__) {
initRouter(app);
}
}
};
function warnHandler(msg, instance, trace) {
if (instance) {
const name = instance.$.type.name;
if (name === "PageMetaHead") {
return;
}
const parent = instance.$.parent;
if (parent && parent.type.name === "PageMeta") {
return;
}
}
const warnArgs = [`[Vue warn]: ${msg}`];
if (trace.length) {
warnArgs.push(`
`, trace);
}
console.warn(...warnArgs);
}
let appVm;
function getApp$1() {
return appVm;
......
......@@ -13859,11 +13859,30 @@ var index$f = {
initApp$1(app);
initViewPlugin(app);
initServicePlugin(app);
app.config.warnHandler = warnHandler;
if (__UNI_FEATURE_PAGES__) {
initRouter(app);
}
}
};
function warnHandler(msg, instance2, trace) {
if (instance2) {
const name = instance2.$.type.name;
if (name === "PageMetaHead") {
return;
}
const parent = instance2.$.parent;
if (parent && parent.type.name === "PageMeta") {
return;
}
}
const warnArgs = [`[Vue warn]: ${msg}`];
if (trace.length) {
warnArgs.push(`
`, trace);
}
console.warn(...warnArgs);
}
let appVm;
function getApp$1() {
return appVm;
......
import { App } from 'vue'
import { App, ComponentPublicInstance } from 'vue'
import { initApp } from '@dcloudio/uni-vue'
import { initViewPlugin, initServicePlugin } from '@dcloudio/uni-core'
......@@ -11,8 +11,33 @@ export default {
initViewPlugin(app)
initServicePlugin(app)
app.config.warnHandler = warnHandler
if (__UNI_FEATURE_PAGES__) {
initRouter(app)
}
},
}
function warnHandler(
msg: string,
instance: ComponentPublicInstance | null,
trace: string
) {
if (instance) {
// ignore ssr warning
const name = instance.$.type.name
if ('PageMetaHead' === name) {
return
}
const parent = instance.$.parent
if (parent && parent.type.name === 'PageMeta') {
return
}
}
const warnArgs = [`[Vue warn]: ${msg}`]
if (trace.length) {
warnArgs.push(`\n`, trace)
}
console.warn(...warnArgs)
}
......@@ -76,7 +76,9 @@ function isH5CustomElement(tag) {
return TAGS.indexOf(tag) !== -1 || BUILT_IN_TAGS.indexOf(tag) !== -1;
}
function isH5NativeTag(tag) {
return (shared.isHTMLTag(tag) || shared.isSVGTag(tag)) && !isBuiltInComponent(tag);
return (tag !== 'head' &&
(shared.isHTMLTag(tag) || shared.isSVGTag(tag)) &&
!isBuiltInComponent(tag));
}
function isNativeTag(tag) {
return shared.isHTMLTag(tag) || shared.isSVGTag(tag) || isBuiltInComponent(tag);
......
......@@ -72,7 +72,9 @@ function isH5CustomElement(tag) {
return TAGS.indexOf(tag) !== -1 || BUILT_IN_TAGS.indexOf(tag) !== -1;
}
function isH5NativeTag(tag) {
return (isHTMLTag(tag) || isSVGTag(tag)) && !isBuiltInComponent(tag);
return (tag !== 'head' &&
(isHTMLTag(tag) || isSVGTag(tag)) &&
!isBuiltInComponent(tag));
}
function isNativeTag(tag) {
return isHTMLTag(tag) || isSVGTag(tag) || isBuiltInComponent(tag);
......
......@@ -5,7 +5,6 @@ import {
UniVitePlugin,
uniPostcssScopedPlugin,
createUniVueTransformAssetUrls,
onContextCreated,
} from '@dcloudio/uni-cli-shared'
import { VitePluginUniResolvedOptions } from '..'
......@@ -62,7 +61,6 @@ export function initPluginVueOptions(
}
compilerOptions.isNativeTag = isNativeTag
compilerOptions.isCustomElement = isCustomElement
;(compilerOptions as any).onContextCreated = onContextCreated
compilerOptions.directiveTransforms = {
...compilerOptions.directiveTransforms,
......
......@@ -458,6 +458,7 @@ importers:
'@dcloudio/uni-cli-shared': 3.0.0-alpha-3021320211109003
'@dcloudio/uni-shared': 3.0.0-alpha-3021320211109003
'@rollup/pluginutils': ^4.1.1
'@vue/compiler-core': 3.2.21
'@vue/compiler-dom': 3.2.21
'@vue/compiler-sfc': 3.2.21
'@vue/server-renderer': 3.2.21
......@@ -470,6 +471,7 @@ importers:
'@vue/compiler-sfc': 3.2.21
'@vue/server-renderer': 3.2.21_vue@3.2.21
devDependencies:
'@vue/compiler-core': 3.2.21
esbuild: 0.13.12
packages/uni-h5-vue:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册