ã³ãŒããå®çšŒåã«å
¥ããšãããã°ã©ãã¯äŸ¿å©ãªæ©èœãšãšãã«ãšã©ãŒãå€éšã«ãªãªãŒã¹ããŸãã ããšãã°ãç¹å®ã®ãµã€ãã§ãå°ããªé害ãçºçããå¯èœæ§ããããŸããããã¯ãããŸããŸãªçç±ã«èµ·å ãããã®ã§ããããã®åå ã«ã¯ãªããŸããã èªåã®ä»äºãç¥ã£ãŠããéçºè
ã«ãšã£ãŠãèªåã®éã¡ã«å¯ŸåŠããèããªããã°ãªããªãåéºã«ã€ããŠã®åœŒãã®è©±ãèããŠãçµæãšããŠããããä¿®æ£ã§ããã¡ã«ããºã ãæäŸããããšã¯çŽ æŽãããããšã§ãã

仿¥ãããã°ã©ããŒã®ããããã»ã®ã«ããŒããœã³ã«ããèšäºã®ç¿»èš³ãå
±æããããšæããŸãã圌ã¯ãReactã§æžãããWebãããžã§ã¯ãã®ãšã©ãŒã远跡ããŠåçŸã§ããå®éšã·ã¹ãã ã«ã€ããŠè©±ããŠããŸãã ãã®ã¢ãããŒãã¯ä»ã®ç°å¢ã«ç§»ãããšãã§ãããšä¿¡ããŠããŸããããã¹ãŠãé 調ã§ãã
ãšã©ãŒå ±åã®ã¢ãããŒã
ãããããWebãããžã§ã¯ãã®ãšã©ãŒã«é¢ããæ
å ±ãåéããããã«ããã®ãããªã·ã³ãã«ãªã·ã¹ãã ã䜿çšããŠããã®ã§ãããïŒæ¬¡ã®äŸã§ã¯ãç§ã«ç³ãæããªãã§ãã ããïŒïŒ
window.onerror = err => fetch(`/errors/${err}`);
ãšã©ãŒã¬ããŒãã確èªããã«ã¯ããã¬ã³ããªãŒãªITå°éå®¶ã«äŸé ŒããŠã
/errors
ã§å§ãŸã404ããŒãžã«é¢ãããã¹ãŠã®èšé²ãå«ããã¡ã€ã«ãæäŸããã ãã§ååã§ãã
ãã ãããã®ã¢ãããŒãã§åŸããããã³ãŒããã¯ããšã©ãŒãçºçããæ£ç¢ºãªå ŽæãèŠã€ããã®ã«åœ¹ç«ã¡ãŸããã ãããããããã§äœããæ¹åãããã¡ã€ã«ãšè¡çªå·ã«é¢ããæ
å ±ãå«ããšã©ãŒã¡ãã»ãŒãžãçæããå¿
èŠããããŸãã
window.addEventListener('error', e => { fetch('/errors', { method: 'POST', body: `${e.message} (in ${e.filename} ${e.lineno}:${e.colno})`, }); });
ãã®ã³ãŒãã¯è¯èã®ã©ããã§ãã©ã³ã¹ãåã£ãŠããŸããããããŸã§ã®ãšãããããã¯ãã£ãšæ·±å»ãªäœãã®éªšæ Œã«ãããŸããã ãšã©ãŒãç¹å®ã®ããŒã¿ã«é¢é£ããŠããå Žåãè¡çªå·ã«é¢ããæ
å ±ã¯ç¹ã«æçã§ã¯ãããŸããã
ãšã©ãŒãçºçããæç¹ã§ãŠãŒã¶ãŒã®ã¢ã¯ãã£ããã£ã«é¢ããå®å
šãªã¬ããŒããããã°äŸ¿å©ã§ããããã«ãããé害ãçºçããç¶æ³ãåçŸã§ããŸãã ããšãã°ã次ã®ãããªãã®ïŒ
ãŠãŒã¶ãŒã¢ã¯ãã£ããã£ã¬ããŒãæãè峿·±ãã®ã¯ããŠãŒã¶ãŒã補åã«é¢ãã詳现æ
å ±ã®ããŒãžã«ç§»åãïŒã¹ããã4ïŒã賌å
¥ãã¿ã³ïŒæåŸã®5çªç®ã®ã¹ãããïŒãã¯ãªãã¯ããããšã§ãã
ç¹å®ã®è£œåã®ããŒã¿ã«äœãçãããããšãèµ·ãã£ãŠãããšããã«æšæž¬ã§ãããããåããªã³ã¯ã«ã¢ã¯ã»ã¹ããŠããããã$ã§è³Œå
¥ããšãã賌å
¥ãã¿ã³ãã¯ãªãã¯ããŸãã
ãã¡ããããããè¡ã£ãåŸãç§ã¯åãééããèŠãŸãã ãã®ç¹å®ã®ã¢ã€ãã ã«ã¯äŸ¡æ Œããªãããã
toLocaleString
ãåŒã³åºããšå€±æããŸãã ç§ãã¡ã®åã«ãããŸãçµéšã®ãªãéçºè
ã®å
žåçãªç£ç£ããããŸãã
ãããããŠãŒã¶ãŒã®ãµã€ããšã®ããåããã¯ããã«è€éãªå Žåã¯ã©ãã§ããããïŒ ãŠãŒã¶ãŒãäœæ¥ãURLã«åæ ããŠããªãå€ãã®ã¿ãã®1ã€ã§ãããããã©ãŒã ã®ããŒã¿ããã§ãã¯ããŠãããšãã«ãšã©ãŒãçºçããå¯èœæ§ããããŸãã ãªã³ã¯ããã©ã£ãŠãã¿ã³ãã¯ãªãã¯ããŠãããã®ãããªãšã©ãŒã¯æããã«ãªããŸããã
ãã®ç¶æ³ã§ã¯ããšã©ãŒãçºçãããŸã§ãã¹ãŠã®ãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãåçŸã§ããããã«ããããšèããŠããŸãã çæ³çã«ã¯ãåçäžã«ã次ã®ã¹ãããããšãããã¿ã³ãã¯ãªãã¯ããã ãã§ãã
æ³ååã倱ã£ãŠããªããªãããããèªåèªèº«ã«æ³åããŠã¿ãŠãã ããã
DOMã芳å¯ããŠãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãåçŸããç»é¢ã«è¡šç€ºããããšã©ãŒæ
å ±ãšãšãã£ã¿ãŒã§éããã¡ã€ã«ã¯ãReactã¢ããªã®äœæã®ã¡ãªããã§ãã
å®éšã®åœ¢ã§ããã¢ãã¬ãŒããããŠããªããŠãŒã¶ããªãã£ãã¹ããã®ãããªãã®ãå®è¡ã§ããã·ã¹ãã ãå®éã«æ§ç¯ããããšã«æ³šæããŠãã ããã ãŠãŒã¶ãŒã®ã¢ã¯ã·ã§ã³ã远跡ããŠåçããã³ãŒããäœæããç¥èã®ãã1人ã®ãžã§ã³ã«ã圌ããã®ãã¹ãŠã«ã€ããŠã©ãæãããå°ããŸããã 圌ã¯ããã¯éŠ¬é¹¿ããã¢ã€ãã¢ã ãšèšã£ãããç§ã®ã³ãŒãã¯ãšã©ãŒãåçŸããã®ã«åœ¹ç«ã€ã ãããšä»ãå ããã
å®éãããã§ããã«ã€ããŠã話ããããšæããŸãã ããããšãããžã§ã³ã
ã·ã¹ãã ã³ã¢
åé¡ã®ã³ãŒãã¯
ããã«ãããŸã ã ããªãã¯ç§ã®è©±ããããããèªãããšã«èå³ããããããããŸããã 以äžã«é¢æ°ã®ç°¡æããŒãžã§ã³ã瀺ããå
šæãžã®ãªã³ã¯ãæäŸããŸãã
ããŸããŸãªãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãã€ã³ã¿ãŒã»ããããããã€ãã®é¢æ°ãå«ãã¢ãžã¥ãŒã«
record.jsããããŸãã ããã¯ãã¹ãŠ
journey
ãªããžã§ã¯ãã«åé¡ããããšã©ãŒãçºçãããšãã«ãµãŒããŒã«è»¢éã§ããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®å
¥åãã€ã³ãã§ã次ã®ãããª
startRecording()
颿°ãåŒã³åºããŠæ
å ±ã®åéãéå§ããŸãã
const journey = { meta: {}, steps: [], }; export const startRecording = () => { journey.meta.startTime = Date.now(); journey.meta.startUrl = document.location.href; journey.meta.screenWidth = window.innerWidth; journey.meta.screenHeight = window.innerHeight; journey.meta.userAgent = navigator.userAgent; };
ãšã©ãŒãçºçããå Žåã
journey
ãªããžã§ã¯ãã¯ãããšãã°ãåæã®ããã«ãµãŒããŒã«éä¿¡ã§ããŸãã ãããè¡ãã«ã¯ã察å¿ããã€ãã³ããã³ãã©ãŒãæ¥ç¶ãããŸãã
window.addEventListener('error', sendErrorReport);
sendErrorReport
颿°
sendErrorReport
ã
journey
ãªããžã§ã¯ããšåãã¢ãžã¥ãŒã«ã§å®£èšãããŸãã
export const sendErrorReport = (err) => { journey.meta.endTime = Date.now(); journey.meta.error = `${err.message} (in ${err.filename} ${err.lineno}:${err.colno})`; fetch('/error', { method: 'POST', body: JSON.stringify(journey) }) .catch(console.error); };
ãšããã§ã誰ãã
JSON.stringify(err)
ã³ãã³ãããšã©ãŒã®æ¬æãæäŸããªãçç±ã説æã§ããã°ãéåžžã«ã¯ãŒã«ã«ãªããŸãã
ãããŸã§ã®ãšãããããããã¹ãŠã«ç¹å¥ãªå©ç¹ã¯ãããŸããã ããããä»ã§ã¯ä»ã®ãã¹ãŠãæ§ç¯ããããã®ãã¬ãŒã ã¯ãŒã¯ããããŸãã
ã¢ããªã±ãŒã·ã§ã³ãç¶æ
ããŒã¹ã®å ŽåïŒã€ãŸããDOMãããã€ãã®äž»èŠãªç¶æ
ã«åºã¥ããŠã®ã¿è¡šç€ºãããå ŽåïŒãããç°¡åã«çããããšãã§ããŸãïŒãšã©ãŒãçºçããå¯èœæ§ãäœããªããšæ³å®ããŠãªã¹ã¯ããããŸãïŒã ãšã©ãŒãåçŸããããšãããšãåçŽã«ç¶æ
ãåäœæã§ããŸããããã«ããããã®ãšã©ãŒãçºçããå¯èœæ§ãé«ããªããŸãã
ã¢ããªã±ãŒã·ã§ã³ãææ°ã®ãã¯ãããžãŒã«åºã¥ããŠããªãå Žåããã€ã³ãã£ã³ã°ã䜿çšãããŠãŒã¶ãŒãããŒãžãšå¯Ÿè©±ããæ¹æ³ã«çŽæ¥åºã¥ããŠäœãã衚瀺ãããšãåé¡ã¯ããå°ãè€éã«ãªããŸãã ãšã©ãŒãåçŸããã«ã¯ãããŠã¹ã¯ãªãã¯ãèŠçŽ ã®æå€±ãšãã©ãŒã«ã¹ã«é¢é£ããã€ãã³ããããã³ããŒããŒãããŒãæŒãããšãåçŸããå¿
èŠããããŸãã 確ãã«ããŠãŒã¶ãŒãã¯ãªããããŒããããã£ãŒã«ãã«äœãã貌ãä»ããå Žåã®å¯ŸåŠæ¹æ³ãèšãã®ã¯é£ãããšæããŸãã ããã§ç§ã¯å®éšã§å¹žéãé¡ãããšãã§ããŸãã
ç§ã¯èªãããã§ã-ç§ã¯æ ãè
ã§å©å·±çãªäººã§ãã®ã§ãç§ã話ãããšã¯ç§ãæ±ãæè¡ãããªãã¡ReactãšReduxã§æ§ç¯ããããããžã§ã¯ãã«çŠç¹ãåœãŠãŸãã
ããããŸãã«ç§ãååããããã®ã§ãïŒ
- ãã¹ãŠã®ã¹ã±ãžã¥ãŒã«ãããã¢ã¯ã·ã§ã³ïŒçµæãšããŠãç¶æ
ã¹ãã¢ãžã®å€æŽã®ãåçããæå¹ã«ããããšãå¯èœã«ãªããŸãïŒã
- URLã®å€æŽïŒã€ãŸããURLãæŽæ°ã§ããããã«ãªããŸãïŒã
- ããŒãžãã¯ãªãã¯ãããšïŒãŠãŒã¶ãŒãã¯ãªãã¯ãããã¿ã³ããªã³ã¯ãèªåã®ç®ã§ç¢ºèªã§ããããã«ãªããŸãïŒã
- ã¹ã¯ããŒã«ïŒããã«ããããšã©ãŒçºçæã«ãŠãŒã¶ãŒãããŒãžã§èŠããã®ãæ£ç¢ºã«ç¥ãããšãã§ããŸãïŒã
Reduxã¢ã¯ã·ã§ã³ã€ã³ã¿ãŒã»ãã
以äžã¯ã
journey
ãªããžã§ã¯ãã®Reduxã¢ã¯ã·ã§ã³ãã€ã³ã¿ãŒã»ããããŠä¿åããããã«äœ¿çšãããã³ãŒãã§ãã
export const captureActionMiddleware = () => next => action => { journey.steps.push({ time: Date.now(), type: INTERACTION_TYPES.REDUX_ACTION, data: action, }); return next(action); };
æåã«ãæ§é
= () => next => action => {
ãèŠãããšãã§ããŸããããã¯ãäžèŠçè§£ã§ããªãããšã¯ãŸã£ããäžå¯èœã§ãã ããã§ãçè§£ã§ããªãå Žåã¯ãèªã
ã§ãã ãã ã 確ãã«ããããæãäžããã®ã§ã¯ãªãããã£ãšéèŠãªããšãããã»ããããã§ããããããšãã°ã幞ããªç¬é¡ãæãç·Žç¿ãããŸããããã¯ãèªçæ¥ãç¥çŠãããšãã«åœ¹ç«ã¡ãŸãã
ãã®ã³ãŒãã§çè§£ããæãéèŠãªããšã¯ããããžã§ã¯ãã§æãã圹å²ã§ãã ã€ãŸãã圌ã¯Reduxã®ãã¢ã¯ã·ã§ã³ããå®è¡äžã«
journey
ãªããžã§ã¯ãã«é
眮ããã®ã«å¿ããããŠããŸãã
次ã«ãReduxãªããžããªãäœæãããšãã«äžèšã®é¢æ°ãé©çšãããªã³ã¯ããã®
applyMiddleware()
ãã¬ãŒã ã¯ãŒã¯ã®é¢æ°ã«æž¡ããŸãã
const store = createStore( reducers, applyMiddleware(captureActionMiddleware), ); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
URLã®å€æŽãèšé²ãã
URL倿Žãã£ããã£ãå®è¡ãããå Žæã¯ãã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒãã£ã³ã°æ¹æ³ã«ãã£ãŠç°ãªããŸãã
Reactã«ãŒã¿ãŒã¯URLã®å€æŽãæ€åºããã®ã«ããŸã圹ã«ç«ããªãã®ã§ã
ãã®ã¢ãããŒãããŸãã¯å€å
ããã«é Œããªããã°ãªããŸããã Reactã«ãŒã¿ãŒã䜿çšããŠã
onRouteChange
ãã³ãã©ãŒãèšå®ãããã ã
onRouteChange
ã ãããç§ã ãã§ãªãå¿
èŠã§ããããšã¯æ³šç®ã«å€ããŸãã ããšãã°ãå€ãã¯ãä»®æ³ããŒãžãã¥ãŒæ
å ±ãGoogleã¢ããªãã£ã¯ã¹ã«éä¿¡ããå¿
èŠã«çŽé¢ããŠããŸãã
ããã¯ãšããããç§ã¯ã»ãšãã©ã®ãµã€ãã®ããã«ç§èªèº«ã®ã«ãŒãã£ã³ã°ã·ã¹ãã ãæžãããšã奜ããããã¯çŽ17åãããããããæçµçã«ãèµ·ããããšã¯
éåžžã«é«éã§ããããšã倿ããããã ã
URLã®å€æŽãååããããã«ãURLã倿Žããããã³ã«åŒã³åºãããæ¬¡ã®é¢æ°ãæºåããŸããã
export const captureCurrentUrl = () => { journey.steps.push({ time: Date.now(), type: INTERACTION_TYPES.URL_CHANGE, data: document.location.href, }); };
ç§ã¯åœŒå¥³ã2ãæã§åŒã³ãŸã
history.push()
ã³ãã³ããå®è¡ããŠURLãæŽæ°ããã®ãšåãå Žæã§ããŸããŠãŒã¶ãŒããã©ãŠã¶ã®[
]ãã¿ã³ãã¯ãªãã¯ãããšåŒã³åºããã
popstate
ã€ãã³ãã§ãïŒ
window.addEventListener('popstate', () => { // - , captureCurrentUrl(); });
ãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ã®èšé²
ãããããããã¯æåéãã©ãã«ã§ãåã蟌ãå¿
èŠãããããããµã€ãã§ã®äœæ¥ã«é¢ããæ
å ±ãååããããã®æãã䟵å
¥çãªãã¡ã«ããºã ã§ãã ãããç§ã®æ¬²æã ãã«äŸåããŠããã°ãç§ã¯ãããæ°ã«ããŸããã ããããç§ãæã£ãããã«ããŠãŒã¶ãŒãã©ããã¯ãªãã¯ããããæ£ç¢ºã«ç¥ããªããã°åçŸã§ããªããšã©ãŒã«ééããŸããã
ãããã«ãããã¿ã¹ã¯ã¯é¢çœãã£ãã®ã§ãããã§ãã®è§£æ±ºçã«ã€ããŠèª¬æããŸãã Reactã§éçºãããšããç§ã¯åžžã«
<Link>
ããã³
<Button>
ã³ã³ããŒãã³ãã䜿çšããŸã;ãã®çµæãéäžã¯ãªãã¯ä»£è¡åä¿¡ã·ã¹ãã ã®éçºã¯éåžžã«ç°¡åã§ãã
<Link>
èŠãŠãã ããïŒ
const Link = props => ( <a href={props.to} data-interaction-id={props.interactionId} // onClick={(e) => { e.preventDefault(); captureInteraction(e); // historyManager.push(props.to); }} > {props.children} </a> );
ããã§è©±ããŠããã®ã¯ã
data-interaction-id={props.interactionId}
ããã³
captureInteraction(e);
ã
ã»ãã·ã§ã³ãåçŸãããšããæ¥ããããŠãŒã¶ãŒãã¯ãªãã¯ãããã®ã匷調ããããšæããŸãã ãããè¡ãã«ã¯ãäœããã®ã»ã¬ã¯ã¿ãŒãå¿
èŠã§ãã ã¯ãªãã¯ããèŠçŽ ã«ã¯èå¥åïŒ
id
ïŒããããšèªä¿¡ãæã£ãŠè¿°ã¹ãããšãã§ããŸãããäœããã®çç±ã§èŠããŠããªãã®ã§ãç£èŠã·ã¹ãã çšã«ç¹å¥ã«èšèšããããã®ã®æ¹ãè¯ããšå€æããŸãããŠãŒã¶ãŒã¢ã¯ãã£ããã£çšã
captureInteraction()
颿°ã¯æ¬¡ã®ãšããã§ãã
export const captureInteraction = (e) => { journey.steps.push({ time: Date.now(), type: INTERACTION_TYPES.ELEMENT_INTERACTION, data: { interactionId: e.target.dataset.interactionId, textContent: e.target.textContent, }, }); };
ããã§å®å
šãªã³ãŒããèŠã€ããããšãã§ããŸãããã®ã³ãŒãã§ã¯ãã»ãã·ã§ã³ãåçããåŸãèŠçŽ ãåã³èŠã€ããããã«ãã§ãã¯ãããŸãã
ä»ã®æ
å ±ãšåæ§ã«ãå¿
èŠãªãã®ãåéããŠã
journey.steps.push
ã³ãã³ããå®è¡ããŸãã
ã¹ã¯ããŒã«
ç§ãæ®ããŠããã®ã¯ããŠãŒã¶ãŒã衚瀺ããŠããããŒãžã®ã©ã®éšåãæ£ç¢ºã«ç¥ãããã«ãã¹ã¯ããŒã«ããŒã¿ãèšé²ãããã ããäŒããããšã§ãã ããšãã°ãããŒãžãäžçªäžã«å·»ãæ»ãããŠãã©ãŒã ã«å
¥åãå§ããå Žåãã¹ã¯ããŒã«ããã«ãããåçŸããŠãããŸãã¡ãªããã¯ãããŸããã
å€ãã®å°ããªã€ãã³ããèšé²ããéã«ã·ã¹ãã ãªãœãŒã¹ãç¡é§ã«ããã
Lodash
ã䜿çšããããã«ãé£ç¶ãããã¹ãŠã®ã¹ã¯ããŒã«ã€ãã³ãã1ã€ã®ã€ãã³ãã«åéããŸãã
const startScrollCapturing = () => { function handleScroll() { journey.steps.push({ type: INTERACTION_TYPES.SCROLL, data: window.scrollY, }); } window.addEventListener('scroll', debounce(handleScroll, 200)); };
ãã®ã³ãŒãã®
äœæ¥ããŒãžã§ã³ã§ã¯ ãé£ç¶ã¹ã¯ããŒã«ã«é¢é£ããã€ãã³ãã¯é€å€ãããŠããŸãã
startScrollCapturing()
颿°ã¯ãã¢ããªã±ãŒã·ã§ã³ãåããŠèµ·åããããšãã«åŒã³åºãããŸãã
远å ã®ã¢ã€ãã¢
ããã¯ç§ã®ãããžã§ã¯ãã§äœ¿çšãããŠããªãã¢ã€ãã¢ã®çããªã¹ãã§ãã ãããããããããå®è£
ãã䟡å€ããããšæãã§ãããã
- Escã
Tab
ã Enter
ãªã©ã®ããŒããŒãããŒã®ããŒã¹ãããŒã¯ãã€ã³ã¿ãŒã»ããããŸãã
- ã¢ããªã±ãŒã·ã§ã³ã®äœæ¥ãŠã£ã³ããŠã®ãµã€ãºå€æŽã«é¢ããæ
å ±ã®èšé²ïŒã¹ã¯ããŒã«äœçœ®ãèæ
®ããŠãçºçããŠããããšãåçŸããããšãéèŠãªå ŽåïŒã
- åçäžã®åŒã³åºãã¯ãã¹ã¯ããŒã«äœçœ®ãã€ã³ã¿ãŒã»ãããã代ããã«ããšã¬ã¡ã³ããéžæããããšãã®scrollIntoViewïŒïŒãåŒã³åºããŸã ã
localStorage
ããã³cookies
ã³ããŒãäœæããŸãïŒãµã€ãã®åäœã«åœ±é¿ããå ŽåïŒã
- ãããŠæåŸã«ããŠãŒã¶ãŒã¯éåžžã誰ããå
¥åãããã®ãã¹ãŠãç¹ã«ã¯ã¬ãžããã«ãŒãçªå·ããã¹ã¯ãŒããªã©ãååããŠä¿åããå Žåãããã奜ãŸãªãã ãããã£ãŠãããªãã®ãµã€ãã§äœæ¥ããŠããéã圌ã®ã¢ã¯ã·ã§ã³ãã©ããã«èšé²ãããŠããããšã誰ãç¥ããªãããšãéåžžã«éèŠã§ãïŒãã¡ãããç§ã¯åè«ãèšã£ãŠããããšãçè§£ããŠããŸãïŒã
ããã§ã¯ãèšäºã®å
ã®ããŒãžã§ã³ãå
¬éããåŸã«è¿œå ããŸããã ããã€ãã®ã³ã¡ã³ãã§è¿°ã¹ãããŠããããšãšã¯å¯Ÿç
§çã«ããã®è³æã§èª¬æãããŠããæ¹æ³ã¯ãå人ããŒã¿ã®ã»ãã¥ãªãã£ãŸãã¯ä¿è·ã«é¢ãã远å ã®æžå¿µãåŒãèµ·ãããªãããšã«æ³šæã§ããŸãã ãã®å Žåããã§ã«ãŠãŒã¶ãŒã®æ©å¯ããŒã¿ã䜿çšããŠããå Žåããã®ãããªããŒã¿ã®åéãšä¿åã«é©çšãããèŠä»¶ã¯ããšã©ãŒã¬ããŒããæºåããã³éä¿¡ãããšãã«ãé©çšãããå¿
èŠããããŸãã ããšãã°ããŠãŒã¶ãŒã«å¯Ÿå¿ãã質åãããã«ãã©ãŒã ããŒã¿ãèªåçã«ä¿åããªãå ŽåããŠãŒã¶ãŒã«è³ªåããã«ãšã©ãŒã¬ããŒããèªåçã«éä¿¡ããªãã§ãã ããã ãŠãŒã¶ãŒã®å人ããŒã¿ãéä¿¡ããåã«ãç¹å¥ãªãã£ãŒã«ãã«èšå®ããããã§ãã¯ããŒã¯ã®åœ¢ã§ãŠãŒã¶ãŒããåæãåŸã矩åãããå Žåã¯ããšã©ãŒã¬ããŒããéä¿¡ããåã«åãããšãè¡ãå¿
èŠããããŸãã ã·ã¹ãã ã«ç»é²ãããšãã«ã¢ãã¬ã¹
/signup
ã«ãŠãŒã¶ãŒããŒã¿ãéä¿¡ããå ŽåããŸãã¯ãšã©ãŒãçºçããå Žåã«ã¢ãã¬ã¹
/error
ã«ãŠãŒã¶ãŒããŒã¿ãéä¿¡ããå Žåãç¹å¥ãªéãã¯ãããŸããã ãã¡ãã¡ã§æãéèŠãªããšã¯ãããŒã¿ãæ£ããåæ³çã«æ±ãããšã§ãã
ãããããæ¢ã«äŒè©±ãçµäºããŠãããšæãããŸããããã®æç¹ã§ã¯ããŠãŒã¶ãŒããµã€ãã§è¡ã£ãŠããããšã®ã¿ãèšé²ããŸããã æ¬¡ã«ãæãè峿·±ãéšåãã€ãŸãé²é³ã®åçãèŠãŠã¿ãŸãããã
ãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ã®åç
ãµã€ãã§ã®äœæ¥äžã«ãŠãŒã¶ãŒãå®è¡ããã¢ã¯ã·ã§ã³ã®åçŸã«ã€ããŠã¯ã次ã®2ã€ã®åé¡ã«ã€ããŠèª¬æããŸãã
- ãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãåçŸããŠãšã©ãŒã®åå ã調æ»ããããã«äœ¿çšããã€ã³ã¿ãŒãã§ã€ã¹ã
- ãµã€ãã³ãŒãã«åã蟌ãŸããå€éšãã管çã§ããã¡ã«ããºã ã
ãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãåçŸããããã®ã€ã³ã¿ãŒãã§ã€ã¹
ãã®ããŒãžã§ã¯ããŠãŒã¶ãŒã®ã¢ã¯ã·ã§ã³ãç¹°ãè¿ãããã«ã
iFrame
䜿çšãããŸã
iFrame
ã§ã¯ãWebãµã€ããéãããã®äžã§
journey
ãªããžã§ã¯ãã«ä»¥åã«èšé²ãããã¹ããããåçãããŸãã
ãã®ããŒãžã¯ããšã©ãŒãçºçããã»ãã·ã§ã³ã«é¢ããæ
å ±ãããŠã³ããŒãããèšé²ãããåã¹ãããããµã€ãã«éä¿¡ããŸãããµã€ãã¯ç¶æ
ã倿Žããåããšã©ãŒãçºçããŸãã
ãã®ããŒãžãéããšãèŠèŠããã·ã³ãã«ãªã€ã³ã¿ãŒãã§ã€ã¹ã衚瀺ãããŸãããã®åŸãiPadã§è¡šç€ºãããŠãããã®ããã«ãµã€ããèªã¿èŸŒãŸããŸãïŒããã§ã¯ãã¿ãã¬ããã®éåžžã®åçã䜿çšããŸããã
ããã¯ãèšäºã®åé ã§ç€ºããã®ãšåãã¢ãã¡ãŒã·ã§ã³ç»åã§ãã
ããã§ãã®ã³ãŒããèŠã€ããããšãã§ããŸãã
ãŠãŒã¶ãŒã»ãã·ã§ã³ãåçããããã»ã¹[
Next step
]ãã¿ã³ãã¯ãªãã¯ãããšã
iFrame
ã«
iFrame.contentWindow.postMessage(nextStep, '*')
æ§é ã䜿çšããŠã¡ãã»ãŒãž
iFrame
éä¿¡ãããŸãã URLã®å€æŽã«é¢é£ããäŸå€ã1ã€ãããŸãã ã€ãŸããåæ§ã®ç¶æ³ã§ã¯ã
iFrame
src
ããããã£ã¯åã«å€æŽãããŸãã ã¢ããªã±ãŒã·ã§ã³ã®å Žåãããã¯å®éã«ã¯ããŒãžå
šäœã®æŽæ°ã§ããããããããæ©èœãããã©ããã¯ãããŒãžéã§ã¢ããªã±ãŒã·ã§ã³ã®ç¶æ
ã転éããæ¹æ³ã«ãã£ãŠç°ãªããŸãã
ããããªãå Žåã
postMessage â
ãç°ãªããŠã£ã³ããŠéã®å¯Ÿè©±ãæäŸããããã«äœæãã
ãWindowãªããžã§ã¯ãã®ã¡ãœããã§ã ïŒãã®å Žåãããã¯ããŒãžã®ã¡ã€ã³ãŠã£ã³ããŠãš
iFrame
éããããŠã£ã³ããŠã§ãïŒã
å®éããŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãåçŸããããŒãžã«ã€ããŠèšããããšã¯ããã ãã§ãã
å€éšãããµã€ãã管çããããã®ã¡ã«ããºã
ãµã€ãã§ã®äœæ¥äžã«ãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãåçŸããã¡ã«ããºã ã¯ã
playback.jsãã¡ã€ã«ã«å®è£
ãããŠããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®èµ·åæã«ããªããžããªã«åé¡ãããåŸã§åŒã³åºãããšãã§ããã¡ãã»ãŒãžãäºæãã颿°ãåŒã³åºããŸãã ããã¯éçºã¢ãŒãã§ã®ã¿è¡ãããŸãã
const store = createStore( // ); if (process.env.NODE_ENV === 'development') { startListeningForPlayback(store); }
ãã㯠ããã®ã³ãŒãã䜿çšãããå Žæã§ãã
èå³ã®ãã颿°ã¯æ¬¡ã®ããã«ãªããŸãã
export const startListeningForPlayback = (store) => { window.addEventListener('message', (message) => { switch (message.data.type) { case INTERACTION_TYPES.REDUX_ACTION: store.dispatch(message.data.data); break; case INTERACTION_TYPES.SCROLL: window.scrollTo(0, message.data.data); break; case INTERACTION_TYPES.ELEMENT_INTERACTION: highlightElement(message.data.data.interactionId); break; default:
ããã§ã¯ããã®ãã«ããŒãžã§ã³ãèŠã€ããããšãã§ããŸãã
Reduxã¢ã¯ã·ã§ã³ã䜿çšããå Žåããããã¯ãªããžããªã«ãã£ã¹ãããããããã以äžã¯ãã£ã¹ããããããŸããã
ã¹ã¯ããŒã«ãåçããããšãããŸãã«ããªããæåŸ
ã§ããããšãè¡ãããŸãã ãã®ç¶æ³ã§ã¯ãããŒãžã®å¹
ãæ£ããããšãéèŠã§ãã ãããžã§ã¯ããªããžããªãèŠããšããŠãŒã¶ãŒããŠã£ã³ããŠã®ãµã€ãºã倿Žããããããšãã°ãµã€ãã衚瀺ãããŠããã¢ãã€ã«ããã€ã¹ãå転ãããããããšããã¹ãŠãæ£ããåäœããããšã
scrollIntoView() â
ã
scrollIntoView() â
ãåŒã³åºãããš
scrollIntoView() â
ããããã«ããŠãåççãªè§£æ±ºçã ãšæããŸãã
highlightElement()
颿°ã¯ãåçŽã«èŠçŽ ã®åšå²ã«å¢çç·ã远å ããŸãã 圌女ã®ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
function highlightElement(interactionId) { const el = document.querySelector(`[data-interaction-id="${interactionId}"]`); el.style.outline = '5px solid rgba(255, 0, 0, 0.67)'; setTimeout(() => { el.style.outline = ''; }, 2000); }
ãã€ãã®ããã«ãããã¯ãã®é¢æ°ã®å®å
šãªã³ãŒãã§ãã
ãŸãšã
React / Reduxã¢ããªã±ãŒã·ã§ã³ã§ã®ç°¡åãªãšã©ãŒå ±åã·ã¹ãã ãèŠãŸããã å®éã«åœ¹ç«ã¡ãŸããïŒ ããã¯ããããžã§ã¯ãã«è¡šç€ºããããšã©ãŒã®æ°ãšãããããèŠã€ããã®ãã©ãã»ã©é£ãããã«ãããšæããŸãã
ãšã©ãŒãçºçããå Žåã¯ãURLãæžãçããŠãã®æ
å ±ãä¿åããŠããã°ãåé¡ã®åå ãç¹å®ããã®ã«åœ¹ç«ã¡ãŸãã ãŸãã¯ããŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãèšé²ããã·ã¹ãã ã¯æåããŠããããã«èŠããŸããããµã€ããšã®ã»ãã·ã§ã³ãåçããããŒãžã¯æåããŠããŸããã ããšãã°ãiOSã®Safari 9ã§ã®ã¿çºçãããšã©ãŒãçºçããå Žåãã»ãã·ã§ã³åçããŒãžã¯åœ¹ã«ç«ããªããªããŸãããšã©ãŒãç¹°ãè¿ãããšã¯ã§ããªãããã§ãã
ãããããªç ç©¶ã«ã€ããŠè©±ããŸããããã®äžã®1ã€ã«ã€ããŠè©±ããŸããããå®éã®ãããžã§ã¯ãã®1ã€ã§å®éšã®çµæãšããŠäœæããããã®ãåãèŸŒãæºåãã§ããŠãããã©ãããèªåãããšããç§ã«ãšã£ãŠçå®ã®ç¬éãæ¥ãŸãã ãã®å Žåããã®è³ªåã«å¯Ÿããçãã¯ããŒã§ãã
ãããã«ããããŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãååããŠåçŸããã·ã¹ãã ã§äœæ¥ããããšã¯ãç§ãäœãæ°ããããšãåŠã¶ããšãå¯èœã«ããè峿·±ãäœéšã§ãã ããã«ããããµã€ãã«ç£èŠã·ã¹ãã ãè¿
éã«å®è£
ããå¿
èŠãããå Žåããã€ãããããã¹ãŠã圹ã«ç«ã€ãšä¿¡ããŠããŸãã
芪æãªãèªè
ïŒ ãã°ã¯ã©ã®ããã«åŠçããŸããïŒ .