Upgrade to Pro — share decks privately, control downloads, hide ads and more …

pixiv SketchのSSRの話

geta6
April 11, 2017

pixiv SketchのSSRの話

pixiv SketchでSSRしている感じの話です

geta6

April 11, 2017
Tweet

More Decks by geta6

Other Decks in Technology

Transcript

  1. ΞʔΩςΫνϟ Web Browser pixiv Sketch API rails iOS Android iOS

    app Android app node.js javascript ࠷ۙͨ·ʹݟ͔͚Δߏ੒͚ͩͲɺ೥΍ͬͯΔͱ͜͸গͳͦ͏
  2. ΞʔΩςΫνϟ Web Browser pixiv Sketch API rails iOS Android iOS

    app Android app node.js javascript ΅͘ͷ୲౰
  3. 443ग़ྗͷΠϝʔδ const app = new Fluxible({ /* shared app root

    component, stores */ }); const srv = express(); srv.use((req, res) => { req.context = app.createContext(); /* ͍Ζ͍Ζ४උ͢Δ (APIΛfetchͨ͠Γͯ͠ɺfluxΛճ͢) */ const react = React.createElement(Html, { context: req.context }); const html = ReactDOM.renderToStaticMarkup(react); res.send(`<!doctype html>${html}`); }); ͜͜Ͱڞ௨ίʔυ Λ౉͢ html͕ϧʔτͷ component ͔ΜͨΜʂʂ
  4. express (1 request) 443ग़ྗͷΠϝʔδ req Flux Context res React Flux

    Context ReactDOM store store css React (html)
  5. express (1 request) 443ग़ྗͷΠϝʔδ req Flux Context res React Flux

    Context ReactDOM store store css React (html) shared shared server code
  6. JTPNPSQIJDTUPSF const app = new Fluxible({ /* shared app root

    component, stores */ }); const srv = express(); srv.use((req, res) => { req.context = app.createContext(); /* ͍Ζ͍Ζ४උ͢Δ (APIΛfetchͨ͠Γͯ͠ɺfluxΛճ͢) */ const dehydrated = `window.dehydrated=${serialize(app.dehydrate(req.context))}`; const react = React.createElement(Html, { context, dehydrated }); const html = ReactDOM.renderToStaticMarkup(react); res.send(`<!doctype html>${html}`); }); serializeͯ͠౉͢
  7. JTPNPSQIJDDTT const app = new Fluxible({ /* shared app root

    component, stores */ }); const srv = express(); srv.use((req, res) => { req.context = app.createContext(); /* ͍Ζ͍Ζ४උ͢Δ (APIΛfetchͨ͠Γͯ͠ɺfluxΛճ͢) */ const context = req.context.getComponentContext(); const styles = []; context.insertCss = (s) => styles.push(s._getCss()); const dehydrated = `window.dehydrated=${serialize(app.dehydrate(req.context))}`; const react = React.createElement(Html, { context, dehydrated, styles }); res.send(`<!doctype html>${html}`); }); ReactContextͰpush
 ͢ΔϝιουΛ౉͢
  8. express (1 request) 443ग़ྗͷΠϝʔδ req Flux Context res React Flux

    Context ReactDOM store store css React (html) serialize ArrayPush render toStaticMarkup res.send
  9. ίϯϙʔωϯτߏ੒ - Component/ `- package.json // { "main": "Component.jsx" }

    `- Component.jsx // component `- Component.styl // stylesheet for component σΟϨΫτϦΛimportͨ࣌͠ʹ mainͷ஋Λࢀরͯ͘͠ΕΔ
  10. $PNQPOFOUKTY import React, { Component } from 'react'; import {

    withStyle } from '../../utils/Decorator'; @withStyle(require('./Component.styl')) export default class Component extends Component { static displayName = 'Component'; componentDidMount = () => { console.log('mounted'); }; render = () => ( <div id='Component'> <div id='ComponentBody'> <span>component content</span> </div> </div> ); } ޙड़ ίϯϙʔωϯτ໊ͱಉ͡ id͔classΛRootʹऔΔ ※ transform-decorators-legacy
  11. $PNQPOFOUTUZM #Component &Body box-sizing border-box margin 0 auto padding 0

    20px max-width 600px width 100% ϑΝΠϧ͋ͨΓ Root͸1ݸͷϧʔϧ
  12. 4UZMF%FDPSBUPS import noop from 'lodash/noop'; import React, { Component, PropTypes

    } from 'react'; export const withStyleDecorator = (style) => (ComposedComponent) => ( class WithStyle extends Component { static displayName = `withStyle(${ComposedComponent.displayName})`; static contextTypes = { insertCss: PropTypes.func.isRequired, }; constructor(props, context) { super(props, context); this.removeCss = style ? this.context.insertCss(style) : noop; } componentWillUnmount = () => { this.removeCss && setTimeout(this.removeCss, 0); }; render = () => ( <ComposedComponent {...this.props} /> ); } ); isomorphic-style-loader ͔Βఏڙ͞ΕΔϚ΢ϯλʔ
  13. 8FCͷେ·͔ͳมભ w  ։ൃ։࢝ νʔϜϝϯόʔਓ  w  ϦϦʔε w

     υϩʔػೳWϦϦʔε 4NPPUI-JOF  w  8FCϦϑΝΫλϦϯά w  υϩʔػೳWϦϦʔε 8FC(-൛
  14. 443ΛܾΊͨϑϩʔ w όοΫΤϯυ΁ͷෆ͔҆ΒSBJMTΤϯδχΞΛௐୡ w SBJMT͔ΒWJFXΛग़͢ͷ͸ઈରʹݏͩͬͨ ޙड़  w 1.ʮJ04൛͸ઈରಉ࣌ʹϦϦʔε͢Δͧʯ w

    αʔϏεϦϦʔε౰ॳ͔Β"1*͕ඞཁ w SBJMTαʔόʔ͔ΒWJFXΛग़ྗ͢Δͱɺ"1*ͱWJFX Ͱೋॏʹ࣮૷͕ඞཁʹͳͬͯ͠·͏
  15. SFTQPOTF srv.use(async (req, res, next) => { try { await

    Promise.all([ request1, request2, request3, ]); next(); } catch (error) { next(error); } }); ͜͏͍͏ײ͡