Download - Clean Front-End Development
![Page 1: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/1.jpg)
CLEANFRONTENDDEVELOPMENT
YOUN JISU,CodeSquad
DEVIEW2016
Last modified : 2016-10-26
![Page 2: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/2.jpg)
Intro.요즘 JavaScript 개발 이야기
![Page 3: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/3.jpg)
Intro
오늘 이야기는 이쯤에 맞춥니다
IE6 Modern Browser
vanilla Full Framework
static Web page SPA
![Page 4: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/4.jpg)
imgae: https://hackernoon.com/how-it-feels-to-learn-javascript-in-2016-d3a717dd577f#.mdtm38i8o
Intro
JavaScript Fatigue >.<
![Page 5: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/5.jpg)
http://stateofjs.com/2016/opinions/
JavaScript 개발은 복잡하다
Intro
![Page 6: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/6.jpg)
http://stateofjs.com/2016/opinions/
JavaScript 개발은 빠르게 변하고 있다
Intro
![Page 7: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/7.jpg)
http://stateofjs.com/2016/opinions/
하지만 올바른 방향으로 가는 중
Intro
![Page 8: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/8.jpg)
Frameworks 의 불편함
우량한 아이들 새로운 아이들
예측하기 어려운 미래 전략병주고 약주고..(SPA + Server-side rendering?)
브라우저 지원범위.커뮤니티, 문서화, 생태계, 급격한 변화
다양한 Syntax와 Pattern 이 존재새로운 Learning costs
Intro
공통적으로
![Page 9: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/9.jpg)
On January 12, 2016 Microsoft announced end of support for IE10, IE9, and IE8.> Progressive Enhancement 전략과 함께 CSS3, ES 최신 버전의 사용도 가능
주변은,
Intro
Mobile Web Browser 의 꾸준한성장> static view 중심의 서비스> data 처리보다는 seamless한 animation 처리가 더 중요
ES2015,ES2016,ES2017 (thanks to jQuery, underscor, lodash)> 다양한 readable syntax 제공. 다양한 라이브러리와의 이별
Standard transpilers (not Typescript, coffeeScript, JSX) with Builders> ES를 더 땡길 수 있는 기회!
![Page 10: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/10.jpg)
우리 서비스는 지속가능해야 한다
성능을 깊게 개선할 수 있어야 한다
동료가 쉽게 이해할 수 있는 코드를 구현해야 한다
다양한 환경에서 동작가능해야 한다
항상 더 좋은 UX를 고민하자
jQuery 개발자보단 Front-end 개발자가 되면 좋겠다
한편, FE개발자의 본능적 미션 !
Intro
“
”
![Page 11: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/11.jpg)
standard Code,with all tools
이런 전략은 어떨까?Intro
standard Code,with all tools
![Page 12: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/12.jpg)
“Polyfill, Transpiler" based Architecture
transpilingES6 based service codes ES5 Codes
Polyfills
Utilities codes Production code
Intro
![Page 13: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/13.jpg)
FUTURE !Intro
transpilingES6 based service codes ES5 Codes
Polyfills
Utilities codes Production code
![Page 14: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/14.jpg)
jQuery Free
![Page 15: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/15.jpg)
<!-- jQuery --> <script src="vendor/jquery/jquery.min.js"></script>
<!-- Bootstrap Core JavaScript --> <script src="vendor/bootstrap/js/bootstrap.min.js"></script>
<!-- Plugin JavaScript --> <script src=“vender/jquery/jquery.easing.min.js”></script>
<!-- Theme JavaScript --> <script src="js/agency.min.js"></script>
간단한 modal control, scroll effect 에 필요한 JavaScript 파일들
jQuery Free
![Page 16: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/16.jpg)
Scroll 효과 정도는 Vanilla로 충분
let mainNav = document.querySelector(“#mainNav");
window.addEventListener("scroll", (evt) => { let currentScrollY = window.pageYOffset; if(currentScrollY > MY_STATIC.SCROLL_TOP_CHANGE) { if(DOWNMODE) return; mainNav.classList.add("affix"); DOWNMODE = true; } else { mainNav.classList.remove("affix"); DOWNMODE = false;; }});
jQuery Free
let mainNav = document.querySelector(“#mainNav");
window.addEventListener("scroll", (evt) => { let currentScrollY = window.pageYOffset; if(currentScrollY > MY_STATIC.SCROLL_TOP_CHANGE) { if(DOWNMODE) return; mainNav.classList.add("affix"); DOWNMODE = true; } else { mainNav.classList.remove("affix"); DOWNMODE = false;; }});
demo
![Page 17: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/17.jpg)
Event Delegation
el.addEventListener("click", (evt) => {
evt.preventDefault();
let ellink = evt.target.closest(".portfolio-link");
if(!ellink) return;
let sHTML = this.myAsync.execAsyncAwait(ellink("href").substring(1));
document.querySelector("footer").insertAdjacentHTML('afterend', sHTML);
});
jQuery Free
Element.closest, matches 메서드만 잘써도 :-)
![Page 18: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/18.jpg)
은근 다 있다new XMLHttpRequest()
xhr.addEventListener
document.createElement
setAttribute
getElementsByTagName requestAnimationFrame
getBoundingClientRect
Object.prototype.toString.call
JSON.parse
bind
JSON.stringify
unshift
splice
Object.keys
forEach
isArray
Date.now
evt.stopPropagation
Math.round
parseInt
cloneNode
insertBefore
appendChild
localStorage.setItem
evt.changedTouches[0].pageY
querySelector
jQuery Free
![Page 19: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/19.jpg)
jQuery Free
if(bMouseEvent) { pageX = evt.pageX; pageY = evt.pageY; } else { pageX = evt.changedTouches[0].pageX; pageY = evt.changedTouches[0].pageY; }
this.nStartPosX = Math.floor(pageX);this.nStartPosY = Math.floor(pageY);
this.nStartTranslateX = _cu.getTranslate3dX(this.elTarget);
this.nTouchStartTime = Date.now();}
handlerTouchMove(evt) {evt.stopPropagation();if(this.bAnimationing) return;if(!this.bSwipe) return;
let bMouseEvent = evt.type.substr(0,5) === "mouse";let htCurrentEvt = (bMouseEvent) ? evt : evt.changedTouches[0];this.nMovePosX = Math.floor(htCurrentEvt.pageX);this.nMovePosY = Math.floor(htCurrentEvt.pageY);
….
Mobile Web & Vanilla 자연스럽다
![Page 20: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/20.jpg)
DOM Append Performance
var $c = $("<div />").addClass("container");for (var i=0; i<10000; i++) { $c.append($("<div />").addClass("test-div"));}$("BODY").append($c);
432.524ms
var c = document.createDocumentFragment();for (var i=0; i<10000; i++) { var e = document.createElement("div"); e.className = "test-div"; c.appendChild(e);}document.body.appendChild(c);
16.237ms
https://howchoo.com/g/mmu0nguznjg/learn-the-slow-and-fast-way-to-append-elements-to-the-dom
jQuery
Pure JavaScript
jQuery Free
![Page 21: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/21.jpg)
https://medium.com/the-vue-point/vue-2-0-is-here-ef1f26acf4b8#.7rbhdnuyp
rendering layer benchmark Oct,1,2016 by VueJS
DOM rendering layer performancejQuery Free
![Page 22: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/22.jpg)
jQuery PluginvanillaJS
Component
최근 5년간 jQuery Plugin TrendjQuery Free
![Page 23: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/23.jpg)
Clean jQuery Free
VanillaJS는 더 지속 가능한 코드다.
모바일웹에서 VanillaJS는 훌륭한 조합.
PC에서도 polyfill을 잘 활용하며 jQuery Free를!
pure DOM API가 대부분 상황에서는 가장 빠르다.
jQuery Free
![Page 24: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/24.jpg)
Modules
![Page 25: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/25.jpg)
Modules
import (ES2015)
import { member } from "module-name";
export default function (…) { … }
good-bye AMD API (Require.js)..
![Page 26: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/26.jpg)
CLASS
import tc from '../lib/TabComponent.js';
class MyAsync{ constructor() { this.name = "xhr"; }
simpleFetch(url) { return new Promise(function(resolve, reject) { var req = new XMLHttpRequest(); req.addEventListener("load", function() { let sData = JSON.parse(req.responseText); if(typeof sData !== "object") reject("wrong data"); else resolve(sData); }); req.open("GET", url); req.send(); });}
Modules
![Page 27: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/27.jpg)
Code
scroll effect코드를 import, export로 모듈화
Modules
![Page 28: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/28.jpg)
Clean Modules
Use Class & Import & Export !!
Modules
![Page 29: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/29.jpg)
Two-way Data Binding
![Page 30: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/30.jpg)
Two way binding
Two-way data binding
데이터가 변경될때, UI를 변경UI가 변경될때, 데이터를 변경
![Page 31: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/31.jpg)
Two way binding
Dirty Checking (digest cycle)작은 변화에 과한 렌더링. 지속적인 CPU 부하
Proxy (ES2015)Interception API
![Page 32: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/32.jpg)
Two way binding
let msgData = {};let elMessage = document.getElementById("message");
let msgProxy = new Proxy(msgData, {get: function(target, name, receiver) {
return target[name];}, set: function(obj, prop, value) {
obj[prop] = value; elMessage.value = value; document.getElementById("text-count").textContent = value.length; return true;}
});
elMessage.addEventListener("input", (evt)=>{msgProxy.content = evt.target.value;});
Proxy
![Page 33: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/33.jpg)
Two way binding
그런데 Proxy는 좀더 걸릴 듯 하다..
babel polyfill 로도 지원하지 않는 중
![Page 34: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/34.jpg)
Two way binding
Simple AccessorES5 getter/setter 통해 비교적 간단히 구현가능.
Object.defineProperty(obj, prop, descriptor)
![Page 35: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/35.jpg)
Two way binding
bindModel(obj, property, elView, fnCallback) { Object.defineProperty(obj, property, { get: function() { return elView.value; }, set: function(newValue) { elView.value = newValue; fnCallback(newValue); }, configurable: true });}
Simple Accessor
![Page 36: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/36.jpg)
Two way binding
demo
Data binding using ‘bindModelInput’
![Page 37: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/37.jpg)
Two way binding
Clean Two-way data bindingTwo-way data binding은 framework에서만 가능한 건 아님.
Proxy API를 지켜보자.
간단한 data binding은 defineProperty 로 간단히 처리!
![Page 38: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/38.jpg)
Asynchronous
![Page 39: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/39.jpg)
simpleAjax("../data/first.json", function(data) { try { var name = data.user.name; var imgUrl = "../data/img/" + name + ".json"; simpleAjax(imgUrl, function(data2) { try { setTimeout(function(){ try { var aImage = data2.images; aImage.forEach((v) => logMsg(elLog,v)); } catch (err) { console.log('error 3' , err ); } },500); } catch (err) { console.log('error 2' , err ); } }); } catch (err) { console.log("error 1: ", err); } });
Asynchronous
가끔 브라우저에서도 Hell
![Page 40: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/40.jpg)
Asynchronous
다행인지, Pure JavaScript에서는 그 해법이 쏟아져 나옴.
> Synchronous-looking style
![Page 41: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/41.jpg)
Asynchronous
Promise A+• 비동기 로직에서 콜백의 분리• thenable• async의 밑바탕 기술
function simpleFetch(url) { return new Promise(function(resolve, reject){ var req = new XMLHttpRequest(); req.addEventListener("load", function() { let htData = JSON.parse(req.responseText); if(typeof htData !== "object") reject("wrong data"); else resolve(htData); }); req.open("GET", url); req.send(); });}
simpleFetch("../data/first.json") .then(function(data) { var name = data.user.name; var imgUrl = "../data/img/" + name + ".json"; return simpleFetch(imgUrl); }) .then(function(data2) { return simpleSetTimeoutPromise(500,data2); }) .then(function(data3) { let elLog = document.querySelector(".log"); let aImage = data3.images; aImage.forEach((v) => logMsg(elLog,v)); }) .catch(function(err){ console.log("error : " + err); })
![Page 42: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/42.jpg)
Asynchronous
generator/yield
딱 비동기 문제를 위한 것만은 아니다.Promise와 조합하는게 좋고,
단, generator를 조정하는 역할을 하는 코드를 구현 함(runner)
function *myGeneratorWithPromise() { try { var data = yield simpleFetch("../data/first.json"); var url2 = "../data/img/" + data.user.name + ".json"; var data2 = yield simpleFetch(url2); var aImage = data2.images;
//do something..}
//code : https://davidwalsh.name/async-generators.function runGenerator(g) { var it = g(), ret; (function iterate(val){ ret = it.next( val );
if (!ret.done) { if (typeof ret.value === "object" && ("then" in ret.value)) { ret.value.then( iterate ); } else { setTimeout( function(){ iterate( ret.value ); }, 0 ); } } })();}
fnlist.generatorAndPromise = function() { runGenerator(myGeneratorWithPromise);}
![Page 43: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/43.jpg)
Asynchronous
wow! async/await !뭐 이건…좋다.async 함수는 promise를 반환한다는 점을 주의
ES2017 이라는 소문 +.+하지만 Babel과 함께라면 당장! (generator 로 변환)
fnlist.asyncAwait = async function () { try { var data = await simpleFetch("../data/first.json"); var url2 = "../data/img/" + data.user.name + ".json";
var data2 = await simpleFetch(url2);
var aImage = data2.images;
//parallel task using Promise.all function. var data3 = await Promise.all([ simpleSetTimeoutPromise(100, aImage), simpleSetTimeoutPromise(500, "dummy"), simpleSetTimeoutPromise(1000, "dummy"), ]);
var elLog = document.querySelector(".log"); data3[0].forEach((v) => logMsg(elLog,v));
} catch (err) { console.log("error during myGenerator : ", err); }} }
thanks to WebPack&Babel
![Page 44: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/44.jpg)
Asynchronous
observable (rx.js)
아.. 음..functional programming의 필요성을 진심 느끼는 분들께.
var chainPromise = Rx.Observable.just('../data/first.json') .flatMap(simpleFetch) .map( (x) => { return ("../data/img/" + x.user.name +".json")}) .flatMap(simpleFetch) .delay(500) .subscribe((x) => { let elLog = document.querySelector(".log"); let aImage = x.images; aImage.forEach((v) => logMsg(elLog,v)); });
thanks to WebPack&Babel
![Page 45: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/45.jpg)
Asynchronous
Clean Asynchronous
그럭저럭 콜백 지옥 상황에선, > 콜백 몸체를 분리하는 정도만으로 충분
빈번한 콜백 지옥이라면, > async,await 와 같은 다양한 방법으로 코드를 clean하게 구현
![Page 46: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/46.jpg)
Templating
![Page 47: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/47.jpg)
Pure Templating Engine
var templateRunner = function(sHtml){ return function(oData){ for(var value in oData){ var re = "{%\\s?" + value + “\\s?%}"; sHtml = sHtml.replace(new RegExp(re, "ig"), oData[value]); } return sHtml; };};
simple !
Templating
![Page 48: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/48.jpg)
서비스 logic 은 clean하게 유지.Template HTML은 쉽게 관리.PreCompile 로 좀더 갈끔하게
template html
template html
template html
PreCompile
[Build Step]
templatefunction
[Service Step]
복잡한 상황에서는 ?Templating
![Page 49: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/49.jpg)
PreCompile
loaders: [ { test : /\-tpl.hbs$/, loader : 'handlebars' }, …
Webpack handlebar-loader
Templating
![Page 50: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/50.jpg)
Templating with ES2015 Modules
var listTpl = require('/template/portfolioModal-tpl.hbs'); listTpl( { name: ‘hello codeSquad' } );
import modalTpl from '/template/portfolioModal-tpl.hbs';listTpl( { name: ‘hello codeSquad' } );
Templating
![Page 51: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/51.jpg)
Clean Templating
간단한 templating 은 replace 로 간단히 구현
복잡한 작업에서는 로직과 html을 잘 분리
Templating
![Page 52: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/52.jpg)
Virtual DOM view 처리의 또다른 해법
![Page 53: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/53.jpg)
VIEW조작의 복잡도를 해결하기 위해
virtual DOM 이 필요하고,
그래서 React를 써야 한다며?
Virtual DOM
> 일단, Virtual DOM 자체가 pure DOM보단
항상 빠른 건 아니다.
![Page 54: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/54.jpg)
https://vdom-benchmark.github.io/vdom-benchmark/
virtual DOM은 React가 짱인가?
simple한 virtual DOM 라이브러리가 2~3배 빠르다
Virtual DOM
![Page 55: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/55.jpg)
<ul className=”list”> <li>item 1</li> <li>item 2</li> </ul>
h(‘ul’, { className: ‘list’ }, h(‘li’, {}, ‘item 1’), h(‘li’, {}, ‘item 2’), );
참고, Virtual DOM 만들기 과정
JSX Transpiled code JavaScript Object
thanks to WebPack&Babel
Virtual DOM
{ type: ‘ul’, props: { className: ‘list’ }, children: [ { type: ‘li’, props: {}, children: [‘item 1’] }, { type: ‘li’, props: {}, children: [‘item 2’] }
] }
![Page 56: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/56.jpg)
function renderMaquette() { return h("ul.ul-wrap", [ aData.map(function(value, index) { return h("li" , [ h("span", [""+ value]) ]); }) ]); }
projector.replace(domNode, renderMaquette);
template library 와 비스무리.
Virtual DOM
Simple VD example(maquette.js)
![Page 57: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/57.jpg)
Simple VD example(maquette.js) Virtual DOM
![Page 58: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/58.jpg)
Clean Virtual DOM
VD는 성능이 분명 빠를 때 사용하기
사용해야하는 경우 코드의 복잡도는 더 올라갈 수 있음.
가벼운 VD 라이브러리가 좋은 선택지가 될 수 있음.
Virtual DOM
![Page 59: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/59.jpg)
Loose CouplingDependency Injection
![Page 60: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/60.jpg)
MODAL
Loose Coupling
XHR
JSONP
Local Storage
의존성있는 동일한 행위의 Class들과의 관계
느슨하게 유지하기
XHR
JSONP
Local Storage
Loose Coupling
![Page 61: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/61.jpg)
let dependencyContainer = { modalDependency : { storagePlugin : new XHR(), otherPlugin : new MyAsync() } }
let oModal = new Main(dependencyContainer.modalDependency);
Loose Coupling
조금 아쉬움이 있다
직접 class를 쓴 거랑 큰 차이는 안나고, Lazy instantiation 이 안되고.
Static Dependency Injection
![Page 62: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/62.jpg)
Loose Coupling
Register1
{XHR, Other2} new mainClass(...aDepClassInstance)getInstance2
Injection3
DI Factory
XHR JSONP LocalStorage
Other1 Other2 Other3
Dependencies Class
XHR Other2
Main Class
Dependency Injection
![Page 63: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/63.jpg)
Loose Coupling
class Service { constructor(storagePlugin, otherPlugin) { this.storagePlugin = storagePlugin; this.otherPlugin = otherPlugin; } getStorageData() { return this.storagePlugin.getData(); } getOtherData() { return this.otherPlugin.getData(); }}
Main Class
Dependency Injection의존성 있는 Class과의 관계는 느슨하다.
![Page 64: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/64.jpg)
Loose Coupling
//register depedencieslet myDI = new DIFactory();myDI.register('xhr', XHR);myDI.register('jsonp', JSONP);myDI.register('other', Other);
//dependency injectionlet cInstance = myDI.getInstance(Service, ["xhr","other"]);console.log(cInstance.getStorageData());
Service code
Dependency InjectionDependency 관계를 미리 정의하고, 인스턴스를 나중에 생성
![Page 65: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/65.jpg)
Loose Coupling
class DIFactory { constructor() {
this.matching = {}; } register(name, dClass) { this.matching[name] = new dClass(); } getInstance(mainClass, aDepClass) { let aDepClassInstance = aDepClass.map((v) => {
return this.matching[v]; });
return new mainClass(...aDepClassInstance); }}
DI Factory
이렇게 처리하기 위해 필요한 DI Factory 는 겨우 이정도
![Page 66: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/66.jpg)
Code
Dependency Injection using simple factory
![Page 67: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/67.jpg)
Register function
User custom function
subscribe publish
‘FN_AFTER_FOCUS’‘FN_AFTER_SUBMIT’
Remove methods of Dependencies.Resuable Codes
Plugin function
Emit Event
Plugin function
Loose Coupling
Custom Function & Event Driven
![Page 68: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/68.jpg)
Resuable Codes
Common Component
AA Component BB Component CC Component
A-1 plugin A-2 plugin B-1 plugin B-2 plugin C-1 plugin C-2 plugin
utility library
Component의 공통 기능
option 설정
plugin 등록
모든 파일에서 참고하는 유틸리티 메서드animation 처리
css 속성 추가
null 체크
..
Components
해당 component에 필요한 기능
Plugins
option으로 제공되는 추가기능.
LooseCoupling -> Resuable Component !Loose
Coupling
![Page 69: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/69.jpg)
Clean Loose Coupling
Dependency를 줄이는 패턴은 어렵고 복잡할 필요는 없다. 간단한 방법도 있다.
커다란 Framework에서만 구현 가능한 것도 아니다.
다양하게 구현된 Module, Component 상황에 최적의 방법이 무엇인지 고민하기
Loose Coupling
![Page 70: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/70.jpg)
사용된 코드는 여기,https://github.com/nigayo/cleanfe
Async 코드는 여기,https://github.com/nigayo/javascript-async
![Page 71: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/71.jpg)
Build Tools
![Page 72: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/72.jpg)
Without gulp or grunt only NPM !
NPM Builds
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "uglify": "mkdir -p dist/js && uglifyjs src/js/A.js src/js/B.js -m -o dist/js/all.min.js", "watch:js" : "onchange 'src/js/*.js' -- npm run uglify" },
NPM Scripts
간단하다면 npm build 만으로도 충분하다!
![Page 73: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/73.jpg)
"scripts": { "build": "webpack" },
entry: { 'script': ['babel-polyfill', './docs/js/main.js'], 'style': './docs/less/agency.less' }, watch: true, debug: true, devtool: 'source-map', module: { loaders: [ { test: /\.es6$/, exclude: /node_modules/, loader: "babel-loader", query: { presets: ['es2015', 'stage-3'] } }, { test: /\.(ttf.*|eot.*|woff.*|ogg|mp3|html)$/, loader: 'file-loader' }, { test: /.(png|jpe?g|gif|svg.*)$/, loader: 'file-loader!img-loader' }, {
webpack.configNPM Scripts
Without gulp or grunt NPM + Webpack
NPM Builds
![Page 74: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/74.jpg)
Clean Build tools
NPM Scripts 나 Webpack 만으로도 clean build환경을.
Resuable Codes
![Page 75: Clean Front-End Development](https://reader034.vdocuments.site/reader034/viewer/2022051521/587071311a28ab48378b795b/html5/thumbnails/75.jpg)
Standard code with all tools,
사용자에게 더 좋은 UX를 제공하고,
개발에서 또 다른 즐거움을 느끼길 바랍니다 :-)
마무리
그리고, 앞으로 더 많은 분들과 함께,이런 고민을 하게 되길 바라겠습니다
윤지수, codesquad [email protected]