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

wip(app): code spliting

上级 19607018
...@@ -51,16 +51,20 @@ ...@@ -51,16 +51,20 @@
"@rollup/plugin-node-resolve": "^11.0.1", "@rollup/plugin-node-resolve": "^11.0.1",
"@rollup/plugin-replace": "^2.3.4", "@rollup/plugin-replace": "^2.3.4",
"@rollup/plugin-strip": "^2.0.0", "@rollup/plugin-strip": "^2.0.0",
"@types/clean-css": "^4.2.5",
"@types/css-font-loading-module": "^0.0.4", "@types/css-font-loading-module": "^0.0.4",
"@types/debug": "^4.1.5", "@types/debug": "^4.1.5",
"@types/es-module-lexer": "^0.3.0", "@types/es-module-lexer": "^0.3.0",
"@types/fs-extra": "^9.0.6", "@types/fs-extra": "^9.0.6",
"@types/jest": "^26.0.23", "@types/jest": "^26.0.23",
"@types/less": "^3.0.3",
"@types/node": "^14.14.20", "@types/node": "^14.14.20",
"@types/pako": "^1.0.1", "@types/pako": "^1.0.1",
"@types/postcss-import": "^12.0.1",
"@types/puppeteer": "^5.4.2", "@types/puppeteer": "^5.4.2",
"@types/quill": "^1.3.7", "@types/quill": "^1.3.7",
"@types/resolve": "^1.20.0", "@types/resolve": "^1.20.0",
"@types/stylus": "^0.48.36",
"@typescript-eslint/parser": "^4.12.0", "@typescript-eslint/parser": "^4.12.0",
"@vitejs/plugin-legacy": "^1.4.4", "@vitejs/plugin-legacy": "^1.4.4",
"@vitejs/plugin-vue": "^1.2.5", "@vitejs/plugin-vue": "^1.2.5",
...@@ -75,6 +79,7 @@ ...@@ -75,6 +79,7 @@
"mini-types": "^0.1.4", "mini-types": "^0.1.4",
"miniprogram-api-typings": "^3.4.0", "miniprogram-api-typings": "^3.4.0",
"module-alias": "^2.2.2", "module-alias": "^2.2.2",
"postcss-load-config": "^3.1.0",
"prettier": "^2.2.1", "prettier": "^2.2.1",
"rollup": "^2.35.1", "rollup": "^2.35.1",
"rollup-plugin-jscc": "^2.0.0", "rollup-plugin-jscc": "^2.0.0",
...@@ -85,7 +90,7 @@ ...@@ -85,7 +90,7 @@
"rollup-plugin-vue": "^6.0.0", "rollup-plugin-vue": "^6.0.0",
"semver": "^7.3.4", "semver": "^7.3.4",
"ts-jest": "^27.0.3", "ts-jest": "^27.0.3",
"typescript": "~4.1.3", "typescript": "^4.3.5",
"vite": "^2.4.2", "vite": "^2.4.2",
"vue": "^3.1.4", "vue": "^3.1.4",
"yorkie": "^2.0.0" "yorkie": "^2.0.0"
......
...@@ -735,11 +735,14 @@ var serviceContext = (function (vue) { ...@@ -735,11 +735,14 @@ var serviceContext = (function (vue) {
return `on${capitalize(camelize(type))}`; return `on${capitalize(camelize(type))}`;
} }
class UniEvent { class UniEvent {
type;
bubbles;
cancelable;
defaultPrevented = false;
timeStamp = Date.now();
_stop = false;
_end = false;
constructor(type, opts) { constructor(type, opts) {
this.defaultPrevented = false;
this.timeStamp = Date.now();
this._stop = false;
this._end = false;
this.type = type; this.type = type;
this.bubbles = !!opts.bubbles; this.bubbles = !!opts.bubbles;
this.cancelable = !!opts.cancelable; this.cancelable = !!opts.cancelable;
...@@ -767,9 +770,7 @@ var serviceContext = (function (vue) { ...@@ -767,9 +770,7 @@ var serviceContext = (function (vue) {
return uniEvent; return uniEvent;
} }
class UniEventTarget { class UniEventTarget {
constructor() { listeners = Object.create(null);
this.listeners = Object.create(null);
}
dispatchEvent(evt) { dispatchEvent(evt) {
const listeners = this.listeners[evt.type]; const listeners = this.listeners[evt.type];
if (!listeners) { if (!listeners) {
...@@ -842,11 +843,15 @@ var serviceContext = (function (vue) { ...@@ -842,11 +843,15 @@ var serviceContext = (function (vue) {
} }
// 为优化性能,各平台不使用proxy来实现node的操作拦截,而是直接通过pageNode定制 // 为优化性能,各平台不使用proxy来实现node的操作拦截,而是直接通过pageNode定制
class UniNode extends UniEventTarget { class UniNode extends UniEventTarget {
nodeId;
nodeType;
nodeName;
childNodes;
pageNode = null;
parentNode = null;
_text = null;
constructor(nodeType, nodeName, container) { constructor(nodeType, nodeName, container) {
super(); super();
this.pageNode = null;
this.parentNode = null;
this._text = null;
if (container) { if (container) {
const { pageNode } = container; const { pageNode } = container;
if (pageNode) { if (pageNode) {
...@@ -1034,6 +1039,7 @@ var serviceContext = (function (vue) { ...@@ -1034,6 +1039,7 @@ var serviceContext = (function (vue) {
const isObject = (val) => val !== null && typeof val === 'object'; const isObject = (val) => val !== null && typeof val === 'object';
class BaseFormatter { class BaseFormatter {
_caches;
constructor() { constructor() {
this._caches = Object.create(null); this._caches = Object.create(null);
} }
...@@ -1171,12 +1177,13 @@ var serviceContext = (function (vue) { ...@@ -1171,12 +1177,13 @@ var serviceContext = (function (vue) {
} }
} }
class I18n { class I18n {
locale = LOCALE_EN;
fallbackLocale = LOCALE_EN;
message = {};
messages = {};
watchers = [];
formater;
constructor({ locale, fallbackLocale, messages, watcher, formater, }) { constructor({ locale, fallbackLocale, messages, watcher, formater, }) {
this.locale = LOCALE_EN;
this.fallbackLocale = LOCALE_EN;
this.message = {};
this.messages = {};
this.watchers = [];
if (fallbackLocale) { if (fallbackLocale) {
this.fallbackLocale = fallbackLocale; this.fallbackLocale = fallbackLocale;
} }
...@@ -2093,12 +2100,15 @@ var serviceContext = (function (vue) { ...@@ -2093,12 +2100,15 @@ var serviceContext = (function (vue) {
if (!isPromise(res)) { if (!isPromise(res)) {
return res; return res;
} }
return res return new Promise((resolve, reject) => {
.then((res) => { res.then((res) => {
return res[1]; if (res[0]) {
}) reject(res[0]);
.catch((res) => { }
return res[0]; else {
resolve(res[1]);
}
});
}); });
}, },
}; };
...@@ -2188,6 +2198,8 @@ var serviceContext = (function (vue) { ...@@ -2188,6 +2198,8 @@ var serviceContext = (function (vue) {
const API_CREATE_INNER_AUDIO_CONTEXT = 'createInnerAudioContext'; const API_CREATE_INNER_AUDIO_CONTEXT = 'createInnerAudioContext';
class VideoContext { class VideoContext {
id;
pageId;
constructor(id, pageId) { constructor(id, pageId) {
this.id = id; this.id = id;
this.pageId = pageId; this.pageId = pageId;
...@@ -2231,6 +2243,8 @@ var serviceContext = (function (vue) { ...@@ -2231,6 +2243,8 @@ var serviceContext = (function (vue) {
}); });
class MapContext { class MapContext {
id;
pageId;
constructor(id, pageId) { constructor(id, pageId) {
this.id = id; this.id = id;
this.pageId = pageId; this.pageId = pageId;
...@@ -2631,6 +2645,9 @@ var serviceContext = (function (vue) { ...@@ -2631,6 +2645,9 @@ var serviceContext = (function (vue) {
//#endregion //#endregion
//#region Class //#region Class
class CanvasGradient { class CanvasGradient {
type;
data;
colorStop;
constructor(type, data) { constructor(type, data) {
this.type = type; this.type = type;
this.data = data; this.data = data;
...@@ -2641,17 +2658,27 @@ var serviceContext = (function (vue) { ...@@ -2641,17 +2658,27 @@ var serviceContext = (function (vue) {
} }
} }
class Pattern { class Pattern {
image;
repetition;
constructor(image, repetition) { constructor(image, repetition) {
this.image = image; this.image = image;
this.repetition = repetition; this.repetition = repetition;
} }
} }
class TextMetrics { class TextMetrics {
width;
constructor(width) { constructor(width) {
this.width = width; this.width = width;
} }
} }
class CanvasContext { class CanvasContext {
id;
pageId;
actions;
path;
subpath;
state;
drawingState;
constructor(id, pageId) { constructor(id, pageId) {
this.id = id; this.id = id;
this.pageId = pageId; this.pageId = pageId;
...@@ -2981,6 +3008,31 @@ var serviceContext = (function (vue) { ...@@ -2981,6 +3008,31 @@ var serviceContext = (function (vue) {
data: [type], data: [type],
}); });
} }
'setFillStyle';
'setStrokeStyle';
'setGlobalAlpha';
'setShadow';
'addColorStop';
'setLineWidth';
'setLineCap';
'setLineJoin';
'setLineDash';
'setMiterLimit';
'fillRect';
'strokeRect';
'clearRect';
'fill';
'stroke';
'scale';
'rotate';
'translate';
'setFontSize';
'fillText';
'setTextAlign';
'setTextBaseline';
'drawImage';
'strokeText';
'setTransform';
} }
const initCanvasContextProperty = /*#__PURE__*/ once(() => { const initCanvasContextProperty = /*#__PURE__*/ once(() => {
[...methods1, ...methods2].forEach(function (method) { [...methods1, ...methods2].forEach(function (method) {
...@@ -3314,6 +3366,10 @@ var serviceContext = (function (vue) { ...@@ -3314,6 +3366,10 @@ var serviceContext = (function (vue) {
return MARGINS.map((name) => `${Number(margins[name]) || 0}px`).join(' '); return MARGINS.map((name) => `${Number(margins[name]) || 0}px`).join(' ');
} }
class ServiceIntersectionObserver { class ServiceIntersectionObserver {
_reqId;
_pageId;
_component;
_options;
constructor(component, options) { constructor(component, options) {
this._pageId = getPageIdByVm(component); this._pageId = getPageIdByVm(component);
this._component = component; this._component = component;
...@@ -3360,6 +3416,9 @@ var serviceContext = (function (vue) { ...@@ -3360,6 +3416,9 @@ var serviceContext = (function (vue) {
let reqComponentObserverId = 1; let reqComponentObserverId = 1;
class ServiceMediaQueryObserver { class ServiceMediaQueryObserver {
_reqId;
_pageId;
_component;
constructor(component) { constructor(component) {
this._pageId = component.$page && component.$page.id; this._pageId = component.$page && component.$page.id;
this._component = component; this._component = component;
...@@ -3420,6 +3479,8 @@ var serviceContext = (function (vue) { ...@@ -3420,6 +3479,8 @@ var serviceContext = (function (vue) {
}, pageId); }, pageId);
} }
class EditorContext { class EditorContext {
id;
pageId;
constructor(id, pageId) { constructor(id, pageId) {
this.id = id; this.id = id;
this.pageId = pageId; this.pageId = pageId;
...@@ -3486,6 +3547,10 @@ var serviceContext = (function (vue) { ...@@ -3486,6 +3547,10 @@ var serviceContext = (function (vue) {
} }
} }
class NodesRef { class NodesRef {
_selectorQuery;
_component;
_selector;
_single;
constructor(selectorQuery, component, selector, single) { constructor(selectorQuery, component, selector, single) {
this._selectorQuery = selectorQuery; this._selectorQuery = selectorQuery;
this._component = component; this._component = component;
...@@ -3521,8 +3586,12 @@ var serviceContext = (function (vue) { ...@@ -3521,8 +3586,12 @@ var serviceContext = (function (vue) {
} }
} }
class SelectorQuery { class SelectorQuery {
_page;
_queue;
_component = undefined;
_queueCb;
_nodesRef;
constructor(page) { constructor(page) {
this._component = undefined;
this._page = page; this._page = page;
this._queue = []; this._queue = [];
this._queueCb = []; this._queueCb = [];
...@@ -3616,6 +3685,10 @@ var serviceContext = (function (vue) { ...@@ -3616,6 +3685,10 @@ var serviceContext = (function (vue) {
transformOrigin: '50% 50% 0', transformOrigin: '50% 50% 0',
}; };
class MPAnimation { class MPAnimation {
actions;
currentTransform;
currentStepAnimates;
option;
constructor(option) { constructor(option) {
this.actions = []; this.actions = [];
this.currentTransform = {}; this.currentTransform = {};
...@@ -3668,6 +3741,34 @@ var serviceContext = (function (vue) { ...@@ -3668,6 +3741,34 @@ var serviceContext = (function (vue) {
this.currentStepAnimates = []; this.currentStepAnimates = [];
return this; return this;
} }
'matrix';
'matrix3d';
'rotate';
'rotate3d';
'rotateX';
'rotateY';
'rotateZ';
'scale';
'scale3d';
'scaleX';
'scaleY';
'scaleZ';
'skew';
'skewX';
'skewY';
'translate';
'translate3d';
'translateX';
'translateY';
'translateZ';
'opacity';
'backgroundColor';
'width';
'height';
'right';
'top';
'bottom';
'left';
} }
const initAnimationProperty = /*#__PURE__*/ once(() => { const initAnimationProperty = /*#__PURE__*/ once(() => {
const animateTypes1 = [ const animateTypes1 = [
...@@ -5789,7 +5890,9 @@ var serviceContext = (function (vue) { ...@@ -5789,7 +5890,9 @@ var serviceContext = (function (vue) {
}, res)); }, res));
}; };
const Recorder = { const Recorder = {
start({ duration = 60000, sampleRate, numberOfChannels, encodeBitRate, format = 'mp3', frameSize, }) { start({ duration = 60000, sampleRate, numberOfChannels, encodeBitRate, format = 'mp3', frameSize,
// audioSource = 'auto',
}) {
if (recording) { if (recording) {
return publishRecorderStateChange('start'); return publishRecorderStateChange('start');
} }
...@@ -6157,8 +6260,9 @@ var serviceContext = (function (vue) { ...@@ -6157,8 +6260,9 @@ var serviceContext = (function (vue) {
}); });
class DownloadTask { class DownloadTask {
_downloader;
_callbacks = [];
constructor(downloader) { constructor(downloader) {
this._callbacks = [];
this._downloader = downloader; this._downloader = downloader;
downloader.addEventListener('statechanged', (download, status) => { downloader.addEventListener('statechanged', (download, status) => {
if (download.downloadedSize && download.totalSize) { if (download.downloadedSize && download.totalSize) {
...@@ -6277,6 +6381,7 @@ var serviceContext = (function (vue) { ...@@ -6277,6 +6381,7 @@ var serviceContext = (function (vue) {
* 请求任务类 * 请求任务类
*/ */
class RequestTask { class RequestTask {
_requestTask;
constructor(requestTask) { constructor(requestTask) {
this._requestTask = requestTask; this._requestTask = requestTask;
} }
...@@ -6451,6 +6556,14 @@ var serviceContext = (function (vue) { ...@@ -6451,6 +6556,14 @@ var serviceContext = (function (vue) {
}); });
} }
class SocketTask { class SocketTask {
_callbacks;
_socket;
id;
CLOSED;
CLOSING;
CONNECTING;
OPEN;
readyState;
constructor(socket, socketId) { constructor(socket, socketId) {
this.id = socketId; this.id = socketId;
this._socket = socket; this._socket = socket;
...@@ -6606,8 +6719,9 @@ var serviceContext = (function (vue) { ...@@ -6606,8 +6719,9 @@ var serviceContext = (function (vue) {
const onSocketClose = /*#__PURE__*/ on('close'); const onSocketClose = /*#__PURE__*/ on('close');
class UploadTask { class UploadTask {
_uploader;
_callbacks = [];
constructor(uploader) { constructor(uploader) {
this._callbacks = [];
this._uploader = uploader; this._uploader = uploader;
uploader.addEventListener('statechanged', (upload, status) => { uploader.addEventListener('statechanged', (upload, status) => {
if (upload.uploadedSize && upload.totalSize) { if (upload.uploadedSize && upload.totalSize) {
...@@ -6861,6 +6975,61 @@ var serviceContext = (function (vue) { ...@@ -6861,6 +6975,61 @@ var serviceContext = (function (vue) {
}, },
]; ];
class InnerAudioContext { class InnerAudioContext {
/**
* 当前音频的长度(单位:s),只有在当前有合法的 src 时返回
*/
'duration';
/**
* 音频开始播放的位置(单位:s)
*/
'startTime';
/**
* 当前音频的播放位置(单位:s),只有在当前有合法的 src 时返回
*/
'currentTime';
/**
* 当前是是否暂停或停止状态,true 表示暂停或停止,false 表示正在播放
*/
'paused';
/**
* 音频的数据链接,用于直接播放。
*/
'src';
/**
* 音频缓冲的时间点,仅保证当前播放时间点到此时间点内容已缓冲
*/
'buffered';
/**
* 是否自动开始播放,默认 false
*/
'autoplay';
/**
* 是否循环播放,默认 false
*/
'loop';
/**
* 是否遵循系统静音开关,当此参数为 false 时,即使用户打开了静音开关,也能继续发出声音,默认值 true
*/
'obeyMuteSwitch';
/**
* 音量。范围 0~1。
*/
'volume';
/**
* 事件监听
*/
_callbacks;
/**
*
* @param id 当前Audio示例id
*/
id;
/**
*
* @param __timing 当前Audio所使用的timer
*/
__timing;
_options;
constructor(id) { constructor(id) {
this.id = id; this.id = id;
this._callbacks = {}; this._callbacks = {};
...@@ -6923,6 +7092,26 @@ var serviceContext = (function (vue) { ...@@ -6923,6 +7092,26 @@ var serviceContext = (function (vue) {
operationType: type, operationType: type,
})); }));
} }
'onCanplay';
'onPlay';
'onPause';
'onStop';
'onEnded';
'onTimeUpdate';
'onError';
'onWaiting';
'onSeeking';
'onSeeked';
'offCanplay';
'offPlay';
'offPause';
'offStop';
'offEnded';
'offTimeUpdate';
'offError';
'offWaiting';
'offSeeking';
'offSeeked';
} }
const initInnerAudioContextEventOnce = /*#__PURE__*/ once(() => { const initInnerAudioContextEventOnce = /*#__PURE__*/ once(() => {
// 批量设置音频上下文事件监听方法 // 批量设置音频上下文事件监听方法
...@@ -7230,6 +7419,19 @@ var serviceContext = (function (vue) { ...@@ -7230,6 +7419,19 @@ var serviceContext = (function (vue) {
}, },
]; ];
class BackgroundAudioManager { class BackgroundAudioManager {
'duration';
'startTime';
'currentTime';
'paused';
'src';
'buffered';
'title';
'epname';
'singer';
'coverImgUrl';
'webUrl';
'protocol';
_options;
constructor() { constructor() {
this._options = {}; this._options = {};
props.forEach((item) => { props.forEach((item) => {
...@@ -7268,6 +7470,16 @@ var serviceContext = (function (vue) { ...@@ -7268,6 +7470,16 @@ var serviceContext = (function (vue) {
operationType: type, operationType: type,
})); }));
} }
'onCanplay';
'onPlay';
'onPause';
'onStop';
'onEnded';
'onTimeUpdate';
'onWaiting';
'onPrev';
'onNext';
'onError';
} }
let backgroundAudioManager; let backgroundAudioManager;
const getBackgroundAudioManager = defineSyncApi(API_GET_BACKGROUND_AUDIO_MANAGER, () => backgroundAudioManager || const getBackgroundAudioManager = defineSyncApi(API_GET_BACKGROUND_AUDIO_MANAGER, () => backgroundAudioManager ||
...@@ -7446,6 +7658,7 @@ var serviceContext = (function (vue) { ...@@ -7446,6 +7658,7 @@ var serviceContext = (function (vue) {
callbacks[pageId] = callback; callbacks[pageId] = callback;
} }
class Page { class Page {
webview;
constructor(webview) { constructor(webview) {
this.webview = webview; this.webview = webview;
} }
...@@ -7671,7 +7884,7 @@ var serviceContext = (function (vue) { ...@@ -7671,7 +7884,7 @@ var serviceContext = (function (vue) {
modal: mask, modal: mask,
back: 'transmit', back: 'transmit',
padding: '10px', padding: '10px',
size: '16px', size: '16px', // 固定字体大小
}; };
if (!image && (!icon || icon === 'none')) { if (!image && (!icon || icon === 'none')) {
// 无图 // 无图
...@@ -8904,6 +9117,7 @@ var serviceContext = (function (vue) { ...@@ -8904,6 +9117,7 @@ var serviceContext = (function (vue) {
adClicked: 'adClicked', adClicked: 'adClicked',
}; };
class AdEventHandler { class AdEventHandler {
_callbacks;
constructor() { constructor() {
this._callbacks = {}; this._callbacks = {};
} }
...@@ -8945,15 +9159,16 @@ var serviceContext = (function (vue) { ...@@ -8945,15 +9159,16 @@ var serviceContext = (function (vue) {
} }
} }
class AdBase extends AdEventHandler { class AdBase extends AdEventHandler {
_isLoaded = false;
_isLoading = false;
_preload = true;
_loadPromiseResolve = null;
_loadPromiseReject = null;
_showPromiseResolve = null;
_showPromiseReject = null;
_adInstance;
constructor(adInstance, options) { constructor(adInstance, options) {
super(); super();
this._isLoaded = false;
this._isLoading = false;
this._preload = true;
this._loadPromiseResolve = null;
this._loadPromiseReject = null;
this._showPromiseResolve = null;
this._showPromiseReject = null;
this._preload = options.preload !== undefined ? options.preload : false; this._preload = options.preload !== undefined ? options.preload : false;
const ad = (this._adInstance = adInstance); const ad = (this._adInstance = adInstance);
ad.onLoad(() => { ad.onLoad(() => {
...@@ -9131,19 +9346,19 @@ var serviceContext = (function (vue) { ...@@ -9131,19 +9346,19 @@ var serviceContext = (function (vue) {
}); });
} }
class InteractiveAd extends AdEventHandler { class InteractiveAd extends AdEventHandler {
_adpid = '';
_provider = '';
_userData = null;
_isLoaded = false;
_isLoading = false;
_loadPromiseResolve = null;
_loadPromiseReject = null;
_showPromiseResolve = null;
_showPromiseReject = null;
_adInstance = null;
_adError = '';
constructor(options) { constructor(options) {
super(); super();
this._adpid = '';
this._provider = '';
this._userData = null;
this._isLoaded = false;
this._isLoading = false;
this._loadPromiseResolve = null;
this._loadPromiseReject = null;
this._showPromiseResolve = null;
this._showPromiseReject = null;
this._adInstance = null;
this._adError = '';
this._adpid = options.adpid; this._adpid = options.adpid;
this._provider = options.provider; this._provider = options.provider;
this._userData = options.userData; this._userData = options.userData;
...@@ -9573,13 +9788,19 @@ var serviceContext = (function (vue) { ...@@ -9573,13 +9788,19 @@ var serviceContext = (function (vue) {
} }
class UniPageNode extends UniNode { class UniPageNode extends UniNode {
pageId;
_id = 1;
_created = false;
createAction;
createdAction;
_createActionMap = new Map();
updateActions = [];
dicts = [];
normalizeDict;
isUnmounted;
_update;
constructor(pageId, options, setup = false) { constructor(pageId, options, setup = false) {
super(NODE_TYPE_PAGE, '#page', null); super(NODE_TYPE_PAGE, '#page', null);
this._id = 1;
this._created = false;
this._createActionMap = new Map();
this.updateActions = [];
this.dicts = [];
this.nodeId = 0; this.nodeId = 0;
this.pageId = pageId; this.pageId = pageId;
this.pageNode = this; this.pageNode = this;
...@@ -9822,22 +10043,33 @@ var serviceContext = (function (vue) { ...@@ -9822,22 +10043,33 @@ var serviceContext = (function (vue) {
return vm; return vm;
} }
function isVuePageAsyncComponent(component) {
return isFunction(component);
}
const pagesMap = new Map(); const pagesMap = new Map();
function definePage(pagePath, component) { function definePage(pagePath, asyncComponent) {
pagesMap.set(pagePath, once(createFactory(component))); pagesMap.set(pagePath, once(createFactory(asyncComponent)));
} }
function createPage(__pageId, __pagePath, __pageQuery, __pageInstance, pageOptions) { function createPage(__pageId, __pagePath, __pageQuery, __pageInstance, pageOptions) {
const pageNode = createPageNode(__pageId, pageOptions, true); const pageNode = createPageNode(__pageId, pageOptions, true);
const app = getVueApp(); const app = getVueApp();
return app.mountPage(pagesMap.get(__pagePath)(), { const component = pagesMap.get(__pagePath)();
const mountPage = (component) => app.mountPage(component, {
__pageId, __pageId,
__pagePath, __pagePath,
__pageQuery, __pageQuery,
__pageInstance, __pageInstance,
}, pageNode); }, pageNode);
if (isPromise(component)) {
return component.then((component) => mountPage(component));
}
return mountPage(component);
} }
function createFactory(component) { function createFactory(component) {
return () => { return () => {
if (isVuePageAsyncComponent(component)) {
return component().then((component) => setupPage(component));
}
return setupPage(component); return setupPage(component);
}; };
} }
......
import { isFunction, isPromise } from '@vue/shared'
import { once, PageNodeOptions } from '@dcloudio/uni-shared' import { once, PageNodeOptions } from '@dcloudio/uni-shared'
import { DefineComponent } from 'vue' import { DefineComponent } from 'vue'
import { createPageNode } from '../dom/Page' import { createPageNode } from '../dom/Page'
...@@ -7,10 +8,21 @@ import { getVueApp } from '../app' ...@@ -7,10 +8,21 @@ import { getVueApp } from '../app'
export type VuePageComponent = DefineComponent<PageProps> export type VuePageComponent = DefineComponent<PageProps>
type VuePageAsyncComponent = () => Promise<VuePageComponent>
function isVuePageAsyncComponent(
component: unknown
): component is VuePageAsyncComponent {
return isFunction(component)
}
const pagesMap = new Map<string, ReturnType<typeof createFactory>>() const pagesMap = new Map<string, ReturnType<typeof createFactory>>()
export function definePage(pagePath: string, component: VuePageComponent) { export function definePage(
pagesMap.set(pagePath, once(createFactory(component))) pagePath: string,
asyncComponent: VuePageAsyncComponent | VuePageComponent
) {
pagesMap.set(pagePath, once(createFactory(asyncComponent)))
} }
interface PageProps { interface PageProps {
...@@ -29,8 +41,10 @@ export function createPage( ...@@ -29,8 +41,10 @@ export function createPage(
) { ) {
const pageNode = createPageNode(__pageId, pageOptions, true) const pageNode = createPageNode(__pageId, pageOptions, true)
const app = getVueApp() const app = getVueApp()
return app.mountPage( const component = pagesMap.get(__pagePath)!()
pagesMap.get(__pagePath)!(), const mountPage = (component: VuePageComponent) =>
app.mountPage(
component,
{ {
__pageId, __pageId,
__pagePath, __pagePath,
...@@ -39,10 +53,17 @@ export function createPage( ...@@ -39,10 +53,17 @@ export function createPage(
}, },
pageNode pageNode
) )
if (isPromise(component)) {
return component.then((component) => mountPage(component))
}
return mountPage(component)
} }
function createFactory(component: VuePageComponent) { function createFactory(component: VuePageAsyncComponent | VuePageComponent) {
return () => { return () => {
if (isVuePageAsyncComponent(component)) {
return component().then((component) => setupPage(component))
}
return setupPage(component) return setupPage(component)
} }
} }
...@@ -11,14 +11,17 @@ const mainJs_1 = require("./plugins/mainJs"); ...@@ -11,14 +11,17 @@ const mainJs_1 = require("./plugins/mainJs");
const manifestJson_1 = require("./plugins/manifestJson"); const manifestJson_1 = require("./plugins/manifestJson");
const pagesJson_1 = require("./plugins/pagesJson"); const pagesJson_1 = require("./plugins/pagesJson");
const resolveId_1 = require("./plugins/resolveId"); const resolveId_1 = require("./plugins/resolveId");
exports.default = [ const plugins = [
resolveId_1.uniResolveIdPlugin(), resolveId_1.uniResolveIdPlugin(),
copy_1.uniCopyPlugin(), copy_1.uniCopyPlugin(),
mainJs_1.uniMainJsPlugin(), mainJs_1.uniMainJsPlugin(),
manifestJson_1.uniManifestJsonPlugin(), manifestJson_1.uniManifestJsonPlugin(),
pagesJson_1.uniPagesJsonPlugin(), pagesJson_1.uniPagesJsonPlugin(),
plugin_1.UniAppPlugin, plugin_1.UniAppPlugin,
uni_cli_shared_1.uniCssPlugin({
app: fs_1.default.readFileSync(require.resolve('@dcloudio/uni-app-plus/dist/style.css'), 'utf8'),
}),
]; ];
if (!process.env.UNI_APP_CODE_SPLITING) {
plugins.push(uni_cli_shared_1.uniCssPlugin({
app: fs_1.default.readFileSync(require.resolve('@dcloudio/uni-app-plus/dist/style.css'), 'utf8'),
}));
}
exports.default = plugins;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UniAppPlugin = void 0;
const uni_shared_1 = require("@dcloudio/uni-shared");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
exports.UniAppPlugin = {
name: 'vite:uni-app',
uni: {
compilerOptions: {
isNativeTag: uni_shared_1.isServiceNativeTag,
isCustomElement: uni_shared_1.isServiceCustomElement,
},
transformEvent: {
tap: 'click',
},
},
config() {
return {
build: {
rollupOptions: {
input: uni_cli_shared_1.resolveMainPathOnce(process.env.UNI_INPUT_DIR),
external: ['vue'],
output: {
name: 'AppService',
format: 'iife',
entryFileNames: 'app-service.js',
manualChunks: undefined,
globals: {
vue: 'Vue',
},
},
},
},
};
},
configResolved(config) {
const manifestJson = uni_cli_shared_1.parseManifestJsonOnce(process.env.UNI_INPUT_DIR);
if (uni_cli_shared_1.getNVueCompiler(manifestJson) === 'uni-app') {
process.env.UNI_USING_NVUE_COMPILER = 'uni-app';
}
if (uni_cli_shared_1.getNVueStyleCompiler(manifestJson) === 'uni-app') {
process.env.UNI_USING_NVUE_STYLE_COMPILER = 'uni-app';
}
// 移除 vite 内置的 css post 处理
const index = config.plugins.findIndex((p) => p.name === 'vite:css-post');
if (index > -1) {
;
config.plugins.splice(index, 1);
}
},
resolveId(id) {
if (id === 'vue') {
return uni_cli_shared_1.resolveBuiltIn('@dcloudio/uni-app-vue');
}
},
};
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildOptions = void 0;
const path_1 = __importDefault(require("path"));
const slash_1 = __importDefault(require("slash"));
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
exports.buildOptions = {
rollupOptions: {
input: uni_cli_shared_1.resolveMainPathOnce(process.env.UNI_INPUT_DIR),
external: ['vue'],
output: {
name: 'AppService',
format: process.env.UNI_APP_CODE_SPLITING ? 'amd' : 'iife',
entryFileNames: 'app-service.js',
manualChunks: {},
chunkFileNames(chunk) {
if (chunk.isDynamicEntry && chunk.facadeModuleId) {
const filepath = path_1.default.relative(process.env.UNI_INPUT_DIR, chunk.facadeModuleId);
return slash_1.default(filepath.replace(path_1.default.extname(filepath), '.js'));
}
return '[name].js';
},
assetFileNames: '[name][extname]',
globals: {
vue: 'Vue',
},
},
},
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.configResolved = void 0;
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const asset_1 = require("../plugins/vitejs/plugins/asset");
const css_1 = require("../plugins/vitejs/plugins/css");
const configResolved = (config) => {
const manifestJson = uni_cli_shared_1.parseManifestJsonOnce(process.env.UNI_INPUT_DIR);
if (uni_cli_shared_1.getNVueCompiler(manifestJson) === 'uni-app') {
process.env.UNI_USING_NVUE_COMPILER = 'uni-app';
}
if (uni_cli_shared_1.getNVueStyleCompiler(manifestJson) === 'uni-app') {
process.env.UNI_USING_NVUE_STYLE_COMPILER = 'uni-app';
}
if (process.env.UNI_APP_CODE_SPLITING) {
initCodeSpliting(config);
}
else {
// 移除 vite 内置的 css post 处理,交由 @dcloudio/uni-cli-shared 的 uniCssPlugin 实现
const index = config.plugins.findIndex((p) => p.name === 'vite:css-post');
if (index > -1) {
;
config.plugins.splice(index, 1);
}
}
};
exports.configResolved = configResolved;
function initCodeSpliting(config) {
// 替换内置插件
const replacedPlugins = [
asset_1.assetPlugin(config),
css_1.cssPlugin(config),
css_1.cssPostPlugin(config),
];
replacedPlugins.forEach((plugin) => {
const index = config.plugins.findIndex((p) => p.name === plugin.name);
if (index > -1) {
;
config.plugins.splice(index, 1, plugin);
}
});
const removedPlugins = ['vite:import-analysis'];
removedPlugins.forEach((name) => {
const index = config.plugins.findIndex((p) => p.name === name);
if (index > -1) {
;
config.plugins.splice(index, 1);
}
});
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UniAppPlugin = void 0;
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const uni_1 = require("./uni");
const build_1 = require("./build");
const configResolved_1 = require("./configResolved");
exports.UniAppPlugin = {
name: 'vite:uni-app',
uni: uni_1.uniOptions,
config() {
return {
build: build_1.buildOptions,
};
},
configResolved: configResolved_1.configResolved,
resolveId(id) {
if (id === 'vue') {
return uni_cli_shared_1.resolveBuiltIn('@dcloudio/uni-app-vue');
}
},
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniOptions = void 0;
const uni_shared_1 = require("@dcloudio/uni-shared");
exports.uniOptions = {
compilerOptions: {
isNativeTag: uni_shared_1.isServiceNativeTag,
isCustomElement: uni_shared_1.isServiceCustomElement,
},
transformEvent: {
tap: 'click',
},
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CLIENT_PUBLIC_PATH = exports.FS_PREFIX = void 0;
/**
* https://github.com/vitejs/vite/blob/main/packages/vite/src/node/constants.ts
*/
/**
* Prefix for resolved fs paths, since windows paths may not be valid as URLs.
*/
exports.FS_PREFIX = `/@fs/`;
exports.CLIENT_PUBLIC_PATH = `/@vite/client`;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.urlToBuiltUrl = exports.getAssetHash = exports.getAssetFilename = exports.fileToUrl = exports.checkPublicFile = exports.registerAssetToChunk = exports.assetPlugin = exports.chunkToEmittedAssetsMap = exports.assetUrlRE = void 0;
/**
* https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/asset.ts
*/
const path_1 = __importDefault(require("path"));
const url_1 = require("url");
const fs_1 = __importStar(require("fs"));
const lite_1 = __importDefault(require("mime/lite"));
const utils_1 = require("../utils");
const constants_1 = require("../constants");
const magic_string_1 = __importDefault(require("magic-string"));
const crypto_1 = require("crypto");
exports.assetUrlRE = /__VITE_ASSET__([a-z\d]{8})__(?:\$_(.*?)__)?/g;
// urls in JS must be quoted as strings, so when replacing them we need
// a different regex
const assetUrlQuotedRE = /"__VITE_ASSET__([a-z\d]{8})__(?:\$_(.*?)__)?"/g;
const rawRE = /(\?|&)raw(?:&|$)/;
const urlRE = /(\?|&)url(?:&|$)/;
exports.chunkToEmittedAssetsMap = new WeakMap();
const assetCache = new WeakMap();
const assetHashToFilenameMap = new WeakMap();
// save hashes of the files that has been emitted in build watch
const emittedHashMap = new WeakMap();
/**
* Also supports loading plain strings with import text from './foo.txt?raw'
*/
function assetPlugin(config) {
// assetHashToFilenameMap initialization in buildStart causes getAssetFilename to return undefined
assetHashToFilenameMap.set(config, new Map());
return {
name: 'vite:asset',
buildStart() {
assetCache.set(config, new Map());
emittedHashMap.set(config, new Set());
},
resolveId(id) {
if (!config.assetsInclude(utils_1.cleanUrl(id))) {
return;
}
// imports to absolute urls pointing to files in /public
// will fail to resolve in the main resolver. handle them here.
const publicFile = checkPublicFile(id, config);
if (publicFile) {
return id;
}
},
load(id) {
return __awaiter(this, void 0, void 0, function* () {
if (id.startsWith('\0')) {
// Rollup convention, this id should be handled by the
// plugin that marked it with \0
return;
}
// raw requests, read from disk
if (rawRE.test(id)) {
const file = checkPublicFile(id, config) || utils_1.cleanUrl(id);
// raw query, read file and return as string
return `export default ${JSON.stringify(yield fs_1.promises.readFile(file, 'utf-8'))}`;
}
if (!config.assetsInclude(utils_1.cleanUrl(id)) && !urlRE.test(id)) {
return;
}
id = id.replace(urlRE, '$1').replace(/[\?&]$/, '');
const url = yield fileToUrl(id, config, this);
return `export default ${JSON.stringify(url)}`;
});
},
renderChunk(code, chunk) {
let match;
let s;
while ((match = assetUrlQuotedRE.exec(code))) {
s = s || (s = new magic_string_1.default(code));
const [full, hash, postfix = ''] = match;
// some internal plugins may still need to emit chunks (e.g. worker) so
// fallback to this.getFileName for that.
const file = getAssetFilename(hash, config) || this.getFileName(hash);
registerAssetToChunk(chunk, file);
const outputFilepath = config.base + file + postfix;
s.overwrite(match.index, match.index + full.length, JSON.stringify(outputFilepath));
}
if (s) {
return {
code: s.toString(),
map: config.build.sourcemap ? s.generateMap({ hires: true }) : null,
};
}
else {
return null;
}
},
generateBundle(_, bundle) {
// do not emit assets for SSR build
if (config.command === 'build' && config.build.ssr) {
for (const file in bundle) {
if (bundle[file].type === 'asset' &&
!file.includes('ssr-manifest.json')) {
delete bundle[file];
}
}
}
},
};
}
exports.assetPlugin = assetPlugin;
function registerAssetToChunk(chunk, file) {
let emitted = exports.chunkToEmittedAssetsMap.get(chunk);
if (!emitted) {
emitted = new Set();
exports.chunkToEmittedAssetsMap.set(chunk, emitted);
}
emitted.add(utils_1.cleanUrl(file));
}
exports.registerAssetToChunk = registerAssetToChunk;
function checkPublicFile(url, { publicDir }) {
// note if the file is in /public, the resolver would have returned it
// as-is so it's not going to be a fully resolved path.
if (!publicDir || !url.startsWith('/')) {
return;
}
const publicFile = path_1.default.join(publicDir, utils_1.cleanUrl(url));
if (fs_1.default.existsSync(publicFile)) {
return publicFile;
}
else {
return;
}
}
exports.checkPublicFile = checkPublicFile;
function fileToUrl(id, config, ctx) {
if (config.command === 'serve') {
return fileToDevUrl(id, config);
}
else {
return fileToBuiltUrl(id, config, ctx);
}
}
exports.fileToUrl = fileToUrl;
function fileToDevUrl(id, config) {
let rtn;
if (checkPublicFile(id, config)) {
// in public dir, keep the url as-is
rtn = id;
}
else if (id.startsWith(config.root)) {
// in project root, infer short public path
rtn = '/' + path_1.default.posix.relative(config.root, id);
}
else {
// outside of project root, use absolute fs path
// (this is special handled by the serve static middleware
rtn = path_1.default.posix.join(constants_1.FS_PREFIX + id);
}
return config.base + rtn.replace(/^\//, '');
}
function getAssetFilename(hash, config) {
var _a;
return (_a = assetHashToFilenameMap.get(config)) === null || _a === void 0 ? void 0 : _a.get(hash);
}
exports.getAssetFilename = getAssetFilename;
/**
* Register an asset to be emitted as part of the bundle (if necessary)
* and returns the resolved public URL
*/
function fileToBuiltUrl(id, config, pluginContext, skipPublicCheck = false) {
return __awaiter(this, void 0, void 0, function* () {
if (!skipPublicCheck && checkPublicFile(id, config)) {
return config.base + id.slice(1);
}
const cache = assetCache.get(config);
const cached = cache.get(id);
if (cached) {
return cached;
}
const file = utils_1.cleanUrl(id);
const content = yield fs_1.promises.readFile(file);
let url;
if (config.build.lib ||
(!file.endsWith('.svg') &&
content.length < Number(config.build.assetsInlineLimit))) {
// base64 inlined as a string
url = `data:${lite_1.default.getType(file)};base64,${content.toString('base64')}`;
}
else {
// emit as asset
// rollup supports `import.meta.ROLLUP_FILE_URL_*`, but it generates code
// that uses runtime url sniffing and it can be verbose when targeting
// non-module format. It also fails to cascade the asset content change
// into the chunk's hash, so we have to do our own content hashing here.
// https://bundlers.tooling.report/hashing/asset-cascade/
// https://github.com/rollup/rollup/issues/3415
const map = assetHashToFilenameMap.get(config);
const contentHash = getAssetHash(content);
const { search, hash } = url_1.parse(id);
const postfix = (search || '') + (hash || '');
const basename = path_1.default.basename(file);
const ext = path_1.default.extname(basename);
const fileName = path_1.default.posix.join(config.build.assetsDir, `${basename.slice(0, -ext.length)}.${contentHash}${ext}`);
if (!map.has(contentHash)) {
map.set(contentHash, fileName);
}
const emittedSet = emittedHashMap.get(config);
if (!emittedSet.has(contentHash)) {
pluginContext.emitFile({
fileName,
type: 'asset',
source: content,
});
emittedSet.add(contentHash);
}
url = `__VITE_ASSET__${contentHash}__${postfix ? `$_${postfix}__` : ``}`;
}
cache.set(id, url);
return url;
});
}
function getAssetHash(content) {
return crypto_1.createHash('sha256').update(content).digest('hex').slice(0, 8);
}
exports.getAssetHash = getAssetHash;
function urlToBuiltUrl(url, importer, config, pluginContext) {
return __awaiter(this, void 0, void 0, function* () {
if (checkPublicFile(url, config)) {
return config.base + url.slice(1);
}
const file = url.startsWith('/')
? path_1.default.join(config.root, url)
: path_1.default.join(path_1.default.dirname(importer), url);
return fileToBuiltUrl(file, config, pluginContext,
// skip public check since we just did it above
true);
});
}
exports.urlToBuiltUrl = urlToBuiltUrl;
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.processSrcSet = exports.generateCodeFrame = exports.posToNumber = exports.pad = exports.isObject = exports.asyncReplace = exports.isDataUrl = exports.dataUrlRE = exports.isExternalUrl = exports.externalRE = exports.cleanUrl = exports.hashRE = exports.queryRE = exports.normalizePath = exports.isWindows = exports.deepImportRE = exports.bareImportRE = exports.slash = void 0;
/**
* https://github.com/vitejs/vite/blob/main/packages/vite/src/node/utils.ts
*/
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
function slash(p) {
return p.replace(/\\/g, '/');
}
exports.slash = slash;
exports.bareImportRE = /^[\w@](?!.*:\/\/)/;
exports.deepImportRE = /^([^@][^/]*)\/|^(@[^/]+\/[^/]+)\//;
exports.isWindows = os_1.default.platform() === 'win32';
function normalizePath(id) {
return path_1.default.posix.normalize(exports.isWindows ? slash(id) : id);
}
exports.normalizePath = normalizePath;
exports.queryRE = /\?.*$/s;
exports.hashRE = /#.*$/s;
const cleanUrl = (url) => url.replace(exports.hashRE, '').replace(exports.queryRE, '');
exports.cleanUrl = cleanUrl;
exports.externalRE = /^(https?:)?\/\//;
const isExternalUrl = (url) => exports.externalRE.test(url);
exports.isExternalUrl = isExternalUrl;
exports.dataUrlRE = /^\s*data:/i;
const isDataUrl = (url) => exports.dataUrlRE.test(url);
exports.isDataUrl = isDataUrl;
function asyncReplace(input, re, replacer) {
return __awaiter(this, void 0, void 0, function* () {
let match;
let remaining = input;
let rewritten = '';
while ((match = re.exec(remaining))) {
rewritten += remaining.slice(0, match.index);
rewritten += yield replacer(match);
remaining = remaining.slice(match.index + match[0].length);
}
rewritten += remaining;
return rewritten;
});
}
exports.asyncReplace = asyncReplace;
function isObject(value) {
return Object.prototype.toString.call(value) === '[object Object]';
}
exports.isObject = isObject;
const splitRE = /\r?\n/;
const range = 2;
function pad(source, n = 2) {
const lines = source.split(splitRE);
return lines.map((l) => ` `.repeat(n) + l).join(`\n`);
}
exports.pad = pad;
function posToNumber(source, pos) {
if (typeof pos === 'number')
return pos;
const lines = source.split(splitRE);
const { line, column } = pos;
let start = 0;
for (let i = 0; i < line - 1; i++) {
start += lines[i].length + 1;
}
return start + column;
}
exports.posToNumber = posToNumber;
function generateCodeFrame(source, start = 0, end) {
start = posToNumber(source, start);
end = end || start;
const lines = source.split(splitRE);
let count = 0;
const res = [];
for (let i = 0; i < lines.length; i++) {
count += lines[i].length + 1;
if (count >= start) {
for (let j = i - range; j <= i + range || end > count; j++) {
if (j < 0 || j >= lines.length)
continue;
const line = j + 1;
res.push(`${line}${' '.repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}`);
const lineLength = lines[j].length;
if (j === i) {
// push underline
const pad = start - (count - lineLength) + 1;
const length = Math.max(1, end > count ? lineLength - pad : end - start);
res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
}
else if (j > i) {
if (end > count) {
const length = Math.max(Math.min(end - count, lineLength), 1);
res.push(` | ` + '^'.repeat(length));
}
count += lineLength + 1;
}
}
break;
}
}
return res.join('\n');
}
exports.generateCodeFrame = generateCodeFrame;
const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g;
function processSrcSet(srcs, replacer) {
return __awaiter(this, void 0, void 0, function* () {
const imageCandidates = srcs
.split(',')
.map((s) => {
const [url, descriptor] = s
.replace(escapedSpaceCharacters, ' ')
.trim()
.split(' ', 2);
return { url, descriptor };
})
.filter(({ url }) => !!url);
const ret = yield Promise.all(imageCandidates.map(({ url, descriptor }) => __awaiter(this, void 0, void 0, function* () {
return {
url: yield replacer({ url, descriptor }),
descriptor,
};
})));
const url = ret.reduce((prev, { url, descriptor }, index) => {
descriptor = descriptor || '';
return (prev +=
url + ` ${descriptor}${index === ret.length - 1 ? '' : ', '}`);
}, '');
return url;
});
}
exports.processSrcSet = processSrcSet;
此差异已折叠。
...@@ -23,5 +23,11 @@ ...@@ -23,5 +23,11 @@
"main": "dist/index.js" "main": "dist/index.js"
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"gitHead": "56deaeb47d42e924d10282d7af418ccee6b139bf" "gitHead": "56deaeb47d42e924d10282d7af418ccee6b139bf",
"dependencies": {
"clean-css": "^5.1.3",
"postcss-import": "^14.0.2",
"postcss-load-config": "^3.1.0",
"postcss-modules": "^4.1.3"
}
} }
...@@ -7,17 +7,22 @@ import { uniManifestJsonPlugin } from './plugins/manifestJson' ...@@ -7,17 +7,22 @@ import { uniManifestJsonPlugin } from './plugins/manifestJson'
import { uniPagesJsonPlugin } from './plugins/pagesJson' import { uniPagesJsonPlugin } from './plugins/pagesJson'
import { uniResolveIdPlugin } from './plugins/resolveId' import { uniResolveIdPlugin } from './plugins/resolveId'
export default [ const plugins = [
uniResolveIdPlugin(), uniResolveIdPlugin(),
uniCopyPlugin(), uniCopyPlugin(),
uniMainJsPlugin(), uniMainJsPlugin(),
uniManifestJsonPlugin(), uniManifestJsonPlugin(),
uniPagesJsonPlugin(), uniPagesJsonPlugin(),
UniAppPlugin, UniAppPlugin,
]
if (!process.env.UNI_APP_CODE_SPLITING) {
plugins.push(
uniCssPlugin({ uniCssPlugin({
app: fs.readFileSync( app: fs.readFileSync(
require.resolve('@dcloudio/uni-app-plus/dist/style.css'), require.resolve('@dcloudio/uni-app-plus/dist/style.css'),
'utf8' 'utf8'
), ),
}), })
] )
}
export default plugins
import {
isServiceNativeTag,
isServiceCustomElement,
} from '@dcloudio/uni-shared'
import {
parseManifestJsonOnce,
resolveMainPathOnce,
UniVitePlugin,
getNVueCompiler,
getNVueStyleCompiler,
resolveBuiltIn,
} from '@dcloudio/uni-cli-shared'
export const UniAppPlugin: UniVitePlugin = {
name: 'vite:uni-app',
uni: {
compilerOptions: {
isNativeTag: isServiceNativeTag,
isCustomElement: isServiceCustomElement,
},
transformEvent: {
tap: 'click',
},
},
config() {
return {
build: {
rollupOptions: {
input: resolveMainPathOnce(process.env.UNI_INPUT_DIR),
external: ['vue'],
output: {
name: 'AppService',
format: 'iife',
entryFileNames: 'app-service.js',
manualChunks: undefined,
globals: {
vue: 'Vue',
},
},
},
},
}
},
configResolved(config) {
const manifestJson = parseManifestJsonOnce(process.env.UNI_INPUT_DIR)
if (getNVueCompiler(manifestJson) === 'uni-app') {
process.env.UNI_USING_NVUE_COMPILER = 'uni-app'
}
if (getNVueStyleCompiler(manifestJson) === 'uni-app') {
process.env.UNI_USING_NVUE_STYLE_COMPILER = 'uni-app'
}
// 移除 vite 内置的 css post 处理
const index = config.plugins.findIndex((p) => p.name === 'vite:css-post')
if (index > -1) {
;(config.plugins as Plugin[]).splice(index, 1)
}
},
resolveId(id) {
if (id === 'vue') {
return resolveBuiltIn('@dcloudio/uni-app-vue')
}
},
}
import path from 'path'
import slash from 'slash'
import { UserConfig } from 'vite'
import { resolveMainPathOnce } from '@dcloudio/uni-cli-shared'
export const buildOptions: UserConfig['build'] = {
rollupOptions: {
input: resolveMainPathOnce(process.env.UNI_INPUT_DIR),
external: ['vue'],
output: {
name: 'AppService',
format: process.env.UNI_APP_CODE_SPLITING ? 'amd' : 'iife',
entryFileNames: 'app-service.js',
manualChunks: {},
chunkFileNames(chunk) {
if (chunk.isDynamicEntry && chunk.facadeModuleId) {
const filepath = path.relative(
process.env.UNI_INPUT_DIR,
chunk.facadeModuleId
)
return slash(filepath.replace(path.extname(filepath), '.js'))
}
return '[name].js'
},
assetFileNames: '[name][extname]',
globals: {
vue: 'Vue',
},
},
},
}
import { Plugin, ResolvedConfig } from 'vite'
import {
parseManifestJsonOnce,
getNVueCompiler,
getNVueStyleCompiler,
} from '@dcloudio/uni-cli-shared'
import { assetPlugin } from '../plugins/vitejs/plugins/asset'
import { cssPlugin, cssPostPlugin } from '../plugins/vitejs/plugins/css'
export const configResolved: Plugin['configResolved'] = (config) => {
const manifestJson = parseManifestJsonOnce(process.env.UNI_INPUT_DIR)
if (getNVueCompiler(manifestJson) === 'uni-app') {
process.env.UNI_USING_NVUE_COMPILER = 'uni-app'
}
if (getNVueStyleCompiler(manifestJson) === 'uni-app') {
process.env.UNI_USING_NVUE_STYLE_COMPILER = 'uni-app'
}
if (process.env.UNI_APP_CODE_SPLITING) {
initCodeSpliting(config as ResolvedConfig)
} else {
// 移除 vite 内置的 css post 处理,交由 @dcloudio/uni-cli-shared 的 uniCssPlugin 实现
const index = config.plugins.findIndex((p) => p.name === 'vite:css-post')
if (index > -1) {
;(config.plugins as Plugin[]).splice(index, 1)
}
}
}
function initCodeSpliting(config: ResolvedConfig) {
// 替换内置插件
const replacedPlugins = [
assetPlugin(config),
cssPlugin(config),
cssPostPlugin(config),
]
replacedPlugins.forEach((plugin) => {
const index = (config.plugins as Plugin[]).findIndex(
(p) => p.name === plugin.name
)
if (index > -1) {
;(config.plugins as Plugin[]).splice(index, 1, plugin)
}
})
const removedPlugins = ['vite:import-analysis']
removedPlugins.forEach((name) => {
const index = config.plugins.findIndex((p) => p.name === name)
if (index > -1) {
;(config.plugins as Plugin[]).splice(index, 1)
}
})
}
import { UniVitePlugin, resolveBuiltIn } from '@dcloudio/uni-cli-shared'
import { uniOptions } from './uni'
import { buildOptions } from './build'
import { configResolved } from './configResolved'
export const UniAppPlugin: UniVitePlugin = {
name: 'vite:uni-app',
uni: uniOptions,
config() {
return {
build: buildOptions,
}
},
configResolved,
resolveId(id) {
if (id === 'vue') {
return resolveBuiltIn('@dcloudio/uni-app-vue')
}
},
}
import {
isServiceNativeTag,
isServiceCustomElement,
} from '@dcloudio/uni-shared'
import { UniVitePlugin } from '@dcloudio/uni-cli-shared'
export const uniOptions: UniVitePlugin['uni'] = {
compilerOptions: {
isNativeTag: isServiceNativeTag,
isCustomElement: isServiceCustomElement,
},
transformEvent: {
tap: 'click',
},
}
/**
* https://github.com/vitejs/vite/blob/main/packages/vite/src/node/constants.ts
*/
/**
* Prefix for resolved fs paths, since windows paths may not be valid as URLs.
*/
export const FS_PREFIX = `/@fs/`
export const CLIENT_PUBLIC_PATH = `/@vite/client`
/**
* https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/asset.ts
*/
import path from 'path'
import { parse as parseUrl } from 'url'
import fs, { promises as fsp } from 'fs'
import mime from 'mime/lite'
import { Plugin } from 'vite'
import { ResolvedConfig } from 'vite'
import { cleanUrl } from '../utils'
import { FS_PREFIX } from '../constants'
import { PluginContext, RenderedChunk } from 'rollup'
import MagicString from 'magic-string'
import { createHash } from 'crypto'
export const assetUrlRE = /__VITE_ASSET__([a-z\d]{8})__(?:\$_(.*?)__)?/g
// urls in JS must be quoted as strings, so when replacing them we need
// a different regex
const assetUrlQuotedRE = /"__VITE_ASSET__([a-z\d]{8})__(?:\$_(.*?)__)?"/g
const rawRE = /(\?|&)raw(?:&|$)/
const urlRE = /(\?|&)url(?:&|$)/
export const chunkToEmittedAssetsMap = new WeakMap<RenderedChunk, Set<string>>()
const assetCache = new WeakMap<ResolvedConfig, Map<string, string>>()
const assetHashToFilenameMap = new WeakMap<
ResolvedConfig,
Map<string, string>
>()
// save hashes of the files that has been emitted in build watch
const emittedHashMap = new WeakMap<ResolvedConfig, Set<string>>()
/**
* Also supports loading plain strings with import text from './foo.txt?raw'
*/
export function assetPlugin(config: ResolvedConfig): Plugin {
// assetHashToFilenameMap initialization in buildStart causes getAssetFilename to return undefined
assetHashToFilenameMap.set(config, new Map())
return {
name: 'vite:asset',
buildStart() {
assetCache.set(config, new Map())
emittedHashMap.set(config, new Set())
},
resolveId(id) {
if (!config.assetsInclude(cleanUrl(id))) {
return
}
// imports to absolute urls pointing to files in /public
// will fail to resolve in the main resolver. handle them here.
const publicFile = checkPublicFile(id, config)
if (publicFile) {
return id
}
},
async load(id) {
if (id.startsWith('\0')) {
// Rollup convention, this id should be handled by the
// plugin that marked it with \0
return
}
// raw requests, read from disk
if (rawRE.test(id)) {
const file = checkPublicFile(id, config) || cleanUrl(id)
// raw query, read file and return as string
return `export default ${JSON.stringify(
await fsp.readFile(file, 'utf-8')
)}`
}
if (!config.assetsInclude(cleanUrl(id)) && !urlRE.test(id)) {
return
}
id = id.replace(urlRE, '$1').replace(/[\?&]$/, '')
const url = await fileToUrl(id, config, this)
return `export default ${JSON.stringify(url)}`
},
renderChunk(code, chunk) {
let match: RegExpExecArray | null
let s: MagicString | undefined
while ((match = assetUrlQuotedRE.exec(code))) {
s = s || (s = new MagicString(code))
const [full, hash, postfix = ''] = match
// some internal plugins may still need to emit chunks (e.g. worker) so
// fallback to this.getFileName for that.
const file = getAssetFilename(hash, config) || this.getFileName(hash)
registerAssetToChunk(chunk, file)
const outputFilepath = config.base + file + postfix
s.overwrite(
match.index,
match.index + full.length,
JSON.stringify(outputFilepath)
)
}
if (s) {
return {
code: s.toString(),
map: config.build.sourcemap ? s.generateMap({ hires: true }) : null,
}
} else {
return null
}
},
generateBundle(_, bundle) {
// do not emit assets for SSR build
if (config.command === 'build' && config.build.ssr) {
for (const file in bundle) {
if (
bundle[file].type === 'asset' &&
!file.includes('ssr-manifest.json')
) {
delete bundle[file]
}
}
}
},
}
}
export function registerAssetToChunk(chunk: RenderedChunk, file: string): void {
let emitted = chunkToEmittedAssetsMap.get(chunk)
if (!emitted) {
emitted = new Set()
chunkToEmittedAssetsMap.set(chunk, emitted)
}
emitted.add(cleanUrl(file))
}
export function checkPublicFile(
url: string,
{ publicDir }: ResolvedConfig
): string | undefined {
// note if the file is in /public, the resolver would have returned it
// as-is so it's not going to be a fully resolved path.
if (!publicDir || !url.startsWith('/')) {
return
}
const publicFile = path.join(publicDir, cleanUrl(url))
if (fs.existsSync(publicFile)) {
return publicFile
} else {
return
}
}
export function fileToUrl(
id: string,
config: ResolvedConfig,
ctx: PluginContext
): string | Promise<string> {
if (config.command === 'serve') {
return fileToDevUrl(id, config)
} else {
return fileToBuiltUrl(id, config, ctx)
}
}
function fileToDevUrl(id: string, config: ResolvedConfig) {
let rtn: string
if (checkPublicFile(id, config)) {
// in public dir, keep the url as-is
rtn = id
} else if (id.startsWith(config.root)) {
// in project root, infer short public path
rtn = '/' + path.posix.relative(config.root, id)
} else {
// outside of project root, use absolute fs path
// (this is special handled by the serve static middleware
rtn = path.posix.join(FS_PREFIX + id)
}
return config.base + rtn.replace(/^\//, '')
}
export function getAssetFilename(
hash: string,
config: ResolvedConfig
): string | undefined {
return assetHashToFilenameMap.get(config)?.get(hash)
}
/**
* Register an asset to be emitted as part of the bundle (if necessary)
* and returns the resolved public URL
*/
async function fileToBuiltUrl(
id: string,
config: ResolvedConfig,
pluginContext: PluginContext,
skipPublicCheck = false
): Promise<string> {
if (!skipPublicCheck && checkPublicFile(id, config)) {
return config.base + id.slice(1)
}
const cache = assetCache.get(config)!
const cached = cache.get(id)
if (cached) {
return cached
}
const file = cleanUrl(id)
const content = await fsp.readFile(file)
let url: string
if (
config.build.lib ||
(!file.endsWith('.svg') &&
content.length < Number(config.build.assetsInlineLimit))
) {
// base64 inlined as a string
url = `data:${mime.getType(file)};base64,${content.toString('base64')}`
} else {
// emit as asset
// rollup supports `import.meta.ROLLUP_FILE_URL_*`, but it generates code
// that uses runtime url sniffing and it can be verbose when targeting
// non-module format. It also fails to cascade the asset content change
// into the chunk's hash, so we have to do our own content hashing here.
// https://bundlers.tooling.report/hashing/asset-cascade/
// https://github.com/rollup/rollup/issues/3415
const map = assetHashToFilenameMap.get(config)!
const contentHash = getAssetHash(content)
const { search, hash } = parseUrl(id)
const postfix = (search || '') + (hash || '')
const basename = path.basename(file)
const ext = path.extname(basename)
const fileName = path.posix.join(
config.build.assetsDir,
`${basename.slice(0, -ext.length)}.${contentHash}${ext}`
)
if (!map.has(contentHash)) {
map.set(contentHash, fileName)
}
const emittedSet = emittedHashMap.get(config)!
if (!emittedSet.has(contentHash)) {
pluginContext.emitFile({
fileName,
type: 'asset',
source: content,
})
emittedSet.add(contentHash)
}
url = `__VITE_ASSET__${contentHash}__${postfix ? `$_${postfix}__` : ``}`
}
cache.set(id, url)
return url
}
export function getAssetHash(content: Buffer): string {
return createHash('sha256').update(content).digest('hex').slice(0, 8)
}
export async function urlToBuiltUrl(
url: string,
importer: string,
config: ResolvedConfig,
pluginContext: PluginContext
): Promise<string> {
if (checkPublicFile(url, config)) {
return config.base + url.slice(1)
}
const file = url.startsWith('/')
? path.join(config.root, url)
: path.join(path.dirname(importer), url)
return fileToBuiltUrl(
file,
config,
pluginContext,
// skip public check since we just did it above
true
)
}
此差异已折叠。
/**
* https://github.com/vitejs/vite/blob/main/packages/vite/src/node/utils.ts
*/
import os from 'os'
import path from 'path'
export function slash(p: string): string {
return p.replace(/\\/g, '/')
}
export const bareImportRE = /^[\w@](?!.*:\/\/)/
export const deepImportRE = /^([^@][^/]*)\/|^(@[^/]+\/[^/]+)\//
export const isWindows = os.platform() === 'win32'
export function normalizePath(id: string): string {
return path.posix.normalize(isWindows ? slash(id) : id)
}
export const queryRE = /\?.*$/s
export const hashRE = /#.*$/s
export const cleanUrl = (url: string): string =>
url.replace(hashRE, '').replace(queryRE, '')
export const externalRE = /^(https?:)?\/\//
export const isExternalUrl = (url: string): boolean => externalRE.test(url)
export const dataUrlRE = /^\s*data:/i
export const isDataUrl = (url: string): boolean => dataUrlRE.test(url)
export async function asyncReplace(
input: string,
re: RegExp,
replacer: (match: RegExpExecArray) => string | Promise<string>
): Promise<string> {
let match: RegExpExecArray | null
let remaining = input
let rewritten = ''
while ((match = re.exec(remaining))) {
rewritten += remaining.slice(0, match.index)
rewritten += await replacer(match)
remaining = remaining.slice(match.index + match[0].length)
}
rewritten += remaining
return rewritten
}
export function isObject(value: unknown): value is Record<string, any> {
return Object.prototype.toString.call(value) === '[object Object]'
}
const splitRE = /\r?\n/
const range: number = 2
export function pad(source: string, n = 2): string {
const lines = source.split(splitRE)
return lines.map((l) => ` `.repeat(n) + l).join(`\n`)
}
export function posToNumber(
source: string,
pos: number | { line: number; column: number }
): number {
if (typeof pos === 'number') return pos
const lines = source.split(splitRE)
const { line, column } = pos
let start = 0
for (let i = 0; i < line - 1; i++) {
start += lines[i].length + 1
}
return start + column
}
export function generateCodeFrame(
source: string,
start: number | { line: number; column: number } = 0,
end?: number
): string {
start = posToNumber(source, start)
end = end || start
const lines = source.split(splitRE)
let count = 0
const res: string[] = []
for (let i = 0; i < lines.length; i++) {
count += lines[i].length + 1
if (count >= start) {
for (let j = i - range; j <= i + range || end > count; j++) {
if (j < 0 || j >= lines.length) continue
const line = j + 1
res.push(
`${line}${' '.repeat(Math.max(3 - String(line).length, 0))}| ${
lines[j]
}`
)
const lineLength = lines[j].length
if (j === i) {
// push underline
const pad = start - (count - lineLength) + 1
const length = Math.max(
1,
end > count ? lineLength - pad : end - start
)
res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length))
} else if (j > i) {
if (end > count) {
const length = Math.max(Math.min(end - count, lineLength), 1)
res.push(` | ` + '^'.repeat(length))
}
count += lineLength + 1
}
}
break
}
}
return res.join('\n')
}
interface ImageCandidate {
url: string
descriptor: string
}
const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g
export async function processSrcSet(
srcs: string,
replacer: (arg: ImageCandidate) => Promise<string>
): Promise<string> {
const imageCandidates: ImageCandidate[] = srcs
.split(',')
.map((s) => {
const [url, descriptor] = s
.replace(escapedSpaceCharacters, ' ')
.trim()
.split(' ', 2)
return { url, descriptor }
})
.filter(({ url }) => !!url)
const ret = await Promise.all(
imageCandidates.map(async ({ url, descriptor }) => {
return {
url: await replacer({ url, descriptor }),
descriptor,
}
})
)
const url = ret.reduce((prev, { url, descriptor }, index) => {
descriptor = descriptor || ''
return (prev +=
url + ` ${descriptor}${index === ret.length - 1 ? '' : ', '}`)
}, '')
return url
}
...@@ -3,5 +3,10 @@ ...@@ -3,5 +3,10 @@
"compilerOptions": { "compilerOptions": {
"outDir": "dist" "outDir": "dist"
}, },
"include": ["src", "../shims-node.d.ts", "../shims-uni-app.d.ts"] "include": [
"src",
"types/shims.d.ts",
"../shims-node.d.ts",
"../shims-uni-app.d.ts"
]
} }
/**
Types from https://github.com/rollup/plugins/blob/master/packages/alias/types/index.d.ts
Inlined because the plugin is bundled.
https://github.com/rollup/plugins/blob/master/LICENSE
The MIT License (MIT)
Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import { PluginHooks } from 'rollup'
export interface Alias {
find: string | RegExp
replacement: string
/**
* Instructs the plugin to use an alternative resolving algorithm,
* rather than the Rollup's resolver.
* @default null
*/
customResolver?: ResolverFunction | ResolverObject | null
}
export type ResolverFunction = PluginHooks['resolveId']
export interface ResolverObject {
buildStart?: PluginHooks['buildStart']
resolveId: ResolverFunction
}
/**
* Specifies an `Object`, or an `Array` of `Object`,
* which defines aliases used to replace values in `import` or `require` statements.
* With either format, the order of the entries is important,
* in that the first defined rules are applied first.
*
* This is passed to \@rollup/plugin-alias as the "entries" field
* https://github.com/rollup/plugins/tree/master/packages/alias#entries
*/
export type AliasOptions = readonly Alias[] | { [find: string]: string }
此差异已折叠。
...@@ -181,7 +181,7 @@ function initFeatures(options) { ...@@ -181,7 +181,7 @@ function initFeatures(options) {
__UNI_FEATURE_PULL_DOWN_REFRESH__: pullDownRefresh, __UNI_FEATURE_PULL_DOWN_REFRESH__: pullDownRefresh,
__UNI_FEATURE_NAVIGATIONBAR_BUTTONS__: navigationBarButtons, __UNI_FEATURE_NAVIGATIONBAR_BUTTONS__: navigationBarButtons,
__UNI_FEATURE_NAVIGATIONBAR_SEARCHINPUT__: navigationBarSearchInput, __UNI_FEATURE_NAVIGATIONBAR_SEARCHINPUT__: navigationBarSearchInput,
__UNI_FEATURE_NAVIGATIONBAR_TRANSPARENT__: navigationBarTransparent, __UNI_FEATURE_NAVIGATIONBAR_TRANSPARENT__: navigationBarTransparent, // 是否启用透明标题栏
}; };
// ssr nodejs features // ssr nodejs features
if (options.ssr) { if (options.ssr) {
......
此差异已折叠。
import { isFunction, isSymbol, extend, isMap, isObject, toRawType, def, isArray, isString, isPromise, toHandlerKey, remove, EMPTY_OBJ, camelize, capitalize, normalizeClass, normalizeStyle, isOn, NOOP, isGloballyWhitelisted, isIntegerKey, hasOwn, hasChanged, NO, invokeArrayFns as invokeArrayFns$1, makeMap, isSet, toNumber, hyphenate, isReservedProp, EMPTY_ARR, toTypeString } from '@vue/shared'; import { isFunction, isSymbol, extend, isMap, isObject, toRawType, def, isArray, isString, isPromise, toHandlerKey, remove, EMPTY_OBJ, camelize, capitalize, normalizeClass, normalizeStyle, isOn, NOOP, isGloballyWhitelisted, isIntegerKey, hasOwn, hasChanged, invokeArrayFns as invokeArrayFns$1, makeMap, isSet, NO, toNumber, hyphenate, isReservedProp, EMPTY_ARR, toTypeString } from '@vue/shared';
export { camelize } from '@vue/shared'; export { camelize } from '@vue/shared';
import { injectHook as injectHook$1 } from 'vue'; import { injectHook as injectHook$1 } from 'vue';
......
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册