提交 8f04fe64 编写于 作者: fxy060608's avatar fxy060608

wip(app): nvue styler

上级 5cf14c50
......@@ -9,6 +9,7 @@ import { uniEasycomPlugin } from '../plugins/easycom'
import { uniManifestJsonPlugin } from '../plugins/manifestJson'
import { uniStatsPlugin } from '../plugins/stats'
import { uniAppNVuePlugin } from './plugin'
import { uniAppCssPlugin } from './plugins/appCss'
import { uniEsbuildPlugin } from './plugins/esbuild'
import { uniMainJsPlugin } from './plugins/mainJs'
import { uniPagesJsonPlugin } from './plugins/pagesJson'
......@@ -17,6 +18,7 @@ export { initNVueNodeTransforms } from './plugin'
export function initNVuePlugins() {
return [
uniAppCssPlugin(),
uniEasycomPlugin({ exclude: UNI_EASYCOM_EXCLUDE }),
uniHBuilderXConsolePlugin(),
uniMainJsPlugin(),
......
import type { Plugin } from 'vite'
import type { PluginContext, RollupError } from 'rollup'
import path from 'path'
import fs from 'fs-extra'
import qs from 'querystring'
import {
CompilerError,
parse,
SFCBlock,
SFCDescriptor,
} from '@vue/compiler-sfc'
import { hash, preNVueHtml, preNVueJs } from '@dcloudio/uni-cli-shared'
declare module '@vue/compiler-sfc' {
interface SFCDescriptor {
id: string
}
}
export const APP_CSS_JS = './app.css.js'
export function uniAppCssPlugin(): Plugin {
const inputDir = process.env.UNI_INPUT_DIR
return {
name: 'uni:app-nvue-app-style',
resolveId(id) {
if (id === APP_CSS_JS) {
return APP_CSS_JS
}
},
load(id) {
if (id === APP_CSS_JS) {
return genAppStylesCode(inputDir, this)
}
},
}
}
const defaultAppStylesCode = `export const AppStyles = []`
async function genAppStylesCode(
inputDir: string,
pluginContext: PluginContext
) {
const filename = path.resolve(inputDir, 'App.vue')
const descriptor = createAppDescriptor(filename, pluginContext)
if (!descriptor.styles.length) {
return defaultAppStylesCode
}
let stylesCode = ``
const styleVars: string[] = []
for (let i = 0; i < descriptor.styles.length; i++) {
const style = descriptor.styles[i]
const src = style.src || descriptor.filename
const attrsQuery = attrsToQuery(style.attrs, 'css')
const srcQuery = style.src ? `&src=${descriptor.id}` : ``
const query = `?vue&type=style&index=${i}${srcQuery}&inline`
const styleRequest = src + query + attrsQuery
stylesCode += `\nimport _style_${i} from ${JSON.stringify(styleRequest)}`
styleVars.push(`_style_${i}`)
}
return `${stylesCode}
export const AppStyles = [${styleVars.join(',')}]
`
}
function readAppCode(filename: string) {
if (!fs.existsSync(filename)) {
return ``
}
const source = fs.readFileSync(filename, 'utf8')
if (source.includes('#endif')) {
return preNVueJs(preNVueHtml(source))
}
return source
}
let appDescriptor: SFCDescriptor
function createAppDescriptor(
filename: string,
pluginContext: PluginContext
): SFCDescriptor {
const source = readAppCode(filename)
const id = hash(source)
if (!appDescriptor || appDescriptor.id !== id) {
const { descriptor, errors } = parse(source, {
filename,
})
descriptor.id = id
if (errors.length) {
errors.forEach((error) =>
pluginContext.error(createRollupError(filename, error))
)
}
appDescriptor = descriptor
}
return appDescriptor
}
export function createRollupError(
id: string,
error: CompilerError | SyntaxError
): RollupError {
const { message, name, stack } = error
const rollupError: RollupError = {
id,
plugin: 'vue',
message,
name,
stack,
}
if ('code' in error && error.loc) {
rollupError.loc = {
file: id,
line: error.loc.start.line,
column: error.loc.start.column,
}
}
return rollupError
}
// these are built-in query parameters so should be ignored
// if the user happen to add them as attrs
const ignoreList = ['id', 'index', 'src', 'type', 'lang', 'module']
function attrsToQuery(
attrs: SFCBlock['attrs'],
langFallback?: string,
forceLangFallback = false
): string {
let query = ``
for (const name in attrs) {
const value = attrs[name]
if (!ignoreList.includes(name)) {
query += `&${qs.escape(name)}${
value ? `=${qs.escape(String(value))}` : ``
}`
}
}
if (langFallback || attrs.lang) {
query +=
`lang` in attrs
? forceLangFallback
? `&lang.${langFallback}`
: `&lang.${attrs.lang}`
: `&lang.${langFallback}`
}
return query
}
import type { Plugin } from 'vite'
import type { BuildOptions, PluginBuild } from 'esbuild'
import path from 'path'
import fs from 'fs-extra'
import debug from 'debug'
import { transformWithEsbuild } from '@dcloudio/uni-cli-shared'
import type { BuildOptions, PluginBuild } from 'esbuild'
import type { Plugin } from 'vite'
import { nvueOutDir } from '../../utils'
const debugEsbuild = debug('uni:app-nvue-esbuild')
export function uniEsbuildPlugin(): Plugin {
let buildOptions: BuildOptions
const outputDir = process.env.UNI_OUTPUT_DIR
......@@ -50,8 +54,11 @@ export function uniEsbuildPlugin(): Plugin {
function buildNVuePage(filename: string, options: BuildOptions) {
return transformWithEsbuild(
`import NVuePageComponent from './${filename}'
Vue.createApp(NVuePageComponent).mount('#root')`,
`import App from './${filename}'
import { AppStyles } from './app.css.js'
const app = Vue.createApp(App)
app.provide('__appStyles', Vue.useCssStyles(AppStyles))
app.mount('#root')`,
path.join(nvueOutDir(), 'main.js'),
options
).then((res) => {
......
import { defineUniMainJsPlugin } from '@dcloudio/uni-cli-shared'
import { APP_CSS_JS } from './appCss'
export function uniMainJsPlugin() {
return defineUniMainJsPlugin((opts) => {
......@@ -17,7 +18,7 @@ export function uniMainJsPlugin() {
}
}
return {
code: `import './pages.json.js'`,
code: `import './pages.json.js';import('${APP_CSS_JS}').then(()=>{})`,
map: { mappings: '' },
}
}
......
......@@ -10982,39 +10982,50 @@ export function nvueFactory(exports, document) {
nextSibling: node => node.nextSibling
};
function isUndef(val) {
return val === undefined || val === null;
function useCssStyles(styles) {
var normalized = {};
if (isArray(styles)) {
styles.forEach(style => {
Object.keys(style).forEach(name => {
if (hasOwn(normalized, name)) {
extend(normalized[name], style[name]);
} else {
normalized[name] = style[name];
}
});
});
}
return normalized;
}
function parseStylesheet(_ref23) {
var {
type
type,
vnode: {
appContext
}
} = _ref23;
if (!type.__styles) {
var {
styles
} = type;
var normalizedStyles = {};
if (isArray(styles)) {
styles.forEach(style => {
Object.keys(style).forEach(name => {
if (hasOwn(normalizedStyles, name)) {
extend(normalizedStyles[name], style[name]);
} else {
normalizedStyles[name] = style[name];
}
});
});
var styles = [];
if (appContext) {
styles.push(appContext.provides.__appStyles);
}
type.__styles = normalizedStyles;
type.styles.forEach(style => styles.push(style));
type.__styles = useCssStyles(styles);
}
return type.__styles;
}
function isUndef(val) {
return val === undefined || val === null;
}
function patchAttr(el, key, value) {
var instance = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
......@@ -11527,6 +11538,7 @@ export function nvueFactory(exports, document) {
unref: unref,
useAttrs: useAttrs,
useCssModule: useCssModule,
useCssStyles: useCssStyles,
useCssVars: useCssVars,
useSSRContext: useSSRContext,
useSlots: useSlots,
......
......@@ -9157,39 +9157,50 @@ export function nvueFactory(exports, document) {
nextSibling: node => node.nextSibling
};
function isUndef(val) {
return val === undefined || val === null;
function useCssStyles(styles) {
var normalized = {};
if (isArray(styles)) {
styles.forEach(style => {
Object.keys(style).forEach(name => {
if (hasOwn(normalized, name)) {
extend(normalized[name], style[name]);
} else {
normalized[name] = style[name];
}
});
});
}
return normalized;
}
function parseStylesheet(_ref23) {
var {
type
type,
vnode: {
appContext
}
} = _ref23;
if (!type.__styles) {
var {
styles
} = type;
var normalizedStyles = {};
if (isArray(styles)) {
styles.forEach(style => {
Object.keys(style).forEach(name => {
if (hasOwn(normalizedStyles, name)) {
extend(normalizedStyles[name], style[name]);
} else {
normalizedStyles[name] = style[name];
}
});
});
var styles = [];
if (appContext) {
styles.push(appContext.provides.__appStyles);
}
type.__styles = normalizedStyles;
type.styles.forEach(style => styles.push(style));
type.__styles = useCssStyles(styles);
}
return type.__styles;
}
function isUndef(val) {
return val === undefined || val === null;
}
function patchAttr(el, key, value) {
var instance = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
......@@ -9698,6 +9709,7 @@ export function nvueFactory(exports, document) {
unref: unref,
useAttrs: useAttrs,
useCssModule: useCssModule,
useCssStyles: useCssStyles,
useCssVars: useCssVars,
useSSRContext: useSSRContext,
useSlots: useSlots,
......
......@@ -8875,30 +8875,38 @@ const nodeOps = {
nextSibling: node => node.nextSibling
};
function isUndef(val) {
return val === undefined || val === null;
function useCssStyles(styles) {
const normalized = {};
if (isArray(styles)) {
styles.forEach(style => {
Object.keys(style).forEach(name => {
if (hasOwn(normalized, name)) {
extend(normalized[name], style[name]);
}
else {
normalized[name] = style[name];
}
});
});
}
return normalized;
}
function parseStylesheet({ type }) {
function parseStylesheet({ type, vnode: { appContext } }) {
if (!type.__styles) {
const { styles } = type;
const normalizedStyles = {};
if (isArray(styles)) {
styles.forEach(style => {
Object.keys(style).forEach(name => {
if (hasOwn(normalizedStyles, name)) {
extend(normalizedStyles[name], style[name]);
}
else {
normalizedStyles[name] = style[name];
}
});
});
const styles = [];
if (appContext) {
styles.push(appContext.provides.__appStyles);
}
type.__styles = normalizedStyles;
type.styles.forEach(style => styles.push(style));
type.__styles = useCssStyles(styles);
}
return type.__styles;
}
function isUndef(val) {
return val === undefined || val === null;
}
function patchAttr(el, key, value, instance = null) {
if (instance) {
value = transformAttr(el, key, value, instance);
......@@ -9219,4 +9227,4 @@ const createApp = ((...args) => {
return app;
});
export { BaseTransition, Comment, EffectScope, Fragment, KeepAlive, ReactiveEffect, Static, Suspense, Teleport, Text, callWithAsyncErrorHandling, callWithErrorHandling, cloneVNode, compatUtils, computed$1 as computed, createApp, createBlock, createCommentVNode, createElementBlock, createBaseVNode as createElementVNode, createHydrationRenderer, createPropsRestProxy, createRenderer, createSlots, createStaticVNode, createTextVNode, createVNode, customRef, defineAsyncComponent, defineComponent, defineEmits, defineExpose, defineProps, devtools, effect, effectScope, getCurrentInstance, getCurrentScope, getTransitionRawChildren, guardReactiveProps, h, handleError, initCustomFormatter, inject, injectHook, isInSSRComponentSetup, isMemoSame, isProxy, isReactive, isReadonly, isRef, isRuntimeOnly, isShallow, isVNode, markRaw, mergeDefaults, mergeProps, nextTick, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, openBlock, popScopeId, provide, proxyRefs, pushScopeId, queuePostFlushCb, reactive, readonly, ref, registerRuntimeCompiler, render, renderList, renderSlot, resolveComponent, resolveDirective, resolveDynamicComponent, resolveFilter, resolveTransitionHooks, setBlockTracking, setDevtoolsHook, setTransitionHooks, shallowReactive, shallowReadonly, shallowRef, ssrContextKey, stop, toHandlers, toRaw, toRef, toRefs, transformVNodeArgs, triggerRef, unref, useAttrs, useCssModule, useCssVars, useSSRContext, useSlots, useTransitionState, version, warn$1 as warn, watch, watchEffect, watchPostEffect, watchSyncEffect, withAsyncContext, withCtx, withDefaults, withDirectives, withMemo, withScopeId };
export { BaseTransition, Comment, EffectScope, Fragment, KeepAlive, ReactiveEffect, Static, Suspense, Teleport, Text, callWithAsyncErrorHandling, callWithErrorHandling, cloneVNode, compatUtils, computed$1 as computed, createApp, createBlock, createCommentVNode, createElementBlock, createBaseVNode as createElementVNode, createHydrationRenderer, createPropsRestProxy, createRenderer, createSlots, createStaticVNode, createTextVNode, createVNode, customRef, defineAsyncComponent, defineComponent, defineEmits, defineExpose, defineProps, devtools, effect, effectScope, getCurrentInstance, getCurrentScope, getTransitionRawChildren, guardReactiveProps, h, handleError, initCustomFormatter, inject, injectHook, isInSSRComponentSetup, isMemoSame, isProxy, isReactive, isReadonly, isRef, isRuntimeOnly, isShallow, isVNode, markRaw, mergeDefaults, mergeProps, nextTick, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, openBlock, popScopeId, provide, proxyRefs, pushScopeId, queuePostFlushCb, reactive, readonly, ref, registerRuntimeCompiler, render, renderList, renderSlot, resolveComponent, resolveDirective, resolveDynamicComponent, resolveFilter, resolveTransitionHooks, setBlockTracking, setDevtoolsHook, setTransitionHooks, shallowReactive, shallowReadonly, shallowRef, ssrContextKey, stop, toHandlers, toRaw, toRef, toRefs, transformVNodeArgs, triggerRef, unref, useAttrs, useCssModule, useCssStyles, useCssVars, useSSRContext, useSlots, useTransitionState, version, warn$1 as warn, watch, watchEffect, watchPostEffect, watchSyncEffect, withAsyncContext, withCtx, withDefaults, withDirectives, withMemo, withScopeId };
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册