Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[思] Handlebars 模板应该如何进行预处理 #35

Open
aleen42 opened this issue Jan 31, 2019 · 0 comments
Open

[思] Handlebars 模板应该如何进行预处理 #35

aleen42 opened this issue Jan 31, 2019 · 0 comments
Assignees

Comments

@aleen42
Copy link
Owner

aleen42 commented Jan 31, 2019

最近,Handlebars 模板预处理解析成为了重构任务中的最重要一环。在该环节,我们希望能通过 Webpack Loader 的预处理,直接 export 出模板解析后的函数。举个例子来说,每个模板都会有特定的一种结构:

root context
partials

partials 1
partials 2
...

对应的 .hbs 文件就可能会是这样:

<!-- root context -->
<div class="container"></div>
<!-- end of root context -->

<!-- partials -->
<script type="text/x-handlebars-template" id="partial1">
    <div class="partial-container">partial 1</div>
</script>

<script type="text/x-handlebars-template" id="partial2">
    <div class="partial-container">partial 2</div>
</script>
<!-- end of partials -->

从模板文件的结构来看,我们希望能通过 loader 做出以下的预处理:

  • 解析模板每一部分,并 export 出相应的 render 函数
  • 过滤掉所有浪费字节的 comments
module.exports = Object.assign(data => {
    /** ... */
}, {
    partial1: data => { /** ... */ },
    partial2: data => { /** ... */ },
});

此外,由于各模块所加载的模板可能会含有特殊的 template helpers,这就意味着我们需要用特定的方式去接收 template data 以外的 context。针对于此,我们考虑两个比较标准的方案:

  1. curry 化所 export 的函数,即在引用 Webpack loader 解析模板后得到的调用函数,在渲染模板前需要先调用一次函数往闭包内传递 context。
    module.exports = context => Object.assign(data => {
        /** ... */
    }, {
        partial1: data => { /** ... */ },
        partial2: data => { /** ... */ },
    });
  2. 额外 export 函数去设定 context
    module.exports = Object.assign(data => {
        /** ... */
    }, {
        config: context => { /** store locally */ }
        partial1: data => { /** ... */ },
        partial2: data => { /** ... */ },
    });

显然,为了避免代码中存在类似 require('hbs!xxx.hbs')()() 的写法,我们还是倾向于第二种方案的实现。当然,为了支持特殊的 context 传递,我们仍然会在函数内接受特定的 context 以覆盖原有:

module.exports = Object.assign(data => {
    /** ... */
}, {
    config: context => { /** store locally */ }
    partial1: (data, context) => { /** ... */ },
    partial2: (data, context) => { /** ... */ },
});

另外,我们从部分历史代码的实现中还发现到,传递给 Handlebars 模板的 data 大部分都存在相似的结构,而这就意味着 module 内部会存在动态调用函数的情况:

require('hbs!.xxx.hbs')[`partial${type}`](data);
/** or */
require('hbs!.xxx.hbs')(`partial${type}`, data);

因此,在设计函数我们依然需要支持 template(id, data, context) 的传递:

module.exports = Object.assign(data => {
    /** ... */
}, {
    config: context => { /** store locally */ }
    partial1: (data, context) => { /** ... */ },
    partial2: (data, context) => { /** ... */ },
    template: (id, data, context) => { /** ... */ },
});
@aleen42 aleen42 self-assigned this Jan 31, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant