Skip to content
This repository has been archived by the owner on Mar 7, 2024. It is now read-only.

Commit

Permalink
perf: 提升模板渲染性能
Browse files Browse the repository at this point in the history
1. 用调用模板的方式替代条件判断
2. 收集使用到的 props ,而不是声明所有 props
  • Loading branch information
Darmody authored and yesmeck committed Aug 26, 2019
1 parent d7b6c27 commit 9af03f9
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 111 deletions.
2 changes: 1 addition & 1 deletion docs/quick-start/wechat.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ my-app/

`dist` 为打包编译后的文件目录。

_在开发阶段我们无需关心打包结果的兼容性及体积,所以 remax 打包结果为 es6 语法未压缩版本,在需要上传代码时应勾选小程序的 **es6 转 es5****代码压缩****样式补全**选项_
_在开发阶段我们无需关心打包结果的兼容性及体积,所以 remax 打包结果为未压缩版本,在需要上传代码时应勾选小程序的 **代码压缩****样式补全**选项_

`src` 为源文件目录

Expand Down
16 changes: 16 additions & 0 deletions packages/remax-cli/src/build/adapters/alipay/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,19 @@ export const templates = {
};

export const moduleFormat = 'esm';

// TODO: remax 和 remax-cli 重复定义了,要 DRY
const alias: any = {
className: 'class',
onClick: 'onTap',
};

export function getNativePropName(prop: string) {
const aliasProp = alias[prop];

if (aliasProp) {
return aliasProp;
}

return prop;
}
2 changes: 1 addition & 1 deletion packages/remax-cli/src/build/adapters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface Adapter {

hostComponents: (component: string) => { props: string[] };

propsAlias: (key: string) => string;
getNativePropName: (key: string) => string;

moduleFormat: 'cjs' | 'esm';
}
Expand Down
22 changes: 22 additions & 0 deletions packages/remax-cli/src/build/adapters/wechat/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,25 @@ export const templates = {
};

export const moduleFormat = 'cjs';

// TODO: alias 方法在 remax 和 remax-cli 都重复定义了,想办法 DRY
const alias: { [prop: string]: string } = {
className: 'class',
activeColor: 'activeColor',
backgroundColor: 'backgroundColor',
onClick: 'bindtap',
};

export function getNativePropName(prop: string) {
const aliasProp = alias[prop];

if (aliasProp) {
return aliasProp;
}

if (prop.startsWith('on')) {
return prop.toLowerCase().replace('on', 'bind');
}

return prop;
}
50 changes: 33 additions & 17 deletions packages/remax-cli/src/build/plugins/components.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as t from '@babel/types';
import { NodePath } from '@babel/traverse';
import { get } from 'dot-prop';
import { kebabCase, unionBy } from 'lodash';
import { kebabCase } from 'lodash';
import { Adapter } from '../adapters';

interface Component {
Expand All @@ -11,7 +11,7 @@ interface Component {
children?: Component[];
}

const components: Component[] = [];
const components: { [id: string]: Component } = {};

export default (adapter: Adapter) => () => ({
visitor: {
Expand All @@ -33,18 +33,22 @@ export default (adapter: Adapter) => () => ({
return;
}

// 基础组件
node.openingElement.attributes.map(e => {
if (t.isJSXAttribute(e)) {
const propName = get(e, 'name.name') as string;
return propName;
}
});

const componentName = componentPath.node.imported.name;

const id = kebabCase(componentName);

let usedProps = adapter.hostComponents(id).props;

const usedAllProps = node.openingElement.attributes.find(
attr => attr.type === 'JSXSpreadAttribute'
);

if (!usedAllProps) {
usedProps = node.openingElement.attributes.map(e => {
const propName = get(e, 'name.name') as string;
return propName;
});
}

if (id === 'swiper-item') {
return;
}
Expand All @@ -53,18 +57,30 @@ export default (adapter: Adapter) => () => ({
return;
}

const { props } = adapter.hostComponents(id);
const props = usedProps
.filter(prop => !!prop)
.map(prop => adapter.getNativePropName(prop as string));

if (!components[id]) {
components[id] = {
type: kebabCase(componentName),
id,
props,
};
}

props.forEach(prop => {
if (components[id].props.findIndex(item => item === prop) !== -1) {
return;
}

components.push({
type: kebabCase(componentName),
id,
props,
components[id].props.push(prop);
});
}
},
},
});

export function getComponents() {
return unionBy(components, 'type');
return Object.values(components);
}
22 changes: 10 additions & 12 deletions packages/remax-cli/templates/alipay/base.ejs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
<template name="REMAX_TPL">
<block a:for="{{tree.root.children}}" a:key="{{item.id}}">
<template is="REMAX_TPL_1" data="{{item}}"/>
<template is="REMAX_TPL_1_CONTAINER" data="{{item: item}}" />
</block>
</template>

<template name="REMAX_TPL_1">
<block>
<block a:if="{{item && item.text}}">
<!-- string -->
{{item.text}}
</block>

<% for (let component of components) { %>
<%- include('./component.ejs', {
<% for (let component of components) { %>
<%- include('./component.ejs', {
type: component.type,
props: component.props,
id: component.id,
}) %>
<% } %>
</block>
<% } %>
<template name="REMAX_TPL_1_plain-text">
<block>{{item.text}}</block>
</template>
<!-- 把动态选择模板的逻辑放入一个模板内,可以提升性能问题 -->
<template name="REMAX_TPL_1_CONTAINER">
<template is="{{'REMAX_TPL_1_' + item.type}}" data="{{item: item}}" />
</template>
56 changes: 23 additions & 33 deletions packages/remax-cli/templates/alipay/component.ejs
Original file line number Diff line number Diff line change
@@ -1,41 +1,31 @@
<% camelCased = function(str) { return str.replace(/-([a-z0-9])/g, function (g) { return g[1].toUpperCase(); })}%>

<%
const events = [
'tap'
];
props = props.concat(events.map(item => `bind${item}`));
%>
<block a:if="{{item.type === '<%= type %>'}}">
<<%=id%>
<% for(let key of props) { %>
<%=key%>="{{item.props.<%=camelCased(key)%>}}"
<% } %>
>
<template name="REMAX_TPL_1_<%=id%>">
<<%=id%> <% for(let key of props) { %> <%=key%>="{{item.props.<%=camelCased(key)%>}}" <% } %>>
<% if (id === 'swiper') { %>
<block a:for="{{item.children}}" a:key="{{item.id}}">
<swiper-item key="{{item.props.key}}" >
<block a:for="{{item.children}}">
<template is="REMAX_TPL_1" data="{{item}}"/>
</block>
</swiper-item>
</block>
<block a:for="{{item.children}}" a:key="{{item.id}}">
<swiper-item key="{{item.props.key}}">
<block a:for="{{item.children}}" a:key="{{item.id}}">
<template is="REMAX_TPL_1_CONTAINER" data="{{item: item}}" />
</block>
</swiper-item>
</block>
<% } else if (id === 'picker') { %>
<view>
<template is="REMAX_TPL_1" data="{{item: item.children[0]}}"/>
</view>
<view>
<template is="REMAX_TPL_1_CONTAINER" data="{{item: item.children[0]}}" />
</view>
<% } else if (id === 'picker-view') { %>
<block a:for="{{item.children}}" a:key="{{item.id}}">
<picker-view-column>
<view a:for="{{item.children}}">
<template is="REMAX_TPL_1" data="{{item}}"/>
</view>
</picker-view-column>
</block>
<block a:for="{{item.children}}" a:key="{{item.id}}">
<picker-view-column>
<view a:for="{{item.children}}">
<template is="REMAX_TPL_1_CONTAINER" data="{{item}}" />
</view>
</picker-view-column>
</block>
<% } else { %>
<block a:for="{{item.children}}" a:key="{{item.id}}">
<template is="REMAX_TPL_1" data="{{item}}"/>
</block>
<block a:for="{{item.children}}" a:key="{{item.id}}">
<template is="REMAX_TPL_1_CONTAINER" data="{{item: item}}" />
</block>
<% } %>
</<%=id%>>
</block>
</template>
6 changes: 3 additions & 3 deletions packages/remax-cli/templates/alipay/page.ejs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<import-sjs name="helper" from="<%= jsHelper %>"/>
<import src="<%= baseTemplate %>"/>
<template is="REMAX_TPL" data="{{tree: helper.reduce(action)}}"/>
<import-sjs name="helper" from="<%= jsHelper %>" />
<import src="<%= baseTemplate %>" />
<template is="REMAX_TPL" data="{{tree: helper.reduce(action)}}" />
32 changes: 17 additions & 15 deletions packages/remax-cli/templates/wechat/base.ejs
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
<template name="REMAX_TPL">
<block wx:for="{{tree.root.children}}" wx:key="{{item.id}}">
<template is="REMAX_TPL_1" data="{{i: item}}"/>
<block wx:for="{{tree.root.children}}" wx:key="{{id}}">
<template is="REMAX_TPL_1_CONTAINER" data="{{i: item}}" />
</block>
</template>

<wxs module="_h">
module.exports = {
v: function(value) {
return value !== undefined ? value : '';
}
v: function(value) {
return value !== undefined ? value : '';
}
};
</wxs>

<% for (var i = 1; i <= depth; i++) { %>
<%var id = i; %>
<template name="REMAX_TPL_<%= id%>">
<block>
<block wx:if="{{i && i.text}}">{{i.text}}</block>
<% for (let component of components) { %>
<%- include('./component.ejs', {
<%var id = i; %>
<% for (let component of components) { %>
<%- include('./component.ejs', {
type: component.type,
props: component.props,
id: component.id,
templateId: id + 1
templateId: id,
}) %>
<% } %>
</block>
</template>
<% } %>
<template name="REMAX_TPL_<%=id%>_plain-text" data="{{i: i}}">
<block>{{i.text}}</block>
</template>
<!-- 把动态选择模板的逻辑放入一个模板内,可以提升性能问题 -->
<template name="REMAX_TPL_<%=id%>_CONTAINER" data="{{i: i}}">
<template is="{{'REMAX_TPL_<%=id%>_' + i.type}}" data="{{i: i}}" />
</template>
<% } %>
30 changes: 14 additions & 16 deletions packages/remax-cli/templates/wechat/component.ejs
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
<% camelCased = function(str) { return str.replace(/-([a-z0-9])/g, function (g) { return g[1].toUpperCase(); })}%>

<block wx:if="{{i.type === '<%= type %>'}}">
<<%=id%>
<% for(let key of props) { %>
<%=key%>="{{_h.v(i.props.<%=camelCased(key)%>)}}"
<% } %>
><% if (id === 'swiper') { %>
<block wx:for="{{i.children}}" wx:key="{{item.id}}">
<swiper-item key="{{item.props.key}}" >
<block wx:for="{{item.children}}" wx:key="{{item.id}}">
<template is="REMAX_TPL_<%= templateId%>" data="{{ i: item}}"/>
</block>
</swiper-item>
</block>
<template name="REMAX_TPL_<%=templateId%>_<%=id%>">
<<%=id%> <% for(let key of props) { %> <%=key%>="{{_h.v(i.props.<%=camelCased(key)%>)}}" <% } %>>
<% if (id === 'swiper') { %>
<block wx:for="{{i.children}}" wx:key="{{id}}">
<swiper-item key="{{item.props.key}}">
<block wx:for="{{item.children}}" wx:key="{{id}}">
<template is="REMAX_TPL_<%= templateId + 1%>_CONTAINER" data="{{i: item}}" />
</block>
</swiper-item>
</block>
<% } else { %>
<block wx:for="{{i.children}}" wx:key="{{item.id}}">
<template is="REMAX_TPL_<%= templateId%>" data="{{i: item}}"/></block>
<block wx:for="{{i.children}}" wx:key="{{id}}">
<template is="REMAX_TPL_<%= templateId + 1%>_CONTAINER" data="{{i: item}}" />
</block>
<% } %>
</<%=id%>>
</block>
</template>
Loading

0 comments on commit 9af03f9

Please sign in to comment.