ããŸã圌ãåŠå®ããæ¬¡ã«åœŒãæã¿ããããŠåœŒãªãã§ã¯çããããªãã
Artyom Kurbatovã®ã¬ããŒããBEMïŒmaster classããã
BEMæ¹æ³è«ã¯ããªãåããååšããŠãããGoogleãEPAM SystemsãBBCãAlfa Bankã§æ¡çšãããŠããŸãã ãã ããéåžžã®äžéã¬ãã«ã®éçºè
ããã³ãããžã§ã¯ããããŒãžã£ãŒã®éã§ã¯äŸç¶ãšããŠæžå¿µãçããŸãã

äžéšã®åããèŠããªäººã«ãšã£ãŠãBEMã®ç ç©¶ã¯ãããäºæž¬å¯èœãªçµæãââåŸãããã«CSSã®éçãè¶
ããŠããŸããã BEMã¯ã¬ã€ã¢ãŠããã¯ããã«è¶
ããŠããŸããããBEMãç¥ã£ãŠããŸããïŒããšãã質åãèãããšãã§ããŸããããã¡ãããããã¯ã¯ã©ã¹ã§äžç·ãåŒãããšã§ããã
BEMã®ã¢ã€ãã¢ãããã«è¿ãå Žåãæ°åã®åæ¥çãéçšããéã«éçšäž»ã®èšèã§çããŸããã以åBEMã«ã€ããŠèããããšãå¿ããŠãã ãããã BEMæ¹æ³è«ã¯ãã»ãšãã©ãäœãç¥ããªãã®ãšåããããè峿·±ããã®ã§ãã BEMã®çŸãããçè§£ããã«ã¯ãBEMãæäŸãããã¹ãŠã®ãã¯ãããžãŒãã©ã€ãã©ãªããã¬ãŒã ã¯ãŒã¯ãããã³ããŒã«ã®ã¢ã€ãã¢ãå¿
èŠã§ãã ããããç ç©¶ããå€åœäººã§ããç¶ãã倧人ãäœã«å¯ŸåŠããŠããã®ãçåã«æãåäŸã§ãã
ç®æ¬¡
ç§ã«ãšã£ãŠã®BEMãšã¯äœã§ããïŒ
ã¬ã¬ãŒãžã§éãã倧èãªãªã¿ã¯ãå¥ã®ã¹ã¿ãŒãã¢ãããçºæããæ¹æ³ã®è©±ãèããããšã¯ééããããŸããã æåã®æåã«ããã圌ãã¯æè³ãåŒã³èŸŒã¿ãé©ãã¹ã補åã§åžå Žã«åå
¥ããããšãã§ããŸããã 圌ãã¯ã©ã®ããã«æåããã©ã®ããã«ããŠããŒã¯è² è·ã«èããæ°žç¶çãªãªãã¡ã¯ã¿ãªã³ã°ã§è¡ãè©°ãŸãããšã¯ãããŸããã§ãããïŒ éåžžã§ã¯ãªããã©ã®ããã«å¿
èŠã§ããïŒ
BEMã¯ãã¹ã¿ãŒãã¢ããã®ã©ã€ãããã¯ã§ãã ä»ã®å€ãã®ãã¬ãŒã ã¯ãŒã¯ããã¯ãããžãŒãšæ¯èŒããŠãBEMã®äœ¿çšãéå§ããã«ã¯å€å°ã®åªåãå¿
èŠã§ãããæç¶å¯èœãªæ¡åŒµæ§ãæäŸããã¢ãŒããã¯ãã£ãåŸãããŸãã ãã¹ãŠã®BEMãã¯ãããžãŒããã¬ãŒã ã¯ãŒã¯ãããã³ã©ã€ãã©ãªã«ã¯ãæåã«å®£èšçã¢ãããŒãã®ååãçµã¿èŸŒãŸããŠããŸãã ãããŠãããã¯åœŒããäžèŠããŠçè§£ãã«ããããæçµçã«æãããã®ã§ãã
ãã®èšäºãèªãã åŸã¯ãBEM Zenãçè§£ããããšã¯ã§ããŸããããCSSã ãã§ãªãæ¬æ ŒçãªåçBEMãããžã§ã¯ããäœæããæ¹æ³ãåŠãã 倧人ã«ééããªãçããããšãã§ããŸãã ãŸããææ¥ãã¢ããªã±ãŒã·ã§ã³ã1æ¥ããã+10 KãŠãŒã¶ãŒãšããéåœã«é¥ã£ãå Žåãèœã¡çããŠãã ããããã®ã€ãã³ããç¥ãæéãããã§ãããã
仿¥ã¯ãåçãªbem-expressãããžã§ã¯ãã®æ°ãããã³ãã¬ãŒããªããžããªã«ã€ããŠèª¬æããŸããããã«ãããBEMãããžã§ã¯ããã¯ã³ã¯ãªãã¯ã§ãããã€ã§ããã ãã§ãªãããããžã§ã¯ããèªåçã«åæ§ç¯ãããã©ãŠã¶ããªããŒãã§ããŸãã ããã«åºã¥ããŠãåçã¢ããªã±ãŒã·ã§ã³ãéçºããããŸããŸãªBEMãã¯ãããžãŒã®çžäºäœçšããã»ã¹ã説æããŸãã ãã¯ã©ã¹ã§äžç·ãåŒããéåœãåé¿ããããã«ãã¬ã€ã¢ãŠããšã¯ã©ã€ã¢ã³ãåŽã®JavaScriptã®åé¡ãæèçã«æ€èšããããšã¯ãããŸããã
äœãéçºããŸããïŒ
ãœãŒã·ã£ã«ãµãŒãã¹æ€çŽ¢ããããïŒç¥ããŠSSSRïŒããªã¯ãšã¹ãã«å¿ããŠãYouTubeããã®ææ°ã®ãã€ãŒãããããªã衚瀺ããŸãã
以äžã䜿çšããŸãã
æåã«ã€ã³ã¹ããŒã«ããå¿
èŠããããŸãïŒ
éèŠïŒ WindowsãŠãŒã¶ãŒã¯ã Git Bashã远å ã§ã€ã³ã¹ããŒã«ããå¿
èŠããããŸãã
䜿çšããã衚èš
èšäºãæããããããã«ãå°ãæç»ããŸãã
-ãã£ã¬ã¯ããª;
-ãã¡ã€ã«;
-ãã£ã¬ã¯ããªãäœæããŸãã
-ãã¡ã€ã«ãäœæããŸãã
-ãã¡ã€ã«ãç·šéããŸãã
äœ¿çšæè¡
BEMã§ã¯ããã¯ãããžãŒãã¡ã€ã³ãšã»ã«ã³ããªã«åé¢ããããšã¯ãããŸããã ã»ããããããã¢ããªã±ãŒã·ã§ã³ã®éžæã¯åå¥ã«æ±ºå®ãããŸãã
- BEMDECLã¯ãBEMã§å®£èšãèšè¿°ããããã®ãã¯ãããžãŒã§ãã
- DEPSã¯ãBEMã§äŸåé¢ä¿ãèšè¿°ããããã®ãã¯ãããžãŒã§ãã
- BEMTREE-ããŒã¿ãBEMJSONã«å€æãããã³ãã¬ãŒããšã³ãžã³ã
- BEMHTML -BEMJSONãHTMLã«å€æãããã³ãã¬ãŒããšã³ãžã³ã
- i-bem.js -BEMã®JavaScriptãã¬ãŒã ã¯ãŒã¯ã
BEMJSONå
¥åãã©ãŒãããã®è©³çްãã芧ãã ããã
ãããã詳ããèŠãŠã¿ãŸãããã
BEMDECL
ããŒãžã®BEMãšã³ãã£ãã£ã®ãªã¹ããå®çŸ©ããŸãã
ãã®ãããªBEMã®ãªã¹ãã¯ã 宣èšãšåŒã°ããŸãã 宣èšã®ç®çã¯ãã¢ã»ã³ããªã«æ¥ç¶ããé åºãšé åºã決å®ããããšã§ãã
宣èšã¯ãæ¡åŒµåã.bemdecl.js
ãã¡ã€ã«ã«èšè¿°ãããŠããŸãã
äŸ
exports.blocks = [ { name: 'page' }, { name: 'header' }, { name: 'body' }, { name: 'footer' } ];
ãããã¯ã®æ°ããèŠãããããè¡ãè¶
ãããšãããããæ£ããé åºã§ãªã¹ããããšããåé¡ãçºçããŸãã ãããã£ãŠã圌ãã¯éåžžãç¹å®ã®ãããã¯ã宣èšããŸããããã¯ãäžå€®ã®ããšã³ããªãã€ã³ãããšèŠãªãããã¹ãã§ãã
ä»ã®ãã¹ãŠã®BEMãšã³ãã£ãã£ã¯ã äŸåé¢ä¿ã¢ã»ã³ããªã«åé¡ãããŸãã
Deps
ãããžã§ã¯ãã®ãã¡ã€ã«æ§é å
šäœã«åºããã宣èšã«ã¯åæ ãããªãBEMãšã³ãã£ãã£éã®äŸåé¢ä¿ãå®çŸ©ããŸãã
äŸåé¢ä¿ã¯ãæ¡åŒµåã.deps.js
ãã¡ã€ã«å
ã®JavaScriptãªããžã§ã¯ããšããŠèšè¿°ãããŸãã
äŸ
({ block: 'page', shouldDeps: [ { block: 'header' } ] })
ãã®ãã¯ãããžãŒã®ååã¯è±èªã®äŸåæ§ã«ç±æ¥ããBEMãšã³ãã£ãã£ãã¢ã»ã³ããªã«æ¥ç¶ããããšãæå³ããŸãã BEMã®åŠçã¯ããã¯ãããžãŒã®å®£èšçãªæ§è³ªãå¿ããããšããããå°æããŸãããã³ãã¬ãŒãã§èª¬æãããŠãããããã¯ã«ã€ããŠããã®ã¹ã¿ã€ã«ãšã¹ã¯ãªãããåéãããªãã®ã¯ãªãã§ããã
èŠããŠãããŠãã ããïŒäœããã®çš®é¡ã®ãããã¯ïŒåããŒãïŒãæã€ãã³ãã¬ãŒãïŒ BEMHTMLãŸãã¯BEMTREE ïŒãèšè¿°ãããšããæ°ããHTMLèŠçŽ ã远å ããã ãã§ãã ãã®ãããã¯ã®ã¹ã¿ã€ã«ãšã¹ã¯ãªãããã¢ã»ã³ããªã«å
¥ãããã«ã¯ãäŸåé¢ä¿ãèšè¿°ããå¿
èŠããããŸãã
ããšãã°ã header
ã body
ããã³footer
ãããã¯ãã¢ã»ã³ããªã«è¿œå ããã«ã¯ãããããžã®äŸåé¢ä¿ãèšè¿°ããå¿
èŠããããŸãã
({ block: 'page', shouldDeps: [ 'header', 'body', 'footer' ] })
次ã®å³ã¯ãäŸåé¢ä¿ããšã®ãã«ãããžãã¯ã瀺ããŠããŸãã
index(DECL) # page | âââ> page(DEPS) # page header, body, footer | âââ> header(DEPS) | | | âââ> ... | âââ> body(DEPS) | | | âââ> ... | âââ> footer(DEPS) | âââ> ...
ãã³ãã¬ãŒ
bem-xjstãã³ãã¬ãŒããšã³ãžã³ã®äžéšã§ãããããŒã¿ãBEMJSONã«å€æããŸãã
ãã³ãã¬ãŒãã¯ãæ¡åŒµå.bemtree.js
ãã¡ã€ã«ã«BEMJSON圢åŒã§èšè¿°ãããŠããŸãã
ãã³ãã¬ãŒãã®å
¥åãšåºåïŒ

BEMHTML
ããã¯bem-xjstãã³ãã¬ãŒããšã³ãžã³ã®äžéšã§ãããããŒãžã®BEMJSONèšè¿°ãHTMLã«å€æããŸãã
ãã³ãã¬ãŒãã¯ãæ¡åŒµåã.bemhtml.js
ãã¡ã€ã«ã«èšè¿°ãããŠããŸãã
ãã³ãã¬ãŒãã®å
¥åãšåºåïŒ

i-bem.js
ã¯ã©ã€ã¢ã³ã-BEMæ¹æ³è«ã®äžéšãšããŠã®Webéçºçšã®ãµã€ãJavaScriptãã¬ãŒã ã¯ãŒã¯ ã
JavaScriptã³ãŒãã¯ãæ¡åŒµåã.js
ãã¡ã€ã«ã«èšè¿°ãããŠããŸãã
èš±å¯ïŒ
- ãããã¯ãèŠçŽ ã修食åã«é¢ããWebã€ã³ã¿ãŒãã§ã€ã¹ãéçºããŸãã
- ãããã¯ã®ããžãã¯ã宣èšã¹ã¿ã€ã«ã§-ç¶æ
ã®ã»ãããšããŠèšè¿°ããŸãã
- JavaScriptã³ãŒããšBEMHTMLãã³ãã¬ãŒãããã³CSSãç°¡åã«çµ±å
- ã©ã€ãã©ãªãããã¯ã®åäœãæè»ã«åå®çŸ©ããŸãã
ããã«ã¡ã¯ãWorldã¢ããª
ããã°ã©ããŒã«ã¯äŒçµ±ããããŸããHelloãWorldã¢ããªã±ãŒã·ã§ã³ã䜿çšããŠãæ°ããèšèªãŸãã¯ãã¬ãŒã ã¯ãŒã¯ã§ããã°ã©ãã³ã°ãéå§ããŠãã ããã ã¢ããªã±ãŒã·ã§ã³ã¯éåžžããHelloãWorldããšããåèªãåºåã¹ããªãŒã ã«æžã蟌ã¿ãŸããããã«ãããã¢ããªã±ãŒã·ã§ã³ãéå§ããI / Oãå®è¡ããããšã瀺ããŸãã
äœæããŠãç®çã®SSSRã«å±éããŸãã
bem-expressãã³ãã¬ãŒããªããžããªã®ããŒã«ã«ã³ããŒãå¿
èŠã§ã ã Gitã䜿çšããŠå®è¡ã§ããŸãã
ãæ³šæ OS XãŸãã¯Linuxã®ãŠãŒã¶ãŒã®å Žåããã¹ãŠã®ã³ãã³ãã¯ã¿ãŒããã«ã§å®è¡ãããŸãã WindowsãŠãŒã¶ãŒã«ã¯Git Bashãå¿
èŠã«ãªããŸãã Git Bashã管çè
ãšããŠå®è¡ãããŠããããšã確èªããŠãã ããã
ãã³ãã¬ãŒããªããžããª
BEMã®ãã¬ãŒã ã¯ãŒã¯å
ã§åçã¢ããªã±ãŒã·ã§ã³ãéçºããåé¡ã解決ããããã«ããã³ãã¬ãŒããªããžããªbem-expressãäœæãããŸãã ã å¿
èŠãªæå°æ§æãã¡ã€ã«ãå«ãŸããŠããããããžã§ã¯ãã®æ§ç¯ããªã³ã¿ãŒã®ã»ããã¢ãããã©ã€ãã©ãªã®æ¥ç¶ãªã©ãã¿ã¹ã¯ã®ã¯ã©ã¹å
šäœã解決ããŸãã
ã¡ã€ã³ã®BEMã©ã€ãã©ãªã¯ããã©ã«ãã§æ¥ç¶ãããŠããŸãïŒ
ã¯ã€ãã¯ã¹ã¿ãŒã
HelloãWorldã¢ããªã±ãŒã·ã§ã³ãäœæããã«ã¯ïŒ
bem-expressã®ã¯ããŒã³ïŒ
git clone https://github.com/bem/bem-express.git sssr-project
ãæ³šæ ãã®äŸã§ã¯ã bem-express
ããŒãžã§ã³2.00ã䜿çšããŸãã
ãããžã§ã¯ããã£ã¬ã¯ããªã«ç§»åããŸãã
cd sssr-project
ãœãŒã¹ãªããžããªã®ããŒãžã§ã³ç®¡çå±¥æŽãåé€ããŸãã
rm -rf .git
ç¬èªã®GitãªããžããªãåæåããŸãã
git init
äŸåé¢ä¿ãã€ã³ã¹ããŒã«ããŸãã
npm install
ãæ³šæ npmäŸåé¢ä¿ãã€ã³ã¹ããŒã«ãããšãã«ãã«ãŒãã¹ãŒããŒãŠãŒã¶ãŒroot
䜿çšããªãã§ãã ããã
ãããžã§ã¯ãããã«ããããµãŒããŒãèµ·åããŸãã
npm run dev
ãæ³šæ ã¢ã»ã³ããªã¯ENBãæ
åœããŸãã
ã¢ããªã±ãŒã·ã§ã³ãèµ·åãããšãã¿ãŒããã«ã«ãµãŒããŒãããŒã3000ã§å®è¡ãããŠãããšããã¡ãã»ãŒãžã衚瀺ãããŸãã
Server is listening on 3000
ãŸãã
ãæ³šæ ããŒã3000
å¥ã®ããã°ã©ã ã§äœ¿çšãããŠããå Žåã¯ãåå²ãåœãŠã§ããŸãã ããšãã°ã 8000
ïŒ
æ¹æ³1.ã¢ããªã±ãŒã·ã§ã³ã®èµ·åæã«å€ã倿ŽããŸãã
PORT=8000 npm run dev
æ¹æ³server/config.js
ããã©ã«ãå€ã倿Žãserver/config.js
ã
defaultPort: 8000,
ã³ã³ãã¥ãŒã¿ãŒäžã§éå§ãããŸããïŒ
- ãµãŒããŒ-åçããŒã¿ã®åŠçãæ
åœããŸãã
- nodemon- ãã¡ã€ã«æ§é ã®å€æŽãç£èŠãããµãŒããŒãåèµ·åããŸãã
- chokidar-
*.blocks/
ãã£ã¬ã¯ããªãã¡ã€ã«ã®å€æŽãç£èŠãããããžã§ã¯ãæ§é ãåæ§ç¯ããŸãã - livereload-ãã©ãŠã¶ã®ããŒãžãæŽæ°ããŸãã
ãã©ãŠã¶ãŒãéãã localhostïŒ3000ã¢ãã¬ã¹ãå
¥åããŸãã
次ã®ã³ã³ãã³ããå«ãããŒãžãéããŸãã
Index page content footer content
ãæ³šæ Windowsã§ã¢ããªã±ãŒã·ã§ã³ãèµ·åãããšãã«ããã¡ã€ã¢ãŠã©ãŒã«ããéç¥ã衚瀺ãããå ŽåïŒ
- [ ãããªãã¯ãããã¯ãŒã¯ ]ãªãã·ã§ã³ããªãã«ããŸãã
- ãªãã·ã§ã³Private Networksãèšå®ããŸãã
- ã¢ã¯ã»ã¹ãèš±å¯ããŸãã
server/index.js
ãéããè¡app.get('/', function(req, res)
å§ãŸãã³ãŒãã§ä»¥äžã®å€æŽïŒã³ã¡ã³ããåç
§ïŒãè¡ããŸãã
app.get('/', function(req, res) { var hello = 'Hello'; // `hello` var world = 'World'; // `world` render(req, res, { view: 'page-index', title: 'Main page', meta: { description: 'Page description', og: { url: 'https://site.com', siteName: 'Site name' } }, hello: hello, // `hello` `this.data.hello` world: world // `world` `this.data.world` }) });
ãã¡ã€ã«common.blocks/page-index/page-index.bemtree.js
ããã®å
å®¹ãæ¬¡ã®ãã®ã«çœ®ãæããŸãã
block('page-index').content()(function() { // `this` var data = this.data; // : `data.hello: 'Hello'`, `data.world: 'World'` return data.hello + ', ' + data.world; });
ä¿ååŸããµãŒããŒã¯èªåçã«åèµ·åããããŒãžã³ã³ãã³ããæ¬¡ã®ããã«å€æŽãããŸãã
Hello, World footer content
ããã«ã¡ã¯ãWorldã¢ããªã®æºåãã§ããŸããã
ããŸããããªãã£ãïŒ
ã¢ããªã±ãŒã·ã§ã³ã®äœæäžã«åé¡ãçºçããå Žåã¯ã ãã©ãŒã©ã ã§è§£æ±ºçãæ¢ããŠãã ãã ã æºåãã§ããŠããªãå Žåã¯ã質åããŠãã ããã
ãœãŒã·ã£ã«ãµãŒãã¹æ€çŽ¢ããããã¢ããª
å®éãSSSRã¢ããªã±ãŒã·ã§ã³ãéçºããæ®µéã«å°éããŸããã ãªã¯ãšã¹ãã«å¿ããŠãã¢ããªã±ãŒã·ã§ã³ã¯YouTubeããã®ææ°ã®ãã€ãŒããšãããªã衚瀺ããããšãæãåºãããŠãã ããã
ããã«è¿ãå°æ¥ã«å®è¡ãããŸã-ã¢ããªã±ãŒã·ã§ã³ã¯æ¬¡ã®ããã«ãªããŸãã

å¿åã¹ããŒã
圌女ã¯èšäºã®ç޹ä»éšåã§èŠãŸããã ã¹ããã1.ãªã¯ãšã¹ã
ãŠãŒã¶ãŒã¯ãµãŒããŒã«ãªã¯ãšã¹ããéä¿¡ããŸãã
ã¹ããã2.ããŒã¿ã®ååŸ
ã¢ããªã±ãŒã·ã§ã³ã¯ãåãåã£ãèŠæ±ã«åŸã£ãŠTwitter Search APIããã³YouTube Data APIã«ããŒã¿ãèŠæ±ããŸãã
ã¹ããã3. BEMTREEãã³ãã¬ãŒã
ã¢ããªã±ãŒã·ã§ã³ã¯ãåä¿¡ããããŒã¿ãBEMTREEãã³ãã¬ãŒããšã³ãžã³ã«æž¡ããŸããBEMTREEãã³ãã¬ãŒããšã³ãžã³ã¯ãããŒã¿ãBEMJSONã«å€æããŸãã
ã¹ããã4. BEMHTMLãã³ãã¬ãŒã
ã¢ããªã±ãŒã·ã§ã³ã¯ãBEMJSONãHTMLã«å€æããBEMHTMLãã³ãã¬ãŒããšã³ãžã³ã«BEMJSONãæž¡ããŸãã
ã¹ããã5.çµæããŠãŒã¶ãŒã«éä¿¡ãã
ã¢ããªã±ãŒã·ã§ã³ã¯çµæïŒHTMLããŒãžïŒããŠãŒã¶ãŒã«è¿ããŸãã
äœ¿çšæžã¿ããŒãã¢ãžã¥ãŒã«
Nodeã®åºæ¬çãªå®è£
ã¯å¯èœãªéãã·ã³ãã«ãªãŸãŸã§ãã ãã¹ãŠã®å¯èœãªã³ã³ããŒãã³ããNodeã«çŽæ¥åã蟌ã代ããã«ãéçºè
ã¯è¿œå ã®æ©èœãåå¥ã®ã¢ãžã¥ãŒã«ïŒããã±ãŒãžïŒã®åœ¢ã§æäŸããŸãã
Nodeã¢ãžã¥ãŒã«ã·ã¹ãã ã¯ãçžäºäœçšããã¢ãžã¥ãŒã«ãäœæããã¡ã«ããºã ã§ããCommonJSã·ã¹ãã ãã¢ãã«ã«ããŠããŸãã ã·ã¹ãã ã®äžå¿ã¯å¥çŽã«ãã£ãŠå ããããŠããŸããå¥çŽã¯éçºè
ãå®è¡ããå¿
èŠããããŸãããã®ãããéçºè
ã®ã¢ãžã¥ãŒã«ã¯éåžžãä»ã®ã¢ãžã¥ãŒã«ãšå¯Ÿè©±ããŸãã
npmããã±ãŒãžãããŒãžã£ãŒã䜿çšããŠã€ã³ã¹ããŒã«ããããã¹ãŠã®ããã±ãŒãžã¯ã node_modules
ãã£ã¬ã¯ããªã«ãããŸãã
ã¢ãžã¥ãŒã«ã¯require
ã³ãã³ãã䜿çšããŠæ¥ç¶ãããŸãã ããã±ãŒãžãnpmã䜿çšããŠã€ã³ã¹ããŒã«ãããŠããå Žåããã¹ãæå®ããå¿
èŠã¯ãããŸããã ååã瀺ãã ãã§ååã§ãã
var express = require('express');
ç¬èªã®ããŒã«ã«ã¢ãžã¥ãŒã«ãæ¥ç¶ãããšãã¯ããã®ã¢ãžã¥ãŒã«ãžã®ãã¹ãæå®ããå¿
èŠããããŸãã
var someModule = require('./somefolder/somemodule');
ã¢ãžã¥ãŒã«ã®éèŠãªæ©èœã¯ãNodeãšå¯Ÿè©±ããããã«èšèšããå¿
èŠãããããšã§ãã ãããè¡ãã«ã¯ã module.exports
ã䜿çšããŠã¢ãžã¥ãŒã«ããšã¯ã¹ããŒãããå¿
èŠããããŸãã
module.exports = {
ã¢ããªã±ãŒã·ã§ã³ãæ©èœããã«ã¯ã次ã®ã¢ãžã¥ãŒã«ãå¿
èŠã§ãã
- ãšã¯ã¹ãã¬ã¹ -Webã¢ããªã±ãŒã·ã§ã³ã®æ§ç¯ã«å¿
èŠãªæ©èœã®ã»ãšãã©ãæäŸããŸãã
- ãã¹ããŒã -Node.jsã¢ããªã±ãŒã·ã§ã³ã«ããŸããŸãªèªèšŒæŠç¥ãæäŸããŸãã
- passport-youtube-v3 -Youtubeã¢ã«ãŠã³ããšOAuth 2.0ããŒã¯ã³ãä»ããŠYoutubeã§èªèšŒã¡ã«ããºã ãæäŸããŸãã
- twitter -Twitter REST APIãæäœããããã®ã¯ã©ã€ã¢ã³ãã©ã€ãã©ãªã
- googleapis -Google REST APIãæäœããããã®ã¯ã©ã€ã¢ã³ãã©ã€ãã©ãªã
- moment-æ¥ä»ã®è§£æãæ€èšŒããã©ãŒãããçšã®JavaScriptã©ã€ãã©ãªã
1ã€ã®ã³ãã³ãã§ã€ã³ã¹ããŒã«ã§ããŸãïŒ
npm install express passport passport-youtube-v3 twitter googleapis moment --save
ãããžã§ã¯ãæ§é ã®æºå
ã³ãŒããæžãå§ããåã«ãåºç€ãšãªãHelloãWorldã¢ããªã±ãŒã·ã§ã³ã®æ§é ãå°ã倿ŽããŸãããã
倿Žç¹ïŒ
éçãã¡ã€ã«ã®å€æŽ

static
ãã£ã¬ã¯ããª
common.blocks
ãã£ã¬ã¯ããª
root/root.bemtree.js
ç·šéãroot/root.bemtree.js
ã
倿ŽïŒ
favicon: '/favicon.ico',
ãªã³ïŒ
favicon: '/images/favicon.ico',
å®å
šãªroot.bemtree.jsã³ãŒã ã
server
ãã£ã¬ã¯ããª
index.js
ãã¡ã€ã«ãç·šéããŸãã
倿ŽïŒ
.use(favicon(path.join(staticFolder, 'favicon.ico')))
ãªã³ïŒ
.use(favicon(path.join(staticFolder, '/images/favicon.ico')))
å®å
šãªã³ãŒãindex.js
ãµãŒããŒã³ãŒãã®å€æŽ

server
ãã£ã¬ã¯ããª
ãµããã£ã¬ã¯ããªãäœæããŸãã
controllers
-ã³ã³ãããŒã©ãŒ;helpers
-ãã«ããŒ;middleware
- middleware
ã¢ãžã¥ãŒã«ã
å°æ¥ã®ã¢ãžã¥ãŒã«çšã«ç©ºã®JS
ãã¡ã€ã«ãäœæããŸãã
app.js
äžéã¢ãžã¥ãŒã«ãããŠã³ãããããã®ã¢ãžã¥ãŒã«ïŒã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšå¯èœã«ããŸãïŒ;auth.js
-YouTubeèªèšŒã¢ãžã¥ãŒã«ãroutes.js
-WebèŠæ±ã«ãŒãã£ã³ã°ã¢ãžã¥ãŒã«ã
app.js
ãã¡ã€ã«ã«æ¬¡ã®ã³ãŒãã远å ããŸãã
routes.js
ãã¡ã€ã«ã«æ¬¡ã®ã³ãŒãã远å ããŸãã
æ§æãã¡ã€ã«ã®æ¡åŒµåã倿ŽããŸãã
config.js
> config.json
config.json
ãã¡ã€ã«ãç·šéããŸãã
倿ŽïŒ
module.exports = { staticFolder: 'static', defaultPort: 3000, cacheTTL: 30000, sessionSecret: 'REPLACE_ME_WITH_RANDOM_STRING' };
ãªã³ïŒ
{ "staticFolder": "static", "defaultPort": 3000, "cacheTTL": 30000, "sessionSecret": "REPLACE_ME_WITH_RANDOM_STRING" }
index.js
ãã¡ã€ã«ã®çŸåšã®ãã¹ãŠã®ã³ã³ãã³ããæ¬¡ã®ããã«å€æŽããŸã ã
ãæ³šæ index.js
ãã¢ããªã±ãŒã·ã§ã³ãèµ·åããããŒãã§ãªã¯ãšã¹ãããªãã¹ã³ããæ©èœã®ã¿index.js
æ®ããŸãã
controllers
ãã£ã¬ã¯ããª
helpers
ãã£ã¬ã¯ããª
middleware
ãã£ã¬ã¯ããª
OAuthããŒã¯ã³ã®ååŸ
Twitterããã³GoogleãµãŒãã¹ã«ã¯ããã€ãŒããYoutubeäžã®ãããªãã¡ãŒã«ã®æçŽãåçãªã©ãããŸããŸãªãŠãŒã¶ãŒããŒã¿ãä¿åãããŸãã ä»ã®ã¢ããªã±ãŒã·ã§ã³ãŸãã¯ãµãŒãããŒãã£ã®ãµãŒãã¹ãããã®ããŒã¿ãžã®äŸ¿å©ãªã¢ã¯ã»ã¹ãæäŸããããã«ã圌ãã¯OAuth 2.0ãªãŒãã³èªèšŒãããã³ã«ã䜿çšããŸã ã
ãããã³ã«ã«åŸã£ãŠãéçºè
ã¯OAuthãµãŒããŒã«ã¢ããªã±ãŒã·ã§ã³ãç»é²ããç¹å®ã®ããŒã¿ãžã®ã¢ã¯ã»ã¹ãèŠæ±ããŸãã èš±å¯ããããŠãŒã¶ãŒã¯ãããèš±å¯ãŸãã¯æåŠããŸãã
Twitterã¯ãã¢ããªã±ãŒã·ã§ã³èªäœã«ä»£ãã£ãŠèªèšŒæžã¿ãªã¯ãšã¹ããçºè¡ããæ©èœãã¢ããªã±ãŒã·ã§ã³ã«æäŸããŸãã
ã©ãããå§ããŸããïŒ
- ããã¥ã¡ã³ãã確èªããŠãã ããã
- ã¢ããªã±ãŒã·ã§ã³ãç»é²ããããŒïŒã³ã³ã·ã¥ãŒãããŒãã³ã³ã·ã¥ãŒãã·ãŒã¯ã¬ããïŒãååŸããŸãã
- 䟿å©ãªæ¹æ³ã§Postmanãã€ã³ã¹ããŒã«ããŸãã
- Base64ã¡ãœããã䜿çšããŠã
Consumer Key:Consumer Secret
æååããšã³ã³ãŒãããŸãã - ã³ãŒããšåŒãæãã«OAuthããŒã¯ã³ãååŸããŸã ã
Twitter Search APIãžã®ãªã¯ãšã¹ãã§ãåä¿¡ããããŒã¯ã³ãšããŒã䜿çšããŸãã
ãæ³šæ Postmanã¯ãBase64ã¡ãœããã§åä¿¡ããã³ãŒããšåŒãæãã«POSTãªã¯ãšã¹ãã䜿çšããŠOAuthããŒã¯ã³ãååŸããã®ã«åœ¹ç«ã¡ãŸãã
æååããšã³ã³ãŒãããæ¹æ³ã¯ïŒ
Base64ã¡ãœããã䜿çšããŠæååããšã³ã³ãŒãããã«ã¯ïŒ
次ã®åœ¢åŒã®è¡ãäœæããŸãïŒ Consumer Key:Consumer Secret
ã
äŸ
xvz1evFS4wEEPTGEFPHBog:L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg
ãæ³šæ ã¢ããªã±ãŒã·ã§ã³ã® [ããŒãšã¢ã¯ã»ã¹ããŒã¯ã³]ã¿ãã«ç§»åã㊠ãã³ã³ã·ã¥ãŒãããŒãšã³ã³ã·ã¥ãŒãã·ãŒã¯ã¬ããããŒãååŸã§ããŸã ã
- ã¿ãŒããã«ãŸãã¯Git Bashãèµ·åããŸãã
- ã³ãã³ã
echo -n "xvz1evFS4wEEPTGEFPHBog:L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg" | base64
å®è¡ããŸãecho -n "xvz1evFS4wEEPTGEFPHBog:L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg" | base64
echo -n "xvz1evFS4wEEPTGEFPHBog:L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg" | base64
ã çµæã®ã³ãŒããã³ããŒããŸãã
äŸ
eHZ6MWV2RlM0d0VFUFRHRUZQSEdFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==
ãæ³šæ åé¡ãããå Žåã¯ã base64encode.orgãªã³ã©ã€ã³ãªãœãŒã¹ã䜿çšããŠãã ãã ã
ã³ãŒããšåŒãæãã«OAuthããŒã¯ã³ãååŸããæ¹æ³ã¯ïŒ
ã³ãŒããšåŒãæãã«ããŒã¯ã³ãåãåãã«ã¯ïŒ
Postmanãèµ·åããŸãã
ãæ³šæ ããã©ã«ãã§ã¯ãTwitter OAuthãµãŒããŒãžã®POSTãªã¯ãšã¹ããçæããå¿
èŠãããã¿ããéããŸãã
- POSTãªã¯ãšã¹ãã®ã¿ã€ããéžæããŸãã
- ãµãŒããŒã¢ãã¬ã¹
https://api.twitter.com/oauth2/token
å
¥åããŸãã - [ããããŒ]ã¿ãã«ç§»åããŸãã
å€ïŒå€ãã£ãŒã«ãïŒ Basic < Consumer Key:Consumer Secret>
ããŠãKeyãã£ãŒã«ãã«Authorization
èŠåºããå
¥åãBasic < Consumer Key:Consumer Secret>
ã
äŸ
Authorization: Basic eHZ6MWV2RlM0d0VFUFRHRUZQSEdFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==
ãæ³šæ Basicã¯ãåºæ¬çãªèªèšŒæ¹æ³ã瀺ããŸãã
å€application/x-www-form-urlencoded;charset=UTF-8
ã®2çªç®ã®Content-Type
ããããŒãå
¥åãapplication/x-www-form-urlencoded;charset=UTF-8
ã
äŸ
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
- [ããã£]ã¿ãã«ç§»åããŸãã
x-www-form-urlencoded
ãªãã·ã§ã³ãéžæããŸãã- ãããŒããã£ãŒã«ãã«å€
client_credentials
ãæã€grant_type
ãªã¯ãšã¹ãgrant_type
ãå
¥åããŸãã éä¿¡ãã¿ã³ãã¯ãªãã¯ããŸãã
OAuthãµãŒããŒã¯ãJSON圢åŒã§ããŒã¯ã³ãè¿ããŸãã
{ "token_type": "bearer", "access_token": "AAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAA" }
éèŠïŒ åä¿¡ããããŒã¯ã³ãšããŒïŒã³ã³ã·ã¥ãŒãããŒãšã³ã³ã·ã¥ãŒãã·ãŒã¯ã¬ããïŒãä¿åããŸãã ãããã¯ãã¢ããªã±ãŒã·ã§ã³æ§æãã¡ã€ã«ã«å¿
èŠã§ã ã
Googleã®OAuthããŒã¯ã³ãååŸãã
Googleã¯ãã¢ããªã±ãŒã·ã§ã³èªäœã«ä»£ãã£ãŠèªèšŒæžã¿ãªã¯ãšã¹ããçºè¡ããæ©èœãã¢ããªã±ãŒã·ã§ã³ã«æäŸããŸãã
ãæ³šæ passport-youtube-v3ã¢ãžã¥ãŒã«ã¯ãèªèšŒã³ãŒããšåŒãæãã«POSTãªã¯ãšã¹ãã䜿çšããŠOAuthããŒã¯ã³ãåä¿¡ããã³æŽæ°ããŸãã
ã©ãããå§ããŸããïŒ
- ããã¥ã¡ã³ãã確èªããŠãã ããã
- ã¢ããªã±ãŒã·ã§ã³ãç»é²ããã¯ã©ã€ã¢ã³ãIDãšã¯ã©ã€ã¢ã³ãã·ãŒã¯ã¬ãããååŸããŸã ã
- ã¢ããªã±ãŒã·ã§ã³ã¢ã«ãŠã³ãã«ã³ãŒã«ããã¯URLïŒãã®å Žåã¯
http://localhost:3000
ïŒãå
¥åããŸãã - YouTube Data APIãžã®ãªã¯ãšã¹ãã§ã¯ãåä¿¡ããã¯ã©ã€ã¢ã³ãIDãšã¯ã©ã€ã¢ã³ãã·ãŒã¯ã¬ããã䜿çšããŸãã
éèŠïŒ åä¿¡ããããŒïŒã¯ã©ã€ã¢ã³ãIDãšã¯ã©ã€ã¢ã³ãã·ãŒã¯ã¬ããïŒãä¿åããŸãã ãããã¯ãã¢ããªã±ãŒã·ã§ã³æ§æãã¡ã€ã«ã«å¿
èŠã§ã ã
ã¢ããªã±ãŒã·ã§ã³æ§æ
ãã¹ãŠã®ããŒãšããŒã¯ã³ãåãåã£ãåŸãããããã¢ããªã±ãŒã·ã§ã³æ§æãã¡ã€ã«ã«è¿œå ããå¿
èŠããããŸãã
services
ãã£ãŒã«ããserver/config.json
ãã¡ã€ã«ã«è¿œå ããŸãã
"services": { "twitter": { "consumer_key": "", "consumer_secret": "", "bearer_token": "" }, "youtube": { "client_id": "", "client_secret": "", "redirect_url": "http://localhost:3000" } }
å®å
šãªconfig.jsonã³ãŒã ã
- åãååã®ãã£ãŒã«ãã«åä¿¡ããŒã¿ãå
¥åããŸã ã
server/config.json
ãGitããŒãžã§ã³ç®¡çã·ã¹ãã ããéserver/config.json
ããŠããã¡ã€ã«ãªããžããªã«èª€ã£ãŠç§å¯ããŒã远å ããªãããã«ããŸãã
å®å
šãª.gitignoreã³ãŒã
Twitter Search APIã䜿çšãããšãTwitter.comã§éå»7æ¥éã«å
¬éãããææ°ãŸãã¯æã人æ°ã®ãããã€ãŒããèŠã€ããããšãã§ããŸãã
APIãæ£åžžã«åŒã³åºãã«ã¯ã次ã®å€æŽãè¡ãå¿
èŠããããŸãã

controllers
ãã£ã¬ã¯ããª
helpers
ãã£ã¬ã¯ããª
YouTube Data APIã䜿çšãã
YouTube Data APIã䜿çšãããšãYoutube.comã§å
¬éãããŠãããããªãæ€çŽ¢ã§ããŸãã ããã©ã«ãã§ã¯ã次ã®ãªãœãŒã¹ãæ€çŽ¢çµæã»ããã«å«ãŸããŠããŸãïŒãããªããã£ã³ãã«ããã¬ã€ãªã¹ãã
APIãæ£åžžã«åŒã³åºãã«ã¯ã次ã®å€æŽãè¡ãå¿
èŠããããŸãã

server
ãã£ã¬ã¯ããª
次ã®ã³ãŒããauth.js
ãã¡ã€ã«ã«è¿œå ããŸãã
routes.js
ãã¡ã€ã«ãç·šéããŸãã
倿ŽïŒ
var router = require('express').Router(), controllers = require('./controllers'); router .get('/ping/', function(req, res) { res.send('ok'); }) .get('/', controllers.getContent); module.exports = router;
ãªã³ïŒ
var router = require('express').Router(), controllers = require('./controllers'), passportYouTube = require('./auth'), middleware = require('./middleware/auth'), isAuthenticated = middleware.isAuthenticated; router .get('/auth/youtube', passportYouTube.authenticate('youtube')) .get('/auth/youtube/callback', passportYouTube.authenticate('youtube', { failureRedirect: '/error', failureFlash: true }), (req, res) => { res.redirect('/'); }) .get('/', isAuthenticated, controllers.getContent); module.exports = router;
controllers
ãã£ã¬ã¯ããª
helpers
ãã£ã¬ã¯ããª
次ã®ã³ã³ãã³ããindex.js
ãã¡ã€ã«ã«è¿œå ããŸãïŒã³ã¡ã³ããåç
§ïŒã
module.exports = { twitter: require('./twitter'), youtube: require('./youtube')
- 次ã®ã³ãŒãã
youtube.js
ãã¡ã€ã«ã«è¿œå ããŸãã
middleware
ãã£ã¬ã¯ããª
auth.js
ãã¡ã€ã«ã«æ¬¡ã®ã³ã³ãã³ãã远å ããŸãã
module.exports = { isAuthenticated: function(req, res, next) { if (req.isAuthenticated()) return next(); return res.redirect('/auth/youtube'); } };
ã¬ã€ã¢ãŠã
ã¬ã€ã¢ãŠããšã¯ã©ã€ã¢ã³ãã®JavaScriptã®åé¡ãæå³çã«èæ
®ããŸããã§ããã ããã«ãããããªã¥ãŒã ã倧ãããªãããããã®èšäºã®å®çšçãªäŸ¡å€ã¯äœããªããŸãã
ã¬ã€ã¢ãŠãããã»ã¹ã¯æ¬¡ã®æé ã«ç°¡ç¥åãããŸãã
common.blocks
ãã£ã¬ã¯ããªãããã¹ãŠã®ãããã¯ãåé€ããŸãã- 次ã®ãããã¯ã
common.blocks
ãã£ã¬ã¯ããªã«common.blocks
ãŸãã - logo.svgã
static/images
ãã£ã¬ã¯ããªã«è¿œå ããŸãã - ãµãŒããŒãåèµ·åããŸãïŒ
npm run dev
ã
瀟äŒãµãŒãã¹æ€çŽ¢ããããã®æºåãã§ããŸããã
ããŸããããªãã£ãïŒ
ã¢ããªã±ãŒã·ã§ã³ã®äœæäžã«åé¡ãçºçããå Žåã¯ã ãã©ãŒã©ã ã§è§£æ±ºçãæ¢ããŠãã ãã ã æºåãã§ããŠããªãå Žåã¯ã質åããŠãã ããã