-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.html
719 lines (629 loc) · 25.8 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Redux Intro</title>
<meta name="description" content="Redux Intro">
<meta name="author" content="C. T. Lin">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
<link rel="stylesheet" href="css/reveal.css">
<link rel="stylesheet" href="css/theme/black.css" id="theme">
<!-- Code syntax highlighting -->
<link rel="stylesheet" href="node_modules/prismjs/themes/prism.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
<style>
.reveal pre code { max-height: 500px !important;}
a { color: white !important; text-decoration: underline !important;}
</style>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section data-background="#b5533c">
<p style="font-size: 3em">Redux</p>
<p style="font-size: 1.1em">predictable state container</p>
<p>
<small><a href="https://github.com/chentsulin">C. T. Lin</a></small>
</p>
</section>
<section data-transition="slide" data-background="#4d7e65">
<section>
<p style="font-size: 2em">MVC 有什麼問題?</p>
</section>
<section>
<p>幾年前開始的 Client Side MVC 大戰</p>
<img src="img/mvc-vs.png" style="background-color: #fff"/>
</section>
<section>
<p style="font-size: 1.8em">UI move fast</p>
<p style="font-size: 1.8em">MVC doesn't scale</p>
</section>
<section>
<p>複雜度超過想像</p>
<img src="img/mvc.png" />
</section>
<section>
<p style="text-align: left; color: #ee5"><a href="https://facebook.github.io/react/blog/2015/10/07/react-v0.14.html#upgrade-guide" target="_blank">the Facebook codebase has over 15,000 React components</a>
<p style="text-align: right; color: #ee5""> - 2015/10/07</p>
</section>
<section>
<p>詳細的可以參考這個影片:<br /><a href="https://www.youtube.com/watch?v=nYkdrAPrdcw" target="_blank">Rethinking Web App Development at Facebook</a></p>
</section>
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p style="text-align: left; color: #ee5">Managing complexity is the most important technical topic in software development. In my view, it’s so important that Software’s Primary Technical Imperative has to be managing complexity.</p>
<p style="text-align: left">軟體首要技術使命是管理複雜度。</p>
<p style="text-align: left"><span style="color: #ee5">– Steve McConnell in Code Complete</span> <a href="http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read" target="_blank">(most-influential-book-every-programmer-should-read)</a></p>
</section>
<section>
<p>處理前端複雜架構的訣竅在於</p>
<p style="font-size: 3em">提高可預測性</p>
<p>這就是 React 的目標</p>
</section>
<section>
<img src="img/react-flux.png" />
</section>
</section>
<section data-transition="slide" data-background="#4d7e65">
<section>
<p style="font-size: 3em">Flux</p>
</section>
<section>
<p>Unidirectional data flow</p>
<img src="img/flux.png" />
</section>
<section>
<img src="img/flux-explained.png" />
</section>
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p style="font-size: 2em">Flux 運作方式</p>
</section>
<section>
<img src="img/flux-concept.png" />
</section>
<section>
<p style="font-size: 1.8em">Classical Flux 的缺點</p>
<br />
<ul>
<li>State Mutation</li>
<li>Impure Reducer</li>
<li>Singleton Issue</li>
<li>Boilerplate</li>
</ul>
</section>
</section>
<section data-transition="slide" data-background="#4d7e65">
<p style="font-size: 3em">Redux</p>
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p>2015/5/30 First commit</p>
<p>原本只是用來準備一個 React EU Conf 的 講題<br /><a href="https://www.youtube.com/watch?v=xsSnOQynTHs" target="_blank">Live React: Hot Reloading with Time Travel</a></p>
</section>
<section>
<p>意外做出最受歡迎的 Flux 架構</p>
<p>所以作者稱為 CDD (Conference Driven Development)</p>
</section>
</section>
<section data-transition="slide" data-background="#4d7e65">
<p style="font-size: 2em">Redux 三大原則</p>
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p style="font-size: 1.5em">唯一真相來源 <br />(Single source of truth)</p>
</section>
<section>
<p style="font-size: 1.5em">State 是唯讀的 <br /(State is read-only)</p>
</section>
<section>
<p style="font-size: 1.5em">變更被寫成 pure functions <br />(Changes are made with pure functions)</p>
</section>
<section>
<p>詳細可參考<a href="http://chentsulin.github.io/redux/docs/introduction/ThreePrinciples.html" target="_blank">這裡</a></p>
</section>
</section>
<section data-transition="slide" data-background="#4d7e65">
<img src="img/redux-2.png" style="background-color: #fff" />
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p style="font-size: 1.5em; color: #B2E1EA">Action</p>
<p>只是個普通的 JS Object</p>
<p>一定要有一個 type</p>
<pre><code class="lang-js">{
type: SEND_MESSAGE,
payload: {
text: 'Hello world'
}
}</code></pre>
<p>把資料傳給 Store 的唯一手段</p>
<p>表達修改 State 的意圖</p>
</section>
<section>
<p style="font-size: 1.5em; color: #B2E1EA">Flux Standard Action</p>
<p><a href="https://github.com/acdlite/flux-standard-action" target="_blank">Flux Standard Action</a> 有一個普遍的 action 定義</p>
<p>包括 meta, error 等欄位</p>
</section>
<section>
<p>type 可以宣告為常數</p>
<p>放在 ActionCreator 或 額外的 actionTypes 檔案</p>
<pre><code class="lang-js">export const ADD_TODO = 'ADD_TODO';
export const COMPLETE_TODO = 'COMPLETE_TODO';
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';</code></pre>
</section>
<section>
<p>詳細可參考<a href="http://chentsulin.github.io/redux/docs/basics/Actions.html" target="_blank">這裡</a></p>
</section>
</section>
<section data-transition="slide" data-background="#4d7e65">
<section>
<p style="font-size: 1.5em; color: #B2E1EA">Action Creators</p>
<p>通常寫在 XxxxActions 或 XxxxActionCreators 命名的檔案中</p>
<p>小心盡量不要跟 Action 搞混</p>
</section>
<section>
<p>一個傳統 Flux 的 Action Creator</p>
<p>會製造 Action 並 dispatch</p>
<pre><code class="lang-js">function sendMessage(text) {
const action = {
type: SEND_MESSAGE,
payload: {
text
}
};
dispatch(action); // 注意這裡,這裡就不是 Pure 的
}</code></pre>
</section>
<section>
<p>Redux 中一個普通的 Action Creator</p>
<p>就是製造 Action 的 Pure Function</p>
<pre><code class="lang-js">function sendMessage(text) {
return {
type: SEND_MESSAGE,
payload: {
text
}
};
}</code></pre>
</section>
<section>
<p>這樣的 Pure Function 很好測試</p>
<pre><code class="lang-js">expect(sendMessage('Hello')).to.deep.equal({
type: SEND_MESSAGE,
payload: {
text: 'Hello'
}
});</code></pre>
</section>
<section>
<p>實際 dispatch Action</p>
<pre><code class="lang-js">// 先不管 dispatch 從哪來
dispatch(sendMessage('Hello'));</code></pre>
</section>
<section>
<p>使用 Middleware </p><p>可以 dispatch 除了一般 action 以外的東西</p>
<p><a href="https://github.com/gaearon/redux-thunk" target="_blank">Thunk Middleware (redux-thunk)</a></p>
<p><a href="https://github.com/acdlite/redux-promise" target="_blank">Promise Middleware (redux-promise)</a></p>
<p><a href="https://github.com/yelouafi/redux-saga" target="_blank">Saga Middleware (redux-promise)</a></p>
<p>這邊先不做敘述</p>
</section>
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p style="font-size: 1.5em; color: #B2E1EA">Reducer</p>
<p>給 Store 初始的 State</p>
<p>並根據收到的 Action 回傳新的 State</p>
<p>就像是傳統 Flux 的 Store 的一部分工作</p>
</section>
<section>
<p><code>(previousState, action) => newState</code></p>
</section>
<section>
<pre><code class="lang-js">// 原理類似這樣
const newState = reducer(previousState, action);</code></pre>
</section>
<section>
<p>每次收到 dispatch 的 Action 就會觸發</p>
<p>根據原本的 previousState 和 Action,回傳新的 newState</p>
<p>這樣的 Functional 的做法</p>
<p>可以更簡潔的表達如何變更 State</p>
</section>
<section>
<p>這是個沒有 Side Effect 的 Function</p>
<p>不要去改 previousState</p>
<p>會使 Time Travel 等需要前面 State 的功能壞掉</p>
<pre><code class="lang-js">const initialState = { message: '' };
function messageReducer(state = initialState, action) {
switch (action.type) {
case SEND_MESSAGE:
return {
message: action.payload.text
};
default:
return state; // 沒有做任何事也要回傳原本的
}
}</code></pre>
</section>
<section>
<p>這樣的 Pure Function 很好測試</p>
<pre><code class="lang-js">// Reducer 了解的 Action
expect(messageReducer(null, {
type: SEND_MESSAGE,
payload: {
text: 'Hello'
}
})).to.deep.equal({ message: 'Hello' });
// Reducer 不了解的 Action
expect(messageReducer({ message: 'Hello' }, {
type: UNKNOWN,
payload: {
text: 'Hello'
}
})).to.deep.equal({ message: 'Hello' });</code></pre>
</section>
<section>
<p>在一開始的時候 Redux 會 dispatch</p>
<p><span style="color: #ee5"><code>@@redux/INIT</code></span> Action 來初始化 State</p>
</section>
<section>
<p style="color: #ee5"><code>@@namespace/EVENT_NAME</code></p>
<p>是目前 Private Event 的命名規範</p>
<p>不要試圖去聽這些 Event</p>
</section>
<section>
<p>詳細可參考<a href="http://chentsulin.github.io/redux/docs/basics/Reducers.html" target="_blank">這裡</a></p>
</section>
</section>
<section data-transition="slide" data-background="#4d7e65">
<section>
<p style="font-size: 1.5em; color: #B2E1EA">Store</p>
<p>應用程式保存 State 的地方,Redux 只有一個</p>
</section>
<section>
<p>建立 Store 的方式是把 reducer 傳進去 <code style="color: #ee5">createStore</code></p>
<pre><code class="lang-js">import { createStore } from 'redux';
import messageReducer from '../reducers/messages';
const store = createStore(messageReducer);
</code></pre>
</section>
<section>
<p>實際會有很多不同資料的 reducer</p>
<p>所以需要用 <code style="color: #ee5">combineReducers</code> 來結合他們</p>
<pre><code class="lang-js">// reducers/index.js
import { combineReducers } from 'redux';
import todos from './todos';
import counter from './counter';
export default combineReducers({
todos,
counter
});
// App.js
import { createStore } from 'redux';
import reducer from './reducers/index';
const store = createStore(reducer);
</code></pre>
</section>
<section>
<pre><code class="lang-js">// 第二個參數可用來當作初始的 state
const store = createStore(todoApp, window.STATE_FROM_SERVER);
</code></pre>
</section>
<section>
<p style="font-size: 1.5em; color: #B2E1EA">dispatch</p>
<p>dispatch 是 Store 比較 Low-level 的 API</p>
<p>不過還是值得一提</p>
<p>雖然通常並不會直接這樣寫</p>
<pre><code class="lang-js">store.dispatch(sendMessage('Hello'));
</code></pre>
</section>
<section>
<p style="font-size: 1.5em; color: #B2E1EA">getState</p>
<p>可以取得 store 現在的 state</p>
<pre><code class="lang-js">store.getState();
</code></pre>
</section>
<section>
<p style="font-size: 1.5em; color: #B2E1EA">subscribe</p>
<p>可以監聽 store state 的改變</p>
<pre><code class="lang-js">// 每次 state 變更,就印出它
const unsubscribe = store.subscribe(() =>
console.log(store.getState())
)
</code></pre>
</section>
<section>
<p>詳細可參考<a href="http://chentsulin.github.io/redux/docs/basics/Store.html" target="_blank">這裡</a></p>
</section>
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p style="font-size: 1.5em; color: #B2E1EA">Middleware</p>
<p>用來延伸 dispatch 的功能</p>
</section>
<section>
<p>使用 <code style="color: #ee5">applyMiddleware</code> util</p>
<pre><code class="lang-js">import { createStore, applyMiddleware } from 'redux';
const store = createStore(
reducer,
applyMiddleware(promise, thunk, observable)
);
// applyMiddleware 可以 decorate createStore
</code></pre>
</section>
<section>
<p><code>dispatch => dispatch'</code></p>
</section>
<section>
<p><a href="https://github.com/gaearon/redux-thunk" target="_blank">redux-thunk</a> 這個 Middleware</p>
<p>讓 Store 可以 dispatch Thunk</p>
<pre><code class="lang-js">function sendMessageAsync(message) {
return dispatch => {
setTimeout(() => {
dispatch(sendMessage(message));
}, 1000);
};
}
</code></pre>
</section>
<section>
<p><a href="https://github.com/acdlite/redux-promise" target="_blank">redux-promise</a> 這個 middleware</p>
<p>讓 Store 可以 dispatch Promise</p>
<pre><code class="lang-js">function sendMessageAsync(message) {
return dispatch => {
dispatch(new Promise((resolve, reject)) => {
setTimeout(() => {
resolve(sendMessage(message))
}, 1000);
});
};
}
</code></pre>
</section>
<section>
<p>非同步的地方讓 ActionCreator 去做</p>
<p>Reducer 是完全同步的</p>
</section>
</section>
<section data-transition="slide" data-background="#4d7e65">
<section>
<p style="font-size: 1.5em; color: #B2E1EA">View</p>
<p>Redux 本身並不依賴特定 View Layer</p>
<p>所以可以跟任何 View Layer 去結合</p>
</section>
<section>
<p><a href="https://github.com/gaearon/react-redux" target="_blank">react-redux</a> 就是 react 跟 redux 的介接</p>
</section>
<section>
<p>提供 Provider 和 connect 兩個東西</p>
</section>
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p style="font-size: 2em">Provider</p>
</section>
<section>
<p>Provider 用來在 RootComponent 外再包一層</p>
<p>並把 Store 用 React Context 傳下去</p>
<pre><code class="lang-js">// 包在 Provider 才能 connect Store
<Provider store={store}>
<MyRootComponent>
</Provider>
</code></pre>
</section>
</section>
<section data-transition="slide" data-background="#4d7e65">
<section>
<p style="font-size: 2em">connect</p>
</section>
<section>
<p>把特定的 State 從 Context 裡的 Store Select 出來</p>
<p>並把它們當 props 傳下去</p>
<pre><code class="lang-js">class MyComponent extends React.Component {
render() {
const { dispatch, user } = this.props;
// connect 沒給第二個參數時 dispatch 會預設當 props 傳下來
// ..
}
}
export default connect(state => ({
user: state.user
}))(MyComponent);
</code></pre>
</section>
<section>
<p>直接包裝 import 進來的 Component</p>
<pre><code class="lang-js">import PresentationalComponent from '../components/PresentationalComponent';
// 從 State 抽取要傳下去的 Props
function mapStateToProps(state) {
return {
user: state.user
};
}
export default connect(mapStateToProps)(PresentationalComponent);
</code></pre>
</section>
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p style="font-size: 1.5em">傳遞 ActionCreator 下去</p>
</section>
<section>
<pre><code class="lang-js">function mapStateToProps(state) {
return { user: state.user };
}
// 把 dispatch 變成 Handler 當成 Props 傳下去
function mapDispatchToProps(dispatch) {
return {
sendMessage: (msg) => { dispatch(sendMessage(msg)) }
};
}
class MyComponent extends React.Component {
render() {
const { user, sendMessage } = this.props;
// sendMessage 也會當 props 傳下來
// ..
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
</code></pre>
</section>
</section>
<section data-transition="slide" data-background="#4d7e65">
<section>
<p style="font-size: 1.5em; color: #B2E1EA">bindActionCreators</p>
<p>Redux 還有這個可以方便使用 ActionCreator 的 util</p>
</section>
<section>
<pre><code class="lang-js">import { bindActionCreators } from 'redux';
import MessageActions from '../actions/MessageActions';
function mapStateToProps(state) {
return { user: state.user };
}
// 把 dispatch 變成 Handler 當成 Props 傳下去
function mapDispatchToProps(dispatch) {
return bindActionCreators(MessageActions, dispatch);
} // 把整個 ActionCreator 的 Handler 傳下去
class MyComponent extends React.Component {
render() {
const { user, sendMessage, deleteMessage } = this.props;
// 把整個 ActionCreator 的 Handler 都當 props 傳下來
// ..
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
</code></pre>
</section>
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p style="font-size: 1.5em">connect 其實不只這樣...</p>
</section>
<section>
<p>connect 有三個可選參數</p>
<p>mapStateToProps, mapDispatchToProps, mergeProps</p>
<ul>
<li><span style="color: #ee5">mapStateToProps:</span> 跟之前一樣,把 Store State 的特定部分當成 Props</li>
<li><span style="color: #ee5">mapDispatchToProps:</span> 把 dispatch 傳進去也變成 Props,通常用來把綁定的 actionCreators 傳下去</li>
<li><span style="color: #ee5">mergeProps:</span> 可以指定 stateProps, dispatchProps, parentProps 的合併方式</li>
</ul>
</section>
<section>
<p>預設是這樣:</p>
<pre><code class="lang-js">const defaultMergeProps = (stateProps, dispatchProps, parentProps) => ({
...parentProps,
...stateProps,
...dispatchProps
});
</code></pre>
</section>
<section>
<p>最後可以改變傳下去的 Props 的機會</p>
<pre><code class="lang-js">function mergeProps(stateProps, dispatchProps, parentProps) {
return {
...stateProps, // 這樣就可以讓 parentProps 蓋掉其他兩個
...dispatchProps,
...parentProps
}
}
export default connect(
mapStateToProps,
mapDispatchToProps,
mergeProps
)(MyDumbComponent)
</code></pre>
</section>
</section>
<section data-transition="slide" data-background="#4d7e65">
<section>
<p style="font-size: 1.5em">Redux 優點</p>
<ol>
<li>所有東西都 Hot Reloadable</li>
<li>容易做 Universal,沒用到 Singleton 而且資料可以 rehydrated</li>
<li>可以用任何形式保存資料:JS Objects, Arrays, ImmutableJS..</li>
<li>簡化至一個 Store</li>
<li>提供 redux-devtools Time travel 功能</li>
<li>可以用 Middleware 擴充 dispatch</li>
<li>不用 Mock 就很容易測試</li>
</ol>
</section>
<section>
<p>而且他的 API 很少,核心只有 createStore 的 150 行程式碼</p>
<img src="img/source.png" />
</section>
<section>
<p>容易學、好擴充</p>
</section>
</section>
<section data-transition="slide" data-background="#b5533c">
<section>
<p style="font-size: 1.5em">開發工具</p>
</section>
<section>
<ul>
<li>redux-devtools</li>
<li>redux-logger</li>
</ul>
</section>
</section>
<section data-transition="slide" data-background="#4d7e65" style="text-align: left;">
<h1>THE END</h1>
<p>Thanks for listening</p>
</section>
</div>
</div>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.js"></script>
<script>
// Full list of configuration options available at:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
slideNumber: true,
transition: 'slide', // none/fade/slide/convex/concave/zoom
// Optional reveal.js plugins
dependencies: [
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'node_modules/prismjs/prism.js'},
{ src: 'node_modules/prismjs/components/prism-bash.min.js'},
{ src: 'node_modules/prismjs/plugins/autolinker/prism-autolinker.min.js'},
{ src: 'node_modules/prismjs/components/prism-javascript.min.js', async: true, callback: function() {
Prism.highlightAll();
}
},
{ src: 'node_modules/prismjs/components/prism-bash.min.js', async: true, callback: function() {
Prism.highlightAll();
}
},
{ src: 'node_modules/prismjs/components/prism-ruby.min.js', async: true, callback: function() {
Prism.highlightAll();
}
},
// { src: 'plugin/highlight/highlight.js', async: true, condition: function() { return !!document.querySelector( 'pre code' ); }, callback: function() {
// hljs.initHighlightingOnLoad(); }
// },
{ src: 'plugin/zoom-js/zoom.js', async: true },
{ src: 'plugin/notes/notes.js', async: true }
]
});
</script>
</body>
</html>