New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@fmfe/genesis-remote

Package Overview
Dependencies
Maintainers
15
Versions
173
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fmfe/genesis-remote - npm Package Compare versions

Comparing version 0.0.50 to 0.0.51

dist/format.js

587

dist/index.js

@@ -17,280 +17,325 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var axios_1 = __importDefault(require("axios"));
var clientKey = '__remote_view_client_state__';
var serverKey = '__remote_view_server_state__';
var RemoteView = /** @class */ (function () {
function RemoteView() {
/* eslint-disable @typescript-eslint/prefer-for-of */
var vue_1 = __importDefault(require("vue"));
var format_1 = require("./format");
var remoteViewStateKey = '__remote_view_state__';
var isPromise = function (obj) {
return (!!obj &&
(typeof obj === 'object' || typeof obj === 'function') &&
typeof obj.then === 'function');
};
/**
* el 加载的元素
* bool 在 doc 中是否已经存在
*/
var onload = function (el, bool) {
// 暂时先处理成已经加载成功
if (bool === true && !('_loading' in el)) {
return Promise.resolve(true);
}
RemoteView.install = function (_Vue, options) {
var RemoteView = _Vue.extend({
name: 'remote-view',
props: {
method: String,
url: String,
option: Object,
mode: String,
serverCall: Boolean
// 已经加载成功
if (el._loading === false) {
return Promise.resolve(true);
}
// 正在加载中
if (el._loading === true) {
return new Promise(function (resolve) {
el._loadArr.push(resolve);
el._loadArr = [];
});
}
// 首次加载
return new Promise(function (resolve, reject) {
var load = function () {
el._loadArr.forEach(function (fn) { return fn(); });
el._loading = false;
resolve(true);
};
var error = function () {
el._loadArr.forEach(function (fn) { return fn(); });
el._loading = false;
resolve(false);
};
el.addEventListener('load', load, false);
el.addEventListener('error', error, false);
el._loading = true;
el._loadArr = [];
});
};
/**
* 加载样式文件
*/
exports.loadStyle = function (html) {
var doc = document.createDocumentFragment();
var div = document.createElement('div');
div.innerHTML = html;
var arr = [];
var linkArr = document.querySelectorAll('link[rel=stylesheet][href]');
var findOne = function (href) {
for (var i = 0; i < linkArr.length; i++) {
if (linkArr[i].href === href) {
return linkArr[i];
}
}
return null;
};
var installArr = [];
var forEach = function (el) {
if (el instanceof HTMLLinkElement &&
el.rel === 'stylesheet' &&
el.href) {
var docLink = findOne(el.href);
if (docLink) {
arr.push(onload(docLink, true));
return;
}
else {
arr.push(onload(el, false));
}
}
installArr.push(el);
};
for (var i = 0; i < div.children.length; i++) {
forEach(div.children[i]);
}
installArr.forEach(function (el) {
doc.appendChild(el);
});
document.head.appendChild(doc);
return Promise.all(arr);
};
/**
* 加载js文件
*/
exports.loadScript = function (html) {
var doc = document.createDocumentFragment();
var div = document.createElement('div');
div.innerHTML = html;
var arr = [];
var scriptArr = document.querySelectorAll('script[src]');
var findOne = function (src) {
for (var i = 0; i < scriptArr.length; i++) {
if (scriptArr[i].src === src) {
return scriptArr[i];
}
}
return null;
};
var installArr = [];
var forEach = function (el) {
if (el instanceof HTMLScriptElement && el.src) {
var docLink = findOne(el.src);
if (docLink) {
arr.push(onload(docLink, true));
return;
}
else {
var newScript_1 = document.createElement('script');
var attrs = el.getAttributeNames();
newScript_1.async = false;
attrs.forEach(function (attr) {
var value = el.getAttribute(attr);
newScript_1.setAttribute(attr, value);
});
arr.push(onload(newScript_1, false));
installArr.push(newScript_1);
return;
}
}
installArr.push(el);
};
for (var i = 0; i < div.children.length; i++) {
forEach(div.children[i]);
}
installArr.forEach(function (el) {
doc.appendChild(el);
});
document.body.appendChild(doc);
return Promise.all(arr);
};
/**
* 远程调用组件
*/
exports.RemoteView = {
name: 'remote-view',
props: {
fetch: {
type: Function
},
clientFetch: {
type: Function
},
serverFetch: {
type: Function
}
},
data: function () {
return {
// 安装的选项
installOptions: {},
// 远程请求到的数据
localData: {
style: '',
script: '',
html: ''
},
data: function () {
return {
installOptions: {},
html: '',
remote: {},
serverIndex: 0,
appId: 0,
destroyed: false
};
},
created: function () {
var ssrContext = this.$root.$options.ssrContext;
if (!ssrContext) {
return;
}
if (typeof window === 'object') {
this.initClient();
}
else {
this.initServer();
}
},
render: function (h) {
return h('div', {
domProps: {
innerHTML: this.html
}
// 组件渲染的下标
index: 0,
// 应用安装的id
appId: 0,
// 当前组件是否已销毁
destroyed: false
};
},
created: function () {
if (process.env.VUE_ENV === 'client') {
if (!this.$root.$options.clientOptions)
return;
this.initClient();
}
if (process.env.VUE_ENV === 'server') {
if (!this.$root.$options.renderContext)
return;
this.initServer();
}
},
render: function (h) {
return h('div', {
domProps: {
innerHTML: this.localData.html
}
});
},
mounted: function () {
var clientOptions = this.$root.$options.clientOptions;
if (!clientOptions) {
this.clientLoad();
}
},
beforeDestroy: function () {
if (this.appId) {
window.genesis.uninstall(this.appId);
}
this.destroyed = true;
},
methods: {
_fetch: function () {
var fetch = this.fetch;
if (process.env.VUE_ENV === 'server' &&
typeof this.serverFetch === 'function') {
fetch = this.serverFetch;
}
if (process.env.VUE_ENV === 'client' &&
typeof this.clientFetch === 'function') {
fetch = this.clientFetch;
}
if (typeof fetch !== 'function') {
return Promise.resolve(null);
}
var res = fetch();
if (isPromise(res)) {
return res.then(function (data) {
if (typeof data !== 'object')
return null;
return data;
});
},
mounted: function () {
var ssrContext = this.$root.$options.ssrContext;
if (!ssrContext) {
this.clientLoad();
}
return Promise.resolve(null);
},
install: function () {
var _this = this;
this.$nextTick(function () {
var options = __assign(__assign({}, _this.installOptions), { el: _this.$el.firstChild });
if (options.el && window.genesis && !_this.destroyed) {
_this.appId = window.genesis.install(options);
}
else {
this.install();
}
},
beforeDestroy: function () {
if (this.appId) {
window.genesis.uninstall(this.appId);
}
this.destroyed = true;
},
methods: {
install: function () {
var _this = this;
this.$nextTick(function () {
var options = __assign(__assign({}, _this.installOptions), { el: _this.$el.firstChild });
if (options.el &&
window.genesis &&
!_this.destroyed) {
_this.appId = window.genesis.install(options);
}
});
},
initServer: function () {
var ssrContext = this.$root.$options.ssrContext;
var state = ssrContext.data.state;
state[clientKey] = state[clientKey] || [];
state[serverKey] = state[serverKey] || [];
this.serverIndex = state[clientKey].length;
state[serverKey].push(this.remote);
state[clientKey].push(null);
Object.defineProperty(state, serverKey, {
enumerable: false
});
},
initClient: function () {
var ssrContext = this.$root.$options.ssrContext;
var id = ssrContext.state[clientKey].splice(0, 1)[0];
if (!id) {
// 这里服务器端加载失败,要调整到客户端加载
this.clientLoad();
return;
}
var el = document.querySelector("[data-ssr-genesis-id=\"" + id + "\"][data-server-rendered]");
if (!el)
return;
this.html = el.parentNode.innerHTML;
if (!window[id]) {
throw new Error("Context for " + id + " not found");
}
this.installOptions = window[id];
delete window[id];
},
clientLoad: function () {
var _this = this;
axios_1.default.get(this.url).then(function (res) {
if (res.status !== 200 || typeof res.data !== 'object')
return;
return _this.$nextTick().then(function () {
// 这里需要往页面插入样式和js
var temp = document.createElement('div');
temp.innerHTML = res.data.style;
var nodeListToArr = function (nodes) {
var arr = [];
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (var i = 0; i < nodes.length; i++) {
arr.push(nodes[i]);
}
return arr;
};
var stylePromiseArr = [];
var scriptPromiseArr = [];
var styles = nodeListToArr(temp.childNodes).map(function (style) {
if (!(style instanceof HTMLLinkElement) ||
!style.href)
return style;
var attrs = style.getAttributeNames();
var values = [];
attrs.forEach(function (attr) {
var value = style.getAttribute(attr);
values.push("[" + attr + "=\"" + value + "\"]");
});
var existEl = document.querySelector("link" + values.join(''));
// 已经存在
if (existEl) {
// 已经加载完成了
if (!existEl.onload)
return null;
var ready_1;
stylePromiseArr.push(new Promise(function (resolve) {
ready_1 = resolve;
}));
var done_1 = function () {
existEl.removeEventListener('load', done_1, false);
existEl.removeEventListener('error', done_1, false);
ready_1();
};
existEl.addEventListener('load', done_1, false);
existEl.addEventListener('error', done_1, false);
return null;
}
// 首次加载这个样式文件
var ready;
stylePromiseArr.push(new Promise(function (resolve) {
ready = resolve;
}));
var done = function () {
style.onload = null;
style.onerror = null;
console.log('genesis-remote style', style.href);
ready();
};
style.onload = done;
style.onerror = done;
return style;
});
temp.innerHTML =
res.data.script + res.data.scriptState;
console.log(res.data);
var scripts = nodeListToArr(temp.childNodes).map(function (script) {
if (!(script instanceof HTMLScriptElement)) {
return script;
}
var attrs = script.getAttributeNames();
var values = [];
attrs.forEach(function (attr) {
var value = script.getAttribute(attr);
values.push("[" + attr + "=\"" + value + "\"]");
});
var existEl = document.querySelector("script" + values.join(''));
// 已经存在
if (existEl) {
// 已经加载完成了
if (!existEl.onload)
return null;
var ready_2;
scriptPromiseArr.push(new Promise(function (resolve) {
ready_2 = resolve;
}));
var done_2 = function () {
existEl.removeEventListener('load', done_2, false);
existEl.removeEventListener('error', done_2, false);
ready_2();
};
existEl.addEventListener('load', done_2, false);
existEl.addEventListener('error', done_2, false);
return null;
}
// 首次加载这个js文件
var newScript = document.createElement('script');
newScript.async = false;
attrs.forEach(function (attr) {
var value = script.getAttribute(attr);
newScript.setAttribute(attr, value);
});
if (script.innerHTML &&
!script.getAttribute('src')) {
// eslint-disable-next-line no-new-func
new Function(script.innerHTML)();
if (window[res.data.id]) {
window[res.data.id].automount = false;
}
}
if (!script.src)
return script;
var ready;
scriptPromiseArr.push(new Promise(function (resolve) {
ready = resolve;
}));
var done = function () {
newScript.onload = null;
newScript.onerror = null;
console.log('genesis-remote script', newScript.src);
ready();
};
newScript.onload = done;
newScript.onerror = done;
return newScript;
});
var doc = document.createDocumentFragment();
[].concat(styles, scripts).forEach(function (el) {
if (!el)
return;
doc.appendChild(el);
});
document.body.appendChild(doc);
return Promise.all([
Promise.all(stylePromiseArr).then(function () {
_this.html = res.data.html;
}),
Promise.all(scriptPromiseArr)
]).then(function () {
var el = _this.$el.querySelector('[data-ssr-genesis-id="' +
res.data.id +
'"][data-server-rendered]');
if (!el)
return;
_this.installOptions = {
id: res.data.id,
name: res.data.name,
state: res.data.state,
url: res.data.url
};
_this.install();
});
});
});
}
},
serverPrefetch: function () {
var _this = this;
if (this.serverCall === false)
});
},
initServer: function () {
var context = this.$root.$options.renderContext;
var state = context.data.state;
var first = !state[remoteViewStateKey];
state[remoteViewStateKey] = state[remoteViewStateKey] || [];
this.index = state[remoteViewStateKey].length;
state[remoteViewStateKey].push(this.localData);
Object.defineProperty(this.localData, 'style', {
enumerable: false
});
Object.defineProperty(this.localData, 'script', {
enumerable: false
});
Object.defineProperty(this.localData, 'html', {
enumerable: false
});
if (!first)
return;
/**
* 渲染完成后,对js和样式进行去重
*/
context.beforeRender(format_1.beforeRender);
},
initClient: function () {
var clientOptions = this.$root.$options
.clientOptions;
var state = clientOptions.state;
// 热更新可能会不存在数组,或者数组已经被清空了。
if (!state[remoteViewStateKey] ||
!state[remoteViewStateKey].length) {
return this.clientLoad();
}
var data = state[remoteViewStateKey].splice(0, 1)[0];
if (!data.id) {
// 这里服务器端加载失败,要调整到客户端加载
this.clientLoad();
return;
}
var el = document.querySelector("[data-ssr-genesis-id=\"" + data.id + "\"][data-server-rendered]");
if (!el)
return;
this.localData.html = el.parentNode.innerHTML;
this.installOptions = data;
this.install();
},
clientLoad: function () {
var _this = this;
this._fetch().then(function (data) {
if (data === null)
return;
return axios_1.default.get(this.url).then(function (res) {
var ssrContext = _this.$root.$options.ssrContext;
if (ssrContext && res.status === 200) {
_this.html = res.data.html;
res.data.automount = false;
Object.assign(_this.remote, res.data);
ssrContext.data.state[clientKey][_this.serverIndex] =
res.data.id;
}
Promise.all([
exports.loadStyle(data.style).then(function () {
_this.localData = data;
}),
exports.loadScript(data.script).then(function () {
window[data.id] = data.state;
})
]).then(function () {
_this.installOptions = {
id: data.id,
name: data.name,
state: data.state,
url: data.url
};
_this.install();
});
});
}
},
serverPrefetch: function () {
var _this = this;
return this._fetch().then(function (data) {
if (data === null)
return;
var context = _this.$root.$options.renderContext;
if (!context && typeof context !== 'object') {
throw new TypeError('[remote-view] Need to pass context to the root instance of vue');
}
data.automount = false;
Object.assign(_this.localData, data);
});
_Vue.component('remote-view', RemoteView);
};
return RemoteView;
}());
exports.default = RemoteView;
}
};
exports.default = {
install: function (_Vue) {
_Vue.component('remote-view', vue_1.default.extend(exports.RemoteView));
}
};
{
"name": "@fmfe/genesis-remote",
"version": "0.0.50",
"version": "0.0.51",
"description": "",

@@ -12,4 +12,7 @@ "main": "dist/index.js",

"license": "MIT",
"gitHead": "7ac2283c0046b59b6bac6e53688216133343b601",
"sideEffects": false
"gitHead": "05859ebe05d7eafd5ff6bf4b97b7e009e52c4762",
"sideEffects": false,
"devDependencies": {
"@fmfe/genesis-core": "^0.0.51"
}
}

@@ -0,351 +1,360 @@

/* eslint-disable @typescript-eslint/prefer-for-of */
import Vue from 'vue';
import axios from 'axios';
const clientKey = '__remote_view_client_state__';
const serverKey = '__remote_view_server_state__';
import { ClientOptions, RenderContext } from '@fmfe/genesis-core';
import { beforeRender } from './format';
const remoteViewStateKey = '__remote_view_state__';
export default class RemoteView {
public static install<T>(_Vue: typeof Vue, options?: T): void {
const RemoteView = _Vue.extend({
name: 'remote-view',
props: {
method: String,
url: String,
option: Object,
mode: String,
serverCall: Boolean
},
data() {
return {
installOptions: {},
html: '',
remote: {},
serverIndex: 0,
appId: 0,
destroyed: false
};
},
created() {
const ssrContext: any = this.$root.$options.ssrContext;
if (!ssrContext) {
return;
}
if (typeof window === 'object') {
this.initClient();
} else {
this.initServer();
}
},
render(h) {
return h('div', {
domProps: {
innerHTML: this.html
}
});
},
mounted() {
const ssrContext: any = this.$root.$options.ssrContext;
if (!ssrContext) {
this.clientLoad();
} else {
this.install();
}
},
beforeDestroy() {
if (this.appId) {
(window as any).genesis.uninstall(this.appId);
}
this.destroyed = true;
},
methods: {
install() {
this.$nextTick(() => {
const options = {
...this.installOptions,
el: this.$el.firstChild
};
if (
options.el &&
(window as any).genesis &&
!this.destroyed
) {
this.appId = (window as any).genesis.install(
options
);
}
});
},
initServer() {
const ssrContext: any = this.$root.$options.ssrContext;
const state = ssrContext.data.state;
const isPromise = (obj: any) => {
return (
!!obj &&
(typeof obj === 'object' || typeof obj === 'function') &&
typeof obj.then === 'function'
);
};
state[clientKey] = state[clientKey] || [];
state[serverKey] = state[serverKey] || [];
export interface RemoteViewData {
automount: boolean;
html: string;
id: string;
name: string;
style: string;
script: string;
url: string;
state: { [x: string]: any };
}
this.serverIndex = state[clientKey].length;
/**
* el 加载的元素
* bool 在 doc 中是否已经存在
*/
const onload = (el, bool: boolean): Promise<boolean> => {
// 暂时先处理成已经加载成功
if (bool === true && !('_loading' in el)) {
return Promise.resolve(true);
}
// 已经加载成功
if (el._loading === false) {
return Promise.resolve(true);
}
// 正在加载中
if (el._loading === true) {
return new Promise((resolve) => {
el._loadArr.push(resolve);
el._loadArr = [];
});
}
// 首次加载
return new Promise((resolve, reject) => {
const load = () => {
el._loadArr.forEach((fn) => fn());
el._loading = false;
resolve(true);
};
const error = () => {
el._loadArr.forEach((fn) => fn());
el._loading = false;
resolve(false);
};
el.addEventListener('load', load, false);
el.addEventListener('error', error, false);
el._loading = true;
el._loadArr = [];
});
};
state[serverKey].push(this.remote);
state[clientKey].push(null);
/**
* 加载样式文件
*/
export const loadStyle = (html: string): Promise<boolean[]> => {
const doc = document.createDocumentFragment();
const div = document.createElement('div');
div.innerHTML = html;
const arr: Promise<boolean>[] = [];
const linkArr = (document.querySelectorAll(
'link[rel=stylesheet][href]'
) as any) as HTMLLinkElement[];
const findOne = (href: string): HTMLLinkElement | null => {
for (let i = 0; i < linkArr.length; i++) {
if (linkArr[i].href === href) {
return linkArr[i];
}
}
return null;
};
const installArr: Element[] = [];
const forEach = (el: Element) => {
if (
el instanceof HTMLLinkElement &&
el.rel === 'stylesheet' &&
el.href
) {
const docLink = findOne(el.href);
if (docLink) {
arr.push(onload(docLink, true));
return;
} else {
arr.push(onload(el, false));
}
}
installArr.push(el);
};
for (let i = 0; i < div.children.length; i++) {
forEach(div.children[i]);
}
installArr.forEach((el) => {
doc.appendChild(el);
});
document.head.appendChild(doc);
return Promise.all<boolean>(arr);
};
Object.defineProperty(state, serverKey, {
enumerable: false
});
},
initClient() {
const ssrContext: any = this.$root.$options.ssrContext;
const id = ssrContext.state[clientKey].splice(0, 1)[0];
if (!id) {
// 这里服务器端加载失败,要调整到客户端加载
this.clientLoad();
return;
}
const el: any = document.querySelector(
`[data-ssr-genesis-id="${id}"][data-server-rendered]`
);
if (!el) return;
this.html = el.parentNode.innerHTML;
if (!window[id]) {
throw new Error(`Context for ${id} not found`);
}
this.installOptions = window[id];
delete window[id];
},
clientLoad() {
axios.get(this.url).then((res) => {
if (res.status !== 200 || typeof res.data !== 'object')
return;
/**
* 加载js文件
*/
export const loadScript = (html: string): Promise<boolean[]> => {
const doc = document.createDocumentFragment();
const div = document.createElement('div');
div.innerHTML = html;
const arr: Promise<boolean>[] = [];
const scriptArr = (document.querySelectorAll(
'script[src]'
) as any) as HTMLScriptElement[];
const findOne = (src: string): HTMLScriptElement | null => {
for (let i = 0; i < scriptArr.length; i++) {
if (scriptArr[i].src === src) {
return scriptArr[i];
}
}
return null;
};
const installArr: Element[] = [];
const forEach = (el: Element) => {
if (el instanceof HTMLScriptElement && el.src) {
const docLink = findOne(el.src);
if (docLink) {
arr.push(onload(docLink, true));
return;
} else {
const newScript = document.createElement('script');
const attrs = el.getAttributeNames();
newScript.async = false;
attrs.forEach((attr) => {
const value = el.getAttribute(attr)!;
newScript.setAttribute(attr, value);
});
arr.push(onload(newScript, false));
installArr.push(newScript);
return;
}
}
installArr.push(el);
};
for (let i = 0; i < div.children.length; i++) {
forEach(div.children[i]);
}
installArr.forEach((el) => {
doc.appendChild(el);
});
document.body.appendChild(doc);
return Promise.all<boolean>(arr);
};
return this.$nextTick().then(() => {
// 这里需要往页面插入样式和js
const temp = document.createElement('div');
temp.innerHTML = res.data.style;
const nodeListToArr = (nodes: any) => {
const arr: any[] = [];
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (let i = 0; i < nodes.length; i++) {
arr.push(nodes[i]);
}
return arr;
};
const stylePromiseArr: Promise<any>[] = [];
const scriptPromiseArr: Promise<any>[] = [];
const styles = nodeListToArr(temp.childNodes).map(
(style: HTMLStyleElement | HTMLLinkElement) => {
if (
!(style instanceof HTMLLinkElement) ||
!style.href
)
return style;
/**
* 远程调用组件
*/
export const RemoteView: any = {
name: 'remote-view',
props: {
fetch: {
type: Function
},
clientFetch: {
type: Function
},
serverFetch: {
type: Function
}
},
data() {
return {
// 安装的选项
installOptions: {},
// 远程请求到的数据
localData: {
style: '',
script: '',
html: ''
},
// 组件渲染的下标
index: 0,
// 应用安装的id
appId: 0,
// 当前组件是否已销毁
destroyed: false
};
},
created() {
if (process.env.VUE_ENV === 'client') {
if (!this.$root.$options.clientOptions) return;
this.initClient();
}
if (process.env.VUE_ENV === 'server') {
if (!this.$root.$options.renderContext) return;
this.initServer();
}
},
render(h) {
return h('div', {
domProps: {
innerHTML: this.localData.html
}
});
},
mounted() {
const clientOptions: ClientOptions = this.$root.$options.clientOptions;
if (!clientOptions) {
this.clientLoad();
}
},
beforeDestroy() {
if (this.appId) {
(window as any).genesis.uninstall(this.appId);
}
this.destroyed = true;
},
methods: {
_fetch(): Promise<RemoteViewData | null> {
let fetch = this.fetch;
if (
process.env.VUE_ENV === 'server' &&
typeof this.serverFetch === 'function'
) {
fetch = this.serverFetch;
}
if (
process.env.VUE_ENV === 'client' &&
typeof this.clientFetch === 'function'
) {
fetch = this.clientFetch;
}
if (typeof fetch !== 'function') {
return Promise.resolve(null);
}
const res = fetch();
if (isPromise(res)) {
return res.then((data: RemoteViewData | null) => {
if (typeof data !== 'object') return null;
return data;
});
}
return Promise.resolve(null);
},
install() {
this.$nextTick(() => {
const options = {
...this.installOptions,
el: this.$el.firstChild
};
if (options.el && (window as any).genesis && !this.destroyed) {
this.appId = (window as any).genesis.install(options);
}
});
},
initServer() {
const context: RenderContext = this.$root.$options.renderContext;
const state = context.data.state;
const first = !state[remoteViewStateKey];
state[remoteViewStateKey] = state[remoteViewStateKey] || [];
const attrs = style.getAttributeNames();
const values: string[] = [];
attrs.forEach((attr) => {
const value = style.getAttribute(attr)!;
values.push(`[${attr}="${value}"]`);
});
const existEl = document.querySelector(
`link${values.join('')}`
) as HTMLLinkElement | null;
// 已经存在
if (existEl) {
// 已经加载完成了
if (!existEl.onload) return null;
let ready;
stylePromiseArr.push(
new Promise((resolve) => {
ready = resolve;
})
);
const done = () => {
existEl.removeEventListener(
'load',
done,
false
);
existEl.removeEventListener(
'error',
done,
false
);
ready();
};
existEl.addEventListener(
'load',
done,
false
);
existEl.addEventListener(
'error',
done,
false
);
return null;
}
// 首次加载这个样式文件
let ready;
stylePromiseArr.push(
new Promise((resolve) => {
ready = resolve;
})
);
const done = () => {
style.onload = null;
style.onerror = null;
console.log(
'genesis-remote style',
style.href
);
ready();
};
style.onload = done;
style.onerror = done;
return style;
}
);
this.index = state[remoteViewStateKey].length;
state[remoteViewStateKey].push(this.localData);
temp.innerHTML =
res.data.script + res.data.scriptState;
console.log(res.data);
const scripts = nodeListToArr(temp.childNodes).map(
(script: HTMLScriptElement) => {
if (
!(script instanceof HTMLScriptElement)
) {
return script;
}
const attrs = script.getAttributeNames();
const values: string[] = [];
attrs.forEach((attr) => {
const value = script.getAttribute(
attr
)!;
values.push(`[${attr}="${value}"]`);
});
const existEl = document.querySelector(
`script${values.join('')}`
) as HTMLScriptElement | null;
// 已经存在
if (existEl) {
// 已经加载完成了
if (!existEl.onload) return null;
let ready;
scriptPromiseArr.push(
new Promise((resolve) => {
ready = resolve;
})
);
const done = () => {
existEl.removeEventListener(
'load',
done,
false
);
existEl.removeEventListener(
'error',
done,
false
);
ready();
};
existEl.addEventListener(
'load',
done,
false
);
existEl.addEventListener(
'error',
done,
false
);
return null;
}
// 首次加载这个js文件
const newScript = document.createElement(
'script'
);
newScript.async = false;
attrs.forEach((attr) => {
const value = script.getAttribute(
attr
)!;
newScript.setAttribute(attr, value);
});
if (
script.innerHTML &&
!script.getAttribute('src')
) {
// eslint-disable-next-line no-new-func
new Function(script.innerHTML)();
if (window[res.data.id]) {
(window as any)[
res.data.id
].automount = false;
}
}
if (!script.src) return script;
let ready;
scriptPromiseArr.push(
new Promise((resolve) => {
ready = resolve;
})
);
const done = () => {
newScript.onload = null;
newScript.onerror = null;
console.log(
'genesis-remote script',
newScript.src
);
ready();
};
newScript.onload = done;
newScript.onerror = done;
return newScript;
}
);
const doc = document.createDocumentFragment();
[].concat(styles, scripts).forEach((el) => {
if (!el) return;
doc.appendChild(el);
});
document.body.appendChild(doc);
return Promise.all([
Promise.all(stylePromiseArr).then(() => {
this.html = res.data.html;
}),
Promise.all(scriptPromiseArr)
]).then(() => {
const el = this.$el.querySelector(
'[data-ssr-genesis-id="' +
res.data.id +
'"][data-server-rendered]'
);
if (!el) return;
this.installOptions = {
id: res.data.id,
name: res.data.name,
state: res.data.state,
url: res.data.url
};
this.install();
});
});
});
}
},
serverPrefetch(this: any) {
if (this.serverCall === false) return;
return axios.get(this.url).then((res) => {
const ssrContext = this.$root.$options.ssrContext;
if (ssrContext && res.status === 200) {
this.html = res.data.html;
res.data.automount = false;
Object.assign(this.remote, res.data);
ssrContext.data.state[clientKey][this.serverIndex] =
res.data.id;
}
Object.defineProperty(this.localData, 'style', {
enumerable: false
});
Object.defineProperty(this.localData, 'script', {
enumerable: false
});
Object.defineProperty(this.localData, 'html', {
enumerable: false
});
if (!first) return;
/**
* 渲染完成后,对js和样式进行去重
*/
context.beforeRender(beforeRender);
},
initClient() {
const clientOptions: ClientOptions = this.$root.$options
.clientOptions;
const state = clientOptions.state;
// 热更新可能会不存在数组,或者数组已经被清空了。
if (
!state[remoteViewStateKey] ||
!state[remoteViewStateKey].length
) {
return this.clientLoad();
}
const data = state[remoteViewStateKey].splice(0, 1)[0];
if (!data.id) {
// 这里服务器端加载失败,要调整到客户端加载
this.clientLoad();
return;
}
const el: any = document.querySelector(
`[data-ssr-genesis-id="${data.id}"][data-server-rendered]`
);
if (!el) return;
this.localData.html = el.parentNode.innerHTML;
this.installOptions = data;
this.install();
},
clientLoad() {
this._fetch().then((data: RemoteViewData) => {
if (data === null) return;
Promise.all([
loadStyle(data.style).then(() => {
this.localData = data;
}),
loadScript(data.script).then(() => {
(window as any)[data.id] = data.state;
})
]).then(() => {
this.installOptions = {
id: data.id,
name: data.name,
state: data.state,
url: data.url
};
this.install();
});
});
}
},
serverPrefetch(this: any) {
return this._fetch().then((data: RemoteViewData | null) => {
if (data === null) return;
const context: RenderContext = this.$root.$options.renderContext;
if (!context && typeof context !== 'object') {
throw new TypeError(
'[remote-view] Need to pass context to the root instance of vue'
);
}
data.automount = false;
Object.assign(this.localData, data);
});
_Vue.component('remote-view', RemoteView);
}
};
export default {
install(_Vue: typeof Vue): void {
_Vue.component('remote-view', Vue.extend(RemoteView));
}
};
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
renderContext?: RenderContext;
clientOptions?: ClientOptions;
}
}
import Vue from 'vue';
export default class RemoteView {
static install<T>(_Vue: typeof Vue, options?: T): void;
import { ClientOptions } from '@fmfe/genesis-core';
export interface RemoteViewData {
automount: boolean;
html: string;
id: string;
name: string;
style: string;
script: string;
url: string;
state: {
[x: string]: any;
};
}
/**
* 加载样式文件
*/
export declare const loadStyle: (html: string) => Promise<boolean[]>;
/**
* 加载js文件
*/
export declare const loadScript: (html: string) => Promise<boolean[]>;
/**
* 远程调用组件
*/
export declare const RemoteView: any;
declare const _default: {
install(_Vue: import("vue").VueConstructor<Vue>): void;
};
export default _default;
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
renderContext?: RenderContext;
clientOptions?: ClientOptions;
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc