diff --git a/packages/miniapp-builder-shared/CHANGELOG.md b/packages/miniapp-builder-shared/CHANGELOG.md
index 789a78aa..0d87ecd8 100644
--- a/packages/miniapp-builder-shared/CHANGELOG.md
+++ b/packages/miniapp-builder-shared/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## [0.2.11]
+
+### Added
+
+- Add ComponentWrapper
+
## [0.2.10] - 2021-08-05
### Changed
diff --git a/packages/miniapp-builder-shared/package.json b/packages/miniapp-builder-shared/package.json
index 54f6c4a7..fb5a941b 100644
--- a/packages/miniapp-builder-shared/package.json
+++ b/packages/miniapp-builder-shared/package.json
@@ -1,6 +1,6 @@
{
"name": "miniapp-builder-shared",
- "version": "0.2.10",
+ "version": "0.2.11",
"description": "miniapp project builder shared lib",
"author": "Rax Team",
"homepage": "https://github.com/raxjs/miniapp#readme",
diff --git a/packages/miniapp-builder-shared/src/componentWrapper.js b/packages/miniapp-builder-shared/src/componentWrapper.js
new file mode 100644
index 00000000..65d2b03d
--- /dev/null
+++ b/packages/miniapp-builder-shared/src/componentWrapper.js
@@ -0,0 +1,4 @@
+module.exports = {
+ WrapperPackage: 'rax-componentwrapper',
+ WrapperElement: 'component-wrapper'
+};
diff --git a/packages/miniapp-builder-shared/src/index.js b/packages/miniapp-builder-shared/src/index.js
index 4c9485f0..73396f98 100644
--- a/packages/miniapp-builder-shared/src/index.js
+++ b/packages/miniapp-builder-shared/src/index.js
@@ -5,6 +5,7 @@ const pathHelper = require('./pathHelper');
const platformMap = require('./platformMap');
const constants = require('./constants');
const autoInstallNpm = require('./autoInstallNpm');
+const componentWrapper = require('./componentWrapper');
module.exports = {
filterNativePages,
@@ -13,5 +14,6 @@ module.exports = {
pathHelper,
platformMap,
constants,
- autoInstallNpm
+ autoInstallNpm,
+ componentWrapper
};
diff --git a/packages/miniapp-render/CHANGELOG.md b/packages/miniapp-render/CHANGELOG.md
index 0905bdc7..657492ea 100644
--- a/packages/miniapp-render/CHANGELOG.md
+++ b/packages/miniapp-render/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## [2.9.0] - 2021-09-23
+
+### Added
+
+- Use Component.setData in `rax-componentwrapper`
+
## [2.8.3] - 2021-09-09
### Changed
diff --git a/packages/miniapp-render/package.json b/packages/miniapp-render/package.json
index 1f06de35..f48f1362 100644
--- a/packages/miniapp-render/package.json
+++ b/packages/miniapp-render/package.json
@@ -1,6 +1,6 @@
{
"name": "miniapp-render",
- "version": "2.8.3",
+ "version": "2.9.0",
"description": "DOM simulator for MiniApp",
"files": [
"dist"
diff --git a/packages/miniapp-render/src/bridge/lifeCycleAdapter.js b/packages/miniapp-render/src/bridge/lifeCycleAdapter.js
index caf98cdf..dd0b78a8 100644
--- a/packages/miniapp-render/src/bridge/lifeCycleAdapter.js
+++ b/packages/miniapp-render/src/bridge/lifeCycleAdapter.js
@@ -1,7 +1,7 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { isMiniApp } from 'universal-env';
-export function getComponentLifeCycle({ mount, unmount, update }) {
+export function getComponentLifeCycle({ mount, unmount, update, onInit }) {
if (isMiniApp) {
return {
didMount(...args) {
@@ -12,6 +12,9 @@ export function getComponentLifeCycle({ mount, unmount, update }) {
},
didUnmount(...args) {
unmount && unmount.apply(this, args);
+ },
+ onInit(...args) {
+ onInit && onInit.apply(this, args);
}
};
} else {
diff --git a/packages/miniapp-render/src/constants.js b/packages/miniapp-render/src/constants.js
index c2857c52..392ca49d 100644
--- a/packages/miniapp-render/src/constants.js
+++ b/packages/miniapp-render/src/constants.js
@@ -44,3 +44,11 @@ export const CATCH_COMPONENTS = new Set(isBaiduSmartProgram || isKuaiShouMiniPro
export const APPEAR_COMPONENT = 'view'; // Without appear event components
export const ANCHOR_COMPONENT = 'scroll-view'; // Components which only use scrollIntoView to scroll
+
+export const COMPONENT_WRAPPER = 'component-wrapper'; // rax-componentwrapper tag
+
+export const NATIVE_TYPES = {
+ customComponent: 'customComponent',
+ miniappPlugin: 'miniappPlugin',
+ componentWrapper: 'componentWrapper'
+};
diff --git a/packages/miniapp-render/src/createConfig/element.js b/packages/miniapp-render/src/createConfig/element.js
index 8a8493aa..9da1837f 100644
--- a/packages/miniapp-render/src/createConfig/element.js
+++ b/packages/miniapp-render/src/createConfig/element.js
@@ -3,6 +3,7 @@ import { isMiniApp } from 'universal-env';
import createEventProxy from '../bridge/createEventProxy';
import cache from '../utils/cache';
import { getComponentLifeCycle } from '../bridge/lifeCycleAdapter';
+import { COMPONENT_WRAPPER } from '../constants';
export default function() {
if (isMiniApp) {
@@ -14,6 +15,16 @@ export default function() {
...getComponentLifeCycle({
mount() {
cache.setElementInstance(this);
+ const node = cache.getNode(this.props.r.nodeId);
+ if (node) {
+ node._internal = this;
+ node.__isCustomComponentRoot = true; // add __isCustomComponentRoot tag to mark the custom component when getting native component instance
+ }
+ },
+ onInit() {
+ if (this.props.__tag === COMPONENT_WRAPPER) {
+ this.data = this.props; // init set data
+ }
}
})
};
diff --git a/packages/miniapp-render/src/document.js b/packages/miniapp-render/src/document.js
index 6252f22b..f3ff6b32 100755
--- a/packages/miniapp-render/src/document.js
+++ b/packages/miniapp-render/src/document.js
@@ -10,7 +10,8 @@ import Textarea from './node/element/textarea';
import Video from './node/element/video';
import CustomComponent from './node/element/custom-component';
import RootElement from './node/root';
-import { BODY_NODE_ID } from './constants';
+import { BODY_NODE_ID, COMPONENT_WRAPPER, NATIVE_TYPES } from './constants';
+import ComponentWrapper from './node/element/component-wrapper';
const CONSTRUCTOR_MAP = new Map([['img', Image], ['input', Input], ['textarea', Textarea], ['video', Video]]);
@@ -61,11 +62,15 @@ class Document extends EventTarget {
if (options.attrs.__native) {
if (this.usingComponents[options.tagName]) {
+ if (options.tagName === COMPONENT_WRAPPER) {
+ options.nativeType = NATIVE_TYPES.componentWrapper;
+ return new ComponentWrapper(options);
+ }
// Transform to custom-component
- options.nativeType = 'customComponent';
+ options.nativeType = NATIVE_TYPES.customComponent;
return new CustomComponent(options);
} else if (this.usingPlugins[options.tagName]) {
- options.nativeType = 'miniappPlugin';
+ options.nativeType = NATIVE_TYPES.miniappPlugin;
return new CustomComponent(options);
}
} else {
diff --git a/packages/miniapp-render/src/node/element.js b/packages/miniapp-render/src/node/element.js
index 3fa441d0..50c0c18f 100755
--- a/packages/miniapp-render/src/node/element.js
+++ b/packages/miniapp-render/src/node/element.js
@@ -53,6 +53,9 @@ class Element extends Node {
}
_triggerUpdate(payload, immediate = true) {
+ payload.nodeId = this.__nodeId;
+ payload.componentWrapperId = this.componentWrapperId;
+
if (immediate) {
this._enqueueRender(payload);
} else {
@@ -421,7 +424,6 @@ class Element extends Node {
replaceChild(node, old) {
if (!(node instanceof Node) || !(old instanceof Node)) return;
-
const replaceIndex = this.childNodes.indexOf(old);
if (replaceIndex !== -1) this.childNodes.splice(replaceIndex, 1);
diff --git a/packages/miniapp-render/src/node/element/component-wrapper.js b/packages/miniapp-render/src/node/element/component-wrapper.js
new file mode 100644
index 00000000..55d00efc
--- /dev/null
+++ b/packages/miniapp-render/src/node/element/component-wrapper.js
@@ -0,0 +1,29 @@
+import { omitFalsyFields } from '../../utils/tool';
+import Element from '../element';
+
+class ComponentWrapper extends Element {
+ constructor(options) {
+ super(options);
+ this.__nativeType = options.nativeType;
+ this.__componentWrapperId = this.__nodeId;
+ }
+
+ _destroy() {
+ super._destroy();
+ this.__nativeType = null;
+ this.__componentWrapperId = null;
+ }
+
+ get _renderInfo() {
+ const renderInfo = omitFalsyFields({
+ nodeId: this.__nodeId,
+ nodeType: this.__tagName,
+ style: this.style.cssText,
+ class: this.className,
+ ...this.__attrs.__value
+ }, ['class', 'style']);
+ return renderInfo;
+ }
+}
+
+export default ComponentWrapper;
diff --git a/packages/miniapp-render/src/node/element/custom-component.js b/packages/miniapp-render/src/node/element/custom-component.js
index 351817df..b7c17db8 100755
--- a/packages/miniapp-render/src/node/element/custom-component.js
+++ b/packages/miniapp-render/src/node/element/custom-component.js
@@ -1,6 +1,7 @@
import Element from '../element';
import cache from '../../utils/cache';
import { getId, omitFalsyFields } from '../../utils/tool';
+import { NATIVE_TYPES } from '../../constants';
class CustomComponent extends Element {
constructor(options) {
@@ -25,9 +26,9 @@ class CustomComponent extends Element {
const config = cache.getConfig();
let nativeInfo = null;
- if (this.__nativeType === 'customComponent') {
+ if (this.__nativeType === NATIVE_TYPES.customComponent) {
nativeInfo = config.usingComponents[this.__tagName];
- } else if (this.__nativeType === 'miniappPlugin') {
+ } else if (this.__nativeType === NATIVE_TYPES.miniappPlugin) {
nativeInfo = config.usingPlugins[this.__tagName];
}
if (nativeInfo) {
diff --git a/packages/miniapp-render/src/node/node.js b/packages/miniapp-render/src/node/node.js
index 67596f93..80012464 100755
--- a/packages/miniapp-render/src/node/node.js
+++ b/packages/miniapp-render/src/node/node.js
@@ -15,6 +15,7 @@ class Node extends EventTarget {
this.parentNode = null;
this.__rendered = false;
this.__ownerDocument = options.document;
+ this.__componentWrapperId = null; // ComponentWrapper Id which this belongs to
}
get __pageId() {
@@ -60,6 +61,16 @@ class Node extends EventTarget {
return this.__rendered;
}
+ get componentWrapperId() {
+ if (this.__componentWrapperId) {
+ return this.__componentWrapperId;
+ }
+ if (this.parentNode) {
+ this.__componentWrapperId = this.parentNode.componentWrapperId;
+ }
+ return this.__componentWrapperId;
+ }
+
get nodeValue() {
return null;
}
diff --git a/packages/miniapp-render/src/node/root.js b/packages/miniapp-render/src/node/root.js
index 048db5a4..66d008c9 100644
--- a/packages/miniapp-render/src/node/root.js
+++ b/packages/miniapp-render/src/node/root.js
@@ -1,8 +1,110 @@
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { isMiniApp } from 'universal-env';
+
import Element from './element';
import cache from '../utils/cache';
import perf from '../utils/perf';
import { isFunction } from '../utils/tool';
+/**
+ * Return a function that filter render stacks by whether task occurs in Component-Wrapper
+ */
+function getFilterRenderStacks() {
+ if (isMiniApp) {
+ // In Miniapp, if sdk version != 2.x and can't use component 2, all stacks shall be passed by Page.setData although in Component-Wrapper
+ if (my.SDKVersion.startsWith('2') || my.canIUse('component2')) {
+ return (renderStacks) => {
+ const rootStacks = [];
+ const componentWrapperObject = Object.create(null);
+
+ renderStacks.forEach(task => {
+ const path = task.path;
+ let componentWrapperNode = null;
+ if (task.componentWrapperId) {
+ componentWrapperNode = cache.getNode(task.componentWrapperId);
+ }
+ if (componentWrapperNode) {
+ if (!componentWrapperObject[task.componentWrapperId]) {
+ componentWrapperObject[task.componentWrapperId] = {
+ node: componentWrapperNode,
+ data: []
+ };
+ }
+ componentWrapperObject[task.componentWrapperId].data.push({
+ ...task,
+ path: 'r' + path.replace(componentWrapperNode._path, '')
+ });
+ } else {
+ rootStacks.push(task);
+ }
+ });
+ return {
+ rootStacks,
+ componentWrapperObject
+ };
+ };
+ }
+
+ return (renderStacks) => {
+ return {
+ rootStacks: renderStacks,
+ componentWrapperObject: Object.create(null)
+ };
+ };
+ }
+
+ return (renderStacks) => {
+ const rootStacks = [];
+ const componentWrapperObject = Object.create(null);
+ const renderObject = Object.create(null);
+ const childrenValuePaths = [];
+
+ renderStacks.forEach(task => {
+ const path = task.path;
+ if (task.type === 'children') {
+ childrenValuePaths.push(path);
+ }
+ renderObject[path] = task;
+ });
+
+ for (const path in renderObject) {
+ // If the whole father children path is set, then its children path can be deleted
+ childrenValuePaths.forEach(cp => {
+ if (path.includes(cp) && cp !== path) {
+ delete renderObject[path];
+ }
+ });
+
+ const task = renderObject[path];
+ if (task) {
+ let componentWrapperNode = null;
+ if (task.componentWrapperId) {
+ componentWrapperNode = cache.getNode(task.componentWrapperId);
+ }
+ if (componentWrapperNode) {
+ if (!componentWrapperObject[task.componentWrapperId]) {
+ componentWrapperObject[task.componentWrapperId] = {
+ node: componentWrapperNode,
+ data: []
+ };
+ }
+ componentWrapperObject[task.componentWrapperId].data.push({
+ ...task,
+ path: 'r' + path.replace(componentWrapperNode._path, '')
+ });
+ } else {
+ rootStacks.push(task);
+ }
+ }
+ }
+
+ return {
+ rootStacks,
+ componentWrapperObject
+ };
+ };
+}
+
class RootElement extends Element {
constructor(options) {
super(options);
@@ -10,6 +112,7 @@ class RootElement extends Element {
this.__allowRender = true;
this.__renderStacks = [];
this.__renderCallbacks = [];
+ this._filterRenderStacks = getFilterRenderStacks();
}
_destroy() {
@@ -47,60 +150,13 @@ class RootElement extends Element {
const { mainPackageName } = cache.getConfig();
const window = cache.getWindow(mainPackageName);
- if (internal.$batchedUpdates) {
- let callback;
- // there is no need to aggregate arrays if $batchedUpdate and $spliceData exist
- internal.$batchedUpdates(() => {
- this.__renderStacks.forEach((task, index) => {
- if (index === this.__renderStacks.length - 1) {
- callback = () => {
- window._trigger('setDataFinished');
- if (process.env.NODE_ENV === 'development') {
- perf.stop('setData');
- }
- let fn;
- while (fn = this.__renderCallbacks.pop()) {
- fn();
- }
- };
- internal.firstRenderCallback();
- }
- if (task.type === 'children') {
- const spliceArgs = [task.start, task.deleteCount];
- internal.$spliceData({
- [task.path]: task.item ? spliceArgs.concat(task.item) : spliceArgs
- }, callback);
- } else {
- internal.setData({
- [task.path]: task.value
- }, callback);
- }
- });
- });
- } else {
- const renderObject = Object.create(null);
- const childrenValuePaths = [];
- this.__renderStacks.forEach(task => {
- const path = task.path;
- if (task.type === 'children') {
- childrenValuePaths.push(path);
- }
- renderObject[path] = task.value;
- });
- for (const path in renderObject) {
- // If the whole father children path is set, then its children path can be deleted
- childrenValuePaths.forEach(cp => {
- if (path.includes(cp) && cp !== path) {
- delete renderObject[path];
- }
- });
- const value = renderObject[path];
- if (isFunction(value)) {
- renderObject[path] = value();
- }
- }
- internal.firstRenderCallback(renderObject);
- internal.setData(renderObject, () => {
+ const { rootStacks, componentWrapperObject } = this._filterRenderStacks(this.__renderStacks);
+ const componentWrapperCount = Object.keys(componentWrapperObject).length;
+ let count = rootStacks.length + componentWrapperCount;
+
+ const callback = () => {
+ count--;
+ if (!count) {
window._trigger('setDataFinished');
let fn;
while (fn = this.__renderCallbacks.pop()) {
@@ -109,11 +165,58 @@ class RootElement extends Element {
if (process.env.NODE_ENV === 'development') {
perf.stop('setData');
}
+ }
+ };
+
+ if (rootStacks.length > 0) {
+ if (internal.$batchedUpdates) {
+ internal.firstRenderCallback();
+ this._batchedUpdate(internal, internal, rootStacks, callback);
+ } else {
+ const renderObject = Object.create(null);
+ rootStacks.forEach((task) => {
+ renderObject[task.path] = isFunction(task.value) ? task.value() : task.value;
+ });
+ internal.firstRenderCallback(renderObject);
+ internal.setData(renderObject, callback);
+ }
+ }
+
+ if (componentWrapperCount > 0) {
+ Object.values(componentWrapperObject).forEach(({ node, data }) => {
+ if (internal.$batchedUpdates) {
+ internal.firstRenderCallback();
+ this._batchedUpdate(internal, node._internal, data, callback);
+ } else {
+ const renderObject = Object.create(null);
+ data.forEach((task) => {
+ renderObject[task.path] = isFunction(task.value) ? task.value() : task.value;
+ });
+ internal.firstRenderCallback(renderObject);
+ node._internal.setData(renderObject, callback);
+ }
});
}
this.__renderStacks = [];
}
+
+ _batchedUpdate(pageInternal, internal, stacks, callback) {
+ pageInternal.$batchedUpdates(() => {
+ stacks.forEach(task => {
+ if (task.type === 'children') {
+ const spliceArgs = [task.start, task.deleteCount];
+ internal.$spliceData({
+ [task.path]: task.item ? spliceArgs.concat(task.item) : spliceArgs
+ }, callback);
+ } else {
+ internal.setData({
+ [task.path]: task.value
+ }, callback);
+ }
+ });
+ });
+ }
}
export default RootElement;
diff --git a/packages/miniapp-render/src/node/text-node.js b/packages/miniapp-render/src/node/text-node.js
index 8b030981..039b510e 100755
--- a/packages/miniapp-render/src/node/text-node.js
+++ b/packages/miniapp-render/src/node/text-node.js
@@ -16,6 +16,8 @@ class TextNode extends Node {
}
_triggerUpdate(payload) {
+ payload.nodeId = this.__nodeId;
+ payload.componentWrapperId = this.componentWrapperId;
this._root._enqueueRender(payload);
}
diff --git a/packages/miniapp-render/src/utils/cache.js b/packages/miniapp-render/src/utils/cache.js
index 56300945..80b96f9a 100755
--- a/packages/miniapp-render/src/utils/cache.js
+++ b/packages/miniapp-render/src/utils/cache.js
@@ -10,6 +10,7 @@ const windowMap = new Map();
const elementsCache = [];
const pagesCache = [];
const elementMethodsCache = new Map();
+const componentWrapperCache = new Map();
// Init
function init(pageId, document) {
@@ -56,7 +57,6 @@ function getNode(nodeId) {
return nodeIdMap.get(nodeId);
}
-
/**
* Get all nodes
*/
diff --git a/packages/miniapp-runtime-config/CHANGELOG.md b/packages/miniapp-runtime-config/CHANGELOG.md
index 587f6c38..716b3b2d 100644
--- a/packages/miniapp-runtime-config/CHANGELOG.md
+++ b/packages/miniapp-runtime-config/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## [0.3.10]
+
+### Added
+
+- Support componentWrapper
+
## [0.3.9] - 2021-07-21
### Fixed
diff --git a/packages/miniapp-runtime-config/package.json b/packages/miniapp-runtime-config/package.json
index 9714da3a..3e857de1 100644
--- a/packages/miniapp-runtime-config/package.json
+++ b/packages/miniapp-runtime-config/package.json
@@ -1,6 +1,6 @@
{
"name": "miniapp-runtime-config",
- "version": "0.3.9",
+ "version": "0.3.10-2",
"description": "miniapp runtime project config",
"author": "Rax Team",
"homepage": "https://github.com/raxjs/miniapp#readme",
@@ -24,11 +24,11 @@
"webpack": "^4.0.0"
},
"dependencies": {
- "miniapp-builder-shared": "^0.2.0",
- "rax-miniapp-babel-plugins": "^0.1.3",
+ "miniapp-builder-shared": "beta",
+ "rax-miniapp-babel-plugins": "beta",
"rax-miniapp-config-webpack-plugin": "^2.0.0",
- "rax-miniapp-runtime-webpack-plugin": "^4.0.0",
- "miniapp-render": "^2.0.0"
+ "rax-miniapp-runtime-webpack-plugin": "beta",
+ "miniapp-render": "beta"
},
"devDependencies": {
"webpack": "^4.44.2"
diff --git a/packages/miniapp-runtime-config/src/setBaseConfig.js b/packages/miniapp-runtime-config/src/setBaseConfig.js
index f33a706e..d00a0b2f 100644
--- a/packages/miniapp-runtime-config/src/setBaseConfig.js
+++ b/packages/miniapp-runtime-config/src/setBaseConfig.js
@@ -33,6 +33,12 @@ module.exports = (
// Using plugins
const usingPlugins = {};
+ // hasing rax-componentwrapper
+ // pass variable by reference
+ const usingComponentWrapper = {
+ using: false
+ };
+
config.output.filename('[name].js');
// publicPath should not work in miniapp, just keep default value
config.output.publicPath('/');
@@ -60,6 +66,7 @@ module.exports = (
rootDir,
usingPlugins,
runtimeDependencies: userConfig.runtimeDependencies,
+ usingComponentWrapper
}),
},
];
@@ -79,7 +86,8 @@ module.exports = (
nativeLifeCycleMap,
usingPlugins,
needCopyList,
- isPluginProject
+ isPluginProject,
+ usingComponentWrapper
},
]);
diff --git a/packages/rax-miniapp-babel-plugins/CHANGELOG.md b/packages/rax-miniapp-babel-plugins/CHANGELOG.md
index 3fe5d50f..3087bded 100644
--- a/packages/rax-miniapp-babel-plugins/CHANGELOG.md
+++ b/packages/rax-miniapp-babel-plugins/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## [0.1.16]
+
+### Added
+
+- Support ComponentWrapper
+
## [0.1.15] - 2021-05-11
### Changed
diff --git a/packages/rax-miniapp-babel-plugins/package.json b/packages/rax-miniapp-babel-plugins/package.json
index 0bb45253..a1e151af 100644
--- a/packages/rax-miniapp-babel-plugins/package.json
+++ b/packages/rax-miniapp-babel-plugins/package.json
@@ -1,6 +1,6 @@
{
"name": "rax-miniapp-babel-plugins",
- "version": "0.1.15",
+ "version": "0.1.16-3",
"description": "rax miniapp babel plugins",
"main": "src/index.js",
"repository": {
@@ -22,6 +22,6 @@
"@babel/code-frame": "^7.8.3",
"fs-extra": "^9.0.1",
"md5": "^2.2.1",
- "miniapp-builder-shared": "^0.2.0"
+ "miniapp-builder-shared": "0.2.11-0"
}
}
diff --git a/packages/rax-miniapp-babel-plugins/src/index.js b/packages/rax-miniapp-babel-plugins/src/index.js
index 0964646f..243be2cf 100644
--- a/packages/rax-miniapp-babel-plugins/src/index.js
+++ b/packages/rax-miniapp-babel-plugins/src/index.js
@@ -1,4 +1,4 @@
-module.exports = function({ usingComponents, nativeLifeCycleMap, target, rootDir, usingPlugins, runtimeDependencies }) {
+module.exports = function({ usingComponents, nativeLifeCycleMap, target, rootDir, usingPlugins, runtimeDependencies, usingComponentWrapper }) {
return [
require.resolve('./plugins/babel-plugin-remove-Function'),
require.resolve('./plugins/babel-plugin-external-module'),
@@ -14,7 +14,8 @@ module.exports = function({ usingComponents, nativeLifeCycleMap, target, rootDir
usingComponents,
target,
rootDir,
- runtimeDependencies
+ runtimeDependencies,
+ usingComponentWrapper
}
],
[
diff --git a/packages/rax-miniapp-babel-plugins/src/plugins/babel-plugin-handle-native-component.js b/packages/rax-miniapp-babel-plugins/src/plugins/babel-plugin-handle-native-component.js
index 1a258e29..e0fe82e9 100644
--- a/packages/rax-miniapp-babel-plugins/src/plugins/babel-plugin-handle-native-component.js
+++ b/packages/rax-miniapp-babel-plugins/src/plugins/babel-plugin-handle-native-component.js
@@ -2,7 +2,10 @@ const { resolve, dirname, join } = require('path');
const { existsSync, readJSONSync } = require('fs-extra');
const {
pathHelper: { absoluteModuleResolve, removeExt },
- platformMap
+ platformMap,
+ componentWrapper: {
+ WrapperPackage
+ }
} = require('miniapp-builder-shared');
const extMap = require('../utils/extMap');
const { collectComponentAttr, collectUsings } = require('../utils/handleComponentAST');
@@ -121,7 +124,7 @@ function hasDefaultSpecifier(specifiers, t) {
module.exports = function visitor(
{ types: t },
- { usingComponents, target, rootDir, runtimeDependencies }
+ { usingComponents, target, rootDir, runtimeDependencies, usingComponentWrapper }
) {
// Collect imported dependencies
let nativeComponents = {};
@@ -151,6 +154,15 @@ module.exports = function visitor(
});
}
collectUsings(path, nativeComponents, usingComponents, filePath, t);
+ } else if (source.value === WrapperPackage) {
+ usingComponentWrapper.using = true;
+ if (!scanedPageMap[filename]) {
+ scanedPageMap[filename] = true;
+ path.parentPath.traverse({
+ JSXOpeningElement: collectComponentAttr(nativeComponents, t)
+ });
+ }
+ collectUsings(path, nativeComponents, usingComponents, filePath, t);
}
}
},
diff --git a/packages/rax-miniapp-babel-plugins/src/utils/handleComponentAST.js b/packages/rax-miniapp-babel-plugins/src/utils/handleComponentAST.js
index f6d66fe9..eec4736e 100644
--- a/packages/rax-miniapp-babel-plugins/src/utils/handleComponentAST.js
+++ b/packages/rax-miniapp-babel-plugins/src/utils/handleComponentAST.js
@@ -1,4 +1,5 @@
const getTagName = require('./getTagName');
+const {componentWrapper: { WrapperElement, WrapperPackage }} = require('miniapp-builder-shared');
function collectComponentAttr(components, t) {
return (innerPath) => {
@@ -39,7 +40,7 @@ function collectUsings(
filePath,
t
) {
- const { specifiers } = path.node;
+ const { specifiers, source } = path.node;
specifiers.some((specifier, index) => {
if (!t.isImportDefaultSpecifier(specifier)) return;
@@ -57,12 +58,13 @@ function collectUsings(
});
// Generate a random tag name
- const replacedTagName = getTagName(tagName);
+ const isComponentWrapper = source.type === 'StringLiteral' && source.value === WrapperPackage;
+ const replacedTagName = isComponentWrapper ? WrapperElement : getTagName(tagName);
if (!usings[replacedTagName]) {
usings[replacedTagName] = { props: [], events: [] };
}
usings[replacedTagName] = {
- path: filePath,
+ path: isComponentWrapper ? './wrapper' : filePath,
props: [
...new Set(componentInfo.props.concat(usings[replacedTagName].props)),
],
diff --git a/packages/rax-miniapp-runtime-webpack-plugin/package.json b/packages/rax-miniapp-runtime-webpack-plugin/package.json
index 3ee4b7e3..c9473b66 100644
--- a/packages/rax-miniapp-runtime-webpack-plugin/package.json
+++ b/packages/rax-miniapp-runtime-webpack-plugin/package.json
@@ -1,6 +1,6 @@
{
"name": "rax-miniapp-runtime-webpack-plugin",
- "version": "4.11.0",
+ "version": "4.12.0",
"description": "A webpack plugin for miniapp runtime build",
"main": "src/index.js",
"files": [
@@ -21,12 +21,15 @@
"csso": "^4.0.3",
"fs-extra": "^8.1.0",
"lodash.isequal": "^4.5.0",
- "miniapp-builder-shared": "^0.2.0",
+ "miniapp-builder-shared": "0.2.11-0",
"path-to-regexp": "^3.0.0",
"postcss": "^7.0.17",
"pretty-data": "^0.40.0",
"terser": "^4.6.10",
"webpack": "^4.35.3",
"webpack-sources": "^1.3.0"
+ },
+ "resolutions": {
+ "miniapp-builder-shared": "0.2.11-0"
}
}
diff --git a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/componentWrapper.js b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/componentWrapper.js
new file mode 100644
index 00000000..a3adcbff
--- /dev/null
+++ b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/componentWrapper.js
@@ -0,0 +1,92 @@
+/**
+ * generate ComponentWrapper
+*/
+const { join } = require('path');
+const { platformMap, componentWrapper: { WrapperElement } } = require('miniapp-builder-shared');
+
+const platformConfig = require('../platforms');
+const { RECURSIVE_TEMPLATE_TYPE, UNRECURSIVE_TEMPLATE_TYPE } = require('../constants');
+
+const addFileToCompilation = require('../utils/addFileToCompilation');
+const getAssetPath = require('../utils/getAssetPath');
+const isNpmModule = require('../utils/isNpmModule');
+const rmCurDirPathSymbol = require('../utils/rmCurDirPathSymbol');
+const { generateRootTmpl } = require('./root');
+const { buildTemplate, buildNativeComponentTemplate, buildSjs } = require('./templates');
+
+function ensureWrapperFolder() {
+
+}
+
+function generateWrapperJS(compilation, { target, command, subAppRoot = '' }) {
+ const filename = join(subAppRoot, 'wrapper.js');
+ addFileToCompilation(compilation, {
+ filename,
+ content:
+`const render = require('${getAssetPath('render.js', filename)}');
+
+Component(render.createElementConfig());`,
+ target,
+ command,
+ });
+}
+
+function generateWrapperTemplate(compilation,
+ { target, command, subAppRoot = '' }) {
+ const { adapter: { formatBindedData, for: targetFor, key } } = platformConfig[target];
+
+ let content = `
+
+
+`;
+
+ const isRecursiveTemplate = RECURSIVE_TEMPLATE_TYPE.has(target);
+ if (!isRecursiveTemplate) {
+ content = `` + content;
+ } else {
+ content = `` + content;
+ }
+
+ addFileToCompilation(compilation, {
+ filename: join(subAppRoot, `wrapper${platformMap[target].extension.xml}`),
+ content,
+ target,
+ command
+ });
+}
+
+function generateWrapperJSON(compilation, { usingComponents, usingPlugins, target, command, subAppRoot = '' }) {
+ const content = {
+ component: true,
+ usingComponents: {
+ [WrapperElement]: './wrapper'
+ }
+ };
+
+ if (UNRECURSIVE_TEMPLATE_TYPE.has(target)) {
+ content.usingComponents.element = './comp';
+ }
+
+ Object.keys(usingComponents).forEach(component => {
+ const componentPath = usingComponents[component].path;
+ content.usingComponents[component] = isNpmModule(componentPath) ? componentPath : getAssetPath(rmCurDirPathSymbol(componentPath), join(subAppRoot, 'comp'));
+ });
+ Object.keys(usingPlugins).forEach(plugin => {
+ content.usingComponents[plugin] = usingPlugins[plugin].path;
+ });
+
+ addFileToCompilation(compilation, {
+ filename: join(subAppRoot, 'wrapper.json'),
+ content: JSON.stringify(content, null, 2),
+ target,
+ command,
+ });
+}
+
+
+module.exports = {
+ ensureWrapperFolder,
+ generateWrapperJS,
+ generateWrapperTemplate,
+ generateWrapperJSON,
+};
diff --git a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/element.js b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/element.js
index d12e9cee..b5626c01 100644
--- a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/element.js
+++ b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/element.js
@@ -10,6 +10,7 @@ const isNpmModule = require('../utils/isNpmModule');
const rmCurDirPathSymbol = require('../utils/rmCurDirPathSymbol');
const { generateRootTmpl } = require('./root');
const { buildTemplate, buildNativeComponentTemplate, buildSjs } = require('./templates');
+const { buildComponentWrapperTemplate } = require('./componentWrapper');
function generateElementJS(compilation, { target, command, subAppRoot = '' }) {
@@ -45,7 +46,9 @@ function generateElementTemplate(compilation,
});
const template = buildTemplate(target, modifyTemplate, { isRecursiveTemplate });
- const nativeComponentTemplate = buildNativeComponentTemplate(usingPlugins, target, isRecursiveTemplate) + buildNativeComponentTemplate(usingComponents, target, isRecursiveTemplate);
+ const nativeComponentTemplate =
+ buildNativeComponentTemplate(usingPlugins, target, isRecursiveTemplate) +
+ buildNativeComponentTemplate(usingComponents, target, isRecursiveTemplate);
// In recursiveTemplate, root.axml need be written into comp.axml
content = template + nativeComponentTemplate + content;
diff --git a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/index.js b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/index.js
index 0f94f82b..2663cece 100644
--- a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/index.js
+++ b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/index.js
@@ -14,6 +14,13 @@ const {
} = require('./element');
const generateRender = require('./render');
const generatePkg = require('./pkg');
+const {
+ ensureWrapperFolder,
+ generateWrapperJS,
+ generateWrapperTemplate,
+ generateWrapperJSON,
+ buildComponentWrapperTemplate
+} = require('./componentWrapper');
module.exports = {
generateAppCSS,
@@ -28,5 +35,10 @@ module.exports = {
generateElementJSON,
generateElementTemplate,
generateRender,
- generatePkg
+ generatePkg,
+ ensureWrapperFolder,
+ generateWrapperJS,
+ generateWrapperTemplate,
+ generateWrapperJSON,
+ buildComponentWrapperTemplate
};
diff --git a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/page.js b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/page.js
index a03f3136..bb01f0e4 100644
--- a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/page.js
+++ b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/page.js
@@ -1,5 +1,5 @@
const { join } = require('path');
-const { platformMap, pathHelper: { getBundlePath }} = require('miniapp-builder-shared');
+const { platformMap, pathHelper: { getBundlePath }, componentWrapper: { WrapperElement }} = require('miniapp-builder-shared');
const platformConfig = require('../platforms');
const getAssetPath = require('../utils/getAssetPath');
@@ -96,6 +96,7 @@ function generatePageJSON(
useComponent,
usingComponents, usingPlugins,
pageRoute,
+ usingComponentWrapper,
{ target, command, subAppRoot = '' }
) {
if (!pageConfig.usingComponents) {
@@ -110,6 +111,10 @@ function generatePageJSON(
const componentPath = usingComponents[component].path;
pageConfig.usingComponents[component] = isNpmModule(componentPath) ? componentPath : getAssetPath(rmCurDirPathSymbol(componentPath), pageRoute);
});
+
+ if (usingComponentWrapper) {
+ pageConfig.usingComponents[WrapperElement] = getAssetPath(join(subAppRoot, 'wrapper'), pageRoute);
+ }
Object.keys(usingPlugins).forEach(plugin => {
pageConfig.usingComponents[plugin] = usingPlugins[plugin].path;
});
diff --git a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/root.js b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/root.js
index 550a102b..82c96ef3 100644
--- a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/root.js
+++ b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/root.js
@@ -1,6 +1,7 @@
const { platformMap } = require('miniapp-builder-shared');
const addFileToCompilation = require('../utils/addFileToCompilation');
+const { buildComponentWrapperTemplate } = require('./componentWrapper');
const { buildTemplate, buildSjs, buildNativeComponentTemplate } = require('./templates');
function generateRootTmpl(
@@ -9,7 +10,9 @@ function generateRootTmpl(
) {
const template = buildTemplate(target, modifyTemplate);
const sjs = buildSjs(target);
- const nativeComponentTemplate = buildNativeComponentTemplate(usingPlugins, target) + buildNativeComponentTemplate(usingComponents, target);
+ const nativeComponentTemplate =
+ buildNativeComponentTemplate(usingPlugins, target) +
+ buildNativeComponentTemplate(usingComponents, target);
addFileToCompilation(compilation, {
filename: `${subAppRoot}/root${platformMap[target].extension.xml}`,
diff --git a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/templates/index.js b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/templates/index.js
index 37bdd531..c3bbcb08 100644
--- a/packages/rax-miniapp-runtime-webpack-plugin/src/generators/templates/index.js
+++ b/packages/rax-miniapp-runtime-webpack-plugin/src/generators/templates/index.js
@@ -1,3 +1,5 @@
+const { componentWrapper: {WrapperElement} } = require('miniapp-builder-shared');
+
const platformConfig = require('../../platforms');
const { buildRecursiveTemplate, buildRecursiveTemplateSjs } = require('./recursiveTemplate');
const { buildUnrecursiveTemplate, buildUnrecursiveTemplateSjs } = require('./unrecursiveTemplate');
@@ -31,6 +33,14 @@ function buildNativeComponentTemplate(usings, target) {
const { formatBindedData, supportSjs } = adapter;
return Object.keys(usings).reduce((current, componentTag) => {
+ if (componentTag === WrapperElement) {
+ return `
+
+ <${WrapperElement}
+ data-private-node-id="{{r.nodeId}}" data-private-page-id="{{r.pageId}}" r="{{r}}"
+ />
+`;
+ }
const props = usings[componentTag].props.reduce((cur, prop) => {
const tmpl = ` ${prop}="{{r['${prop}']}}"`;
return cur + tmpl;
diff --git a/packages/rax-miniapp-runtime-webpack-plugin/src/index.js b/packages/rax-miniapp-runtime-webpack-plugin/src/index.js
index 7abddcc3..e3a05fd4 100755
--- a/packages/rax-miniapp-runtime-webpack-plugin/src/index.js
+++ b/packages/rax-miniapp-runtime-webpack-plugin/src/index.js
@@ -22,7 +22,10 @@ const {
generateElementJSON,
generateElementTemplate,
generateRender,
- generatePkg
+ generatePkg,
+ generateWrapperJS,
+ generateWrapperTemplate,
+ generateWrapperJSON
} = require('./generators');
const getFinalRouteMap = require('./utils/getFinalRouteMap');
@@ -47,7 +50,8 @@ class MiniAppRuntimePlugin {
mainPackageRoot,
appConfig,
subAppConfigList = [],
- isPluginProject = false
+ isPluginProject = false,
+ usingComponentWrapper: _usingComponentWrapper
} = options;
const {
context: { command, userConfig: rootUserConfig, rootDir },
@@ -58,6 +62,7 @@ class MiniAppRuntimePlugin {
let isFirstRender = true;
let lastUsingComponents = {};
let lastUsingPlugins = {};
+ let lastImportComponentWrapper = false;
let needAutoInstallDependency = false;
const packageJsonFilePath = [];
@@ -74,6 +79,7 @@ class MiniAppRuntimePlugin {
});
compiler.hooks.emit.tapAsync(PluginName, (compilation, callback) => {
+ const usingComponentWrapper = _usingComponentWrapper.using;
const outputPath = compilation.outputOptions.path;
const sourcePath = join(rootDir, 'src');
const pages = [];
@@ -93,14 +99,17 @@ class MiniAppRuntimePlugin {
if (!isFirstRender) {
useComponentChanged =
!isEqual(usingComponents, lastUsingComponents) ||
- !isEqual(usingPlugins, lastUsingPlugins);
+ !isEqual(usingPlugins, lastUsingPlugins) ||
+ lastImportComponentWrapper !== usingComponentWrapper;
}
lastUsingComponents = Object.assign({}, usingComponents);
lastUsingPlugins = Object.assign({}, usingPlugins);
+ lastImportComponentWrapper = usingComponentWrapper;
+
const useComponent =
Object.keys(lastUsingPlugins).length +
Object.keys(lastUsingComponents).length >
- 0;
+ 0 || usingComponentWrapper;
// These files need be written in first render
if (isFirstRender) {
// render.js
@@ -144,7 +153,8 @@ class MiniAppRuntimePlugin {
pages,
target,
command,
- subPackages
+ subPackages,
+ usingComponentWrapper
});
// Only when developer may use native component, it will generate package.json in output
@@ -188,7 +198,8 @@ class MiniAppRuntimePlugin {
usingComponents: mainPackageUsingComponents,
usingPlugins: mainPackageUsingPlugins,
target,
- command
+ command,
+ usingComponentWrapper
});
generateElementTemplate(compilation, {
usingComponents: mainPackageUsingComponents,
@@ -197,6 +208,25 @@ class MiniAppRuntimePlugin {
command,
modifyTemplate
});
+ if (usingComponentWrapper) {
+ generateWrapperJS(compilation, {
+ target,
+ command
+ });
+ generateWrapperJSON(compilation, {
+ usingComponents: mainPackageUsingComponents,
+ usingPlugins: mainPackageUsingPlugins,
+ target,
+ command
+ });
+ generateWrapperTemplate(compilation, {
+ usingComponents: mainPackageUsingComponents,
+ usingPlugins: mainPackageUsingPlugins,
+ target,
+ command,
+ modifyTemplate
+ });
+ }
} else {
// Only when there isn't native component, it need generate root template file
// Generate root template xml
@@ -267,7 +297,7 @@ class MiniAppRuntimePlugin {
usingPlugins: subPackageUsingPlugins,
target,
command,
- subAppRoot
+ subAppRoot,
});
generateElementTemplate(compilation, {
usingComponents: subPackageUsingComponents,
@@ -304,6 +334,7 @@ class MiniAppRuntimePlugin {
isSubPackagePage ? subPackageUsingComponents : mainPackageUsingComponents,
isSubPackagePage ? subPackageUsingPlugins : mainPackageUsingPlugins,
entryName,
+ usingComponentWrapper,
{
target,
command,