Node Express에서 Handlebars layout body script처리(helper사용)

들어가기

음 저번에 Express에 Handlebars 템플릿으로 레이아웃을 만들었다.

Express Node에 Handlebars 템플릿엔진 적용하기.

레이아웃 구조

위와 같이 레이아웃은 말끔히 만들었지만, 문제가 하나 있었다.

index.hbs에서 jquery를 호출 할 수가 없었다.

그 이유는 레이아웃을 담당하는 main.hbs에서 대부분의 script와 style등을 load하는데 그 순서가 다음과 같이 되어 있었기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>{{title}}</title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
{{{body}}}

<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>

</body>
</html>

위 경우 body에서 Jquery를 사용할 경우 아직 로드되지 않는 jquery에 접근하기 때문에 문제가 발생 할 수도 있다.

위와 같은 문제를 해결하기 위해 handlebars의 helper를 사용하여, 서버에서 handlebars 페이지를 렌더링 할때 body의 script와 style을 가져와 레이아웃을 담당하는 main.hbs에 적용 할 수 있다.

Handlebars layout에 helper 사용하기

아래는 layout을 담당하는 main.hbs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>{{title}}</title>
<link rel="stylesheet" href="/stylesheets/style.css">
{{{_sections.style}}}
</head>
<body>
{{{body}}}

<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
{{{_sections.script}}}
</body>
</html>

위의 _sections는 handlebars의 helper를 호출하는 부분이다.

그리고 body에 들어갈 index.hbs는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
<p>This is my home page</p>

{{#section 'script'}}

<script type="application/javascript">
$(function() {
alert( "I'm ready!" );
});
</script>

{{/section}}

위 index.hbs 내부의 section 감싸진 부분은 main.hbs의 _sections.script로 옮겨져 서버에서 렌더링 되므로, index.hbs에서 main.hbs에서 로드하는 기타 자원들이 로드되었는지 여부를 걱정 할 필요가 없어진다.

그리고 express의 app.js 의 handelbars셋팅은 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
app.engine( 'hbs', hbs( {
extname: 'hbs',
defaultLayout: 'main',
layoutsDir: __dirname + '/views/layouts/',
partialsDir: __dirname + '/views/partials/',
helpers : {
inc : function(number, options){
//return parseInt(value) + 1;
if(typeof(number) === 'undefined' || number === null)
return null;

// Increment by inc parameter if it exists or just by one
return number + (options.hash.inc || 1);
},
section: function(name, options){
if(!this._sections) this._sections = {};
this._sections[name] = options.fn(this);
return null;
}
}
} ) );

app.set( 'view engine', 'hbs' );

위의 설정중 section이라는 helper를 이용하여 index.hbs의 script, style을 레이아웃을 담당하는 main.hbs에 불러와 렌더링 할 수 있다.

참고자료

https://stackoverflow.com/questions/25300017/how-to-ensure-the-javascript-is-at-the-bottom-of-the-code-in-express-handlebars