Slide 1

Slide 1 text

WordPressͰ HeadlessϑϩϯτΤϯυ Kansai WordPress Meetup 2020/11 Okamoto Hidetaka #WPmeetupOsaka

Slide 2

Slide 2 text

TL;DR • webαΠτදࣔํ๏͸SSR / SPA / SSGͷ3ͭ • SEO / Մ༻ੑॏࢹͳΒ͹SSG • Paywall / ձһઐ༻ίϯςϯπͳͲ͸SPA • ύϑΥʔϚϯεͱߋ৽଎౓ͷఱṝ࣍ୈͰSSR #WPmeetupOsaka

Slide 3

Slide 3 text

Agenda • WordPressΛHeadlessʹ࢖͏ͨΊʹඞཁͳ΋ͷ • SPAͰ࡞Δํ๏ • SSGͰ࡞Δํ๏ • SSRͰ࡞Δํ๏ • Next.js ͱ Gatsby • All In One Content Management System͔Βͷ୤٫ #WPmeetupOsaka

Slide 4

Slide 4 text

“Why Headlessʁ”͸ҎԼͷεϥΠυ΁ https://speakerdeck.com/hideokamoto/shifter-meetup-202011 #WPmeetupOsaka

Slide 5

Slide 5 text

Agenda • WordPressΛHeadlessʹ࢖͏ͨΊʹඞཁͳ΋ͷ • SPAͰ࡞Δํ๏ • SSGͰ࡞Δํ๏ • SSRͰ࡞Δํ๏ • Next.js ͱ Gatsby • All In One Content Management System͔Βͷ୤٫ #WPmeetupOsaka

Slide 6

Slide 6 text

Headless = ֎͔ΒWPͷσʔλΛऔಘ͢Δ • HTTP(S) APIΛར༻ͯ͠ɺ֎෦͔ΒWPͷσʔλΛऔಘ • REST API / GraphQL API / XMLRPC APIͷ3ͭ • XMLRPC APIͷ͜ͱ͸๨Ε·͠ΐ͏ • REST API: ͍ΘΏΔWP API • GraphQL: WP GraphQL ϓϥάΠϯʢ࠷͍ۙͭʹv1ϦϦʔεʣ #WPmeetupOsaka

Slide 7

Slide 7 text

WP API • WPίΞ͕ఏڙ͢ΔREST API • GET͸͍͍ͩͨೝূͳ͠ͰOK • HookͰΧελϚΠζՄೳ • ΧελϜϑΟʔϧυͳͲͷ֦ு͸ ϓϥάΠϯ͔HookͰରԠ https://developer.wordpress.org/rest-api/reference/ #WPmeetupOsaka

Slide 8

Slide 8 text

WP GraphQL • ϓϥάΠϯͱͯ͠Πϯετʔϧ • WordPressͷσʔλΛGraphQLͰ • Hook΍ϓϥάΠϯͰ֦ுՄೳ • ഁյతมߋ͕ଟ͔ͬͨͷͰ v0࣌୅ͷهࣄʹ͸ཁ஫ҙ https://wordpress.org/plugins/wp-graphql/ #WPmeetupOsaka

Slide 9

Slide 9 text

REST API or GraphQL • ໔ڐऔಘલ͔ΒϨʔγϯάΧʔʹ৐Δඞཁ͸ͳ͍ • γϯϓϧͳBlog / websiteͳΒREST APIͰ͍͍ͩͨࣄ଍ΓΔ • ΧελϜ౤ߘ / ϑΟʔϧυͳͲ͕૿͑ͯ͘ΔͱɺGraphQL΋ݕ౼ର৅ • REST APIΛ3ͭ΋4ͭ΋ಉ࣌ʹୟ͔ͳ͍ͱ͍͚ͳ͍ or HookͰΧελϜ͠·͘Βͳ͍ͱ͍͚ͳ͍ͳΒGraphQLͷग़൪ • ࠷ऴతʹHTTPͰGET(REST)͔POST(GraphQL)͢ΔͷʹมΘΓͳ͠ʢWebSocketͷ͜ͱ͸͍ͬͨΜ๨ΕΖʣ #WPmeetupOsaka

Slide 10

Slide 10 text

Agenda • WordPressΛHeadlessʹ࢖͏ͨΊʹඞཁͳ΋ͷ • SPAͰ࡞Δํ๏ • SSGͰ࡞Δํ๏ • SSRͰ࡞Δํ๏ • Next.js ͱ Gatsby • All In One Content Management System͔Βͷ୤٫ #WPmeetupOsaka

Slide 11

Slide 11 text

S ingle P age A pplication • ࠷ۙͷWebΞϓϦʹଟ͍ • AjaxͰσʔλΛऔಘͯ͠දࣔ • νϡʔτϦΞϧ΍ೖ໳ॻ͸ ͍͍ͩͨ͜ΕΛ࡞Δ͜ͱ͕ଟ͍ https://ja.reactjs.org/ #WPmeetupOsaka

Slide 12

Slide 12 text

ReactͰͷ REST API import React, {useEffect, useState } from 'react' import DOMPurify from 'dompurify'; export const Home:FC<{ posts: WPPost[] }> = ({posts: initialProps}) => { const [posts, setPosts] = useState([]) useEffect(() => { fetch('https://wp.example.com/wp-json/wp/v2/posts') .then(data => { return data.json() }) .then(data => { setPosts(data) }) }) return (
{posts.map(post => (

))}
) • APIͳͲඇಉظॲཧ͸ Ұखؒඞཁ • useEffectͰAPIݺͼग़͠ • useStateͰϨεϙϯεอ࣋ • ͋ͱ͸React JSXͰHTMLඳը #WPmeetupOsaka

Slide 13

Slide 13 text

ReactͰͷ REST API import React, {useEffect, useState } from 'react' import DOMPurify from 'dompurify'; export const Home:FC<{ posts: WPPost[] }> = ({posts: initialProps}) => { const [posts, setPosts] = useState([]) useEffect(() => { fetch('https://wp.example.com/wp-json/wp/v2/posts') .then(data => { return data.json() }) .then(data => { setPosts(data) }) }) return (
{posts.map(post => (

))}
) • APIͳͲඇಉظॲཧ͸ Ұखؒඞཁ • useEffectͰAPIݺͼग़͠ • useStateͰϨεϙϯεอ࣋ • ͋ͱ͸React JSXͰHTMLඳը #WPmeetupOsaka

Slide 14

Slide 14 text

ReactͰͷ REST API import React, {useEffect, useState } from 'react' import DOMPurify from 'dompurify'; export const Home:FC<{ posts: WPPost[] }> = ({posts: initialProps}) => { const [posts, setPosts] = useState([]) useEffect(() => { fetch('https://wp.example.com/wp-json/wp/v2/posts') .then(data => { return data.json() }) .then(data => { setPosts(data) }) }) return (
{posts.map(post => (

))}
) • APIͳͲඇಉظॲཧ͸ Ұखؒඞཁ • useEffectͰAPIݺͼग़͠ • useStateͰϨεϙϯεอ࣋ • ͋ͱ͸React JSXͰHTMLඳը #WPmeetupOsaka

Slide 15

Slide 15 text

ReactͰͷ REST API import React, {useEffect, useState } from 'react' import DOMPurify from 'dompurify'; export const Home:FC<{ posts: WPPost[] }> = ({posts: initialProps}) => { const [posts, setPosts] = useState([]) useEffect(() => { fetch('https://wp.example.com/wp-json/wp/v2/posts') .then(data => { return data.json() }) .then(data => { setPosts(data) }) }) return (
{posts.map(post => (

))}
) • APIͳͲඇಉظॲཧ͸ Ұखؒඞཁ • useEffectͰAPIݺͼग़͠ • useStateͰϨεϙϯεอ࣋ • ͋ͱ͸React JSXͰHTMLඳը #WPmeetupOsaka

Slide 16

Slide 16 text

SPAͰWebαΠτΛ࡞Δ • ೖ໳͠΍͍͢ • ॻ੶ͳͲͷϦιʔε΋ଟΊ • શ෦ϑϩϯτͰ࣮ߦͳͷͰ ൺֱతγϯϓϧʹ࡞ΕΔ • CapacitorͳͲͰiOS / AndroidରԠ ϝϦοτ • SEO / OGPͰҰखؒඞཁ • ϧʔςΟϯά΋͋Δఔ౓ࣗલ࣮૷ • First Meaningful Paint͕஗Ί • ίʔυ෼ׂ͠ͳ͍ͱ JSͷಡΈࠐΈαΠζ͕ංେ͕ͪ͠ σϝϦοτ #WPmeetupOsaka

Slide 17

Slide 17 text

Agenda • WordPressΛHeadlessʹ࢖͏ͨΊʹඞཁͳ΋ͷ • SPAͰ࡞Δํ๏ • SSGͰ࡞Δํ๏ • SSRͰ࡞Δํ๏ • Next.js ͱ Gatsby • All In One Content Management System͔Βͷ୤٫ #WPmeetupOsaka

Slide 18

Slide 18 text

S tatic S ite G enerator • Jekyll΍HugoͳͲ΋ • දࣔ͢ΔHTMLΛࣄલʹੜ੒͢Δ • MovableTypeͷGenerate΋͍ۙ • FW / Tool͕܈༤ׂڌঢ়ଶ Vue / React + Ruby / Go / etc… https://jamstack.org/generators/ #WPmeetupOsaka

Slide 19

Slide 19 text

ReactͰͷSSG 2TOP: Next.js / Gatsby

Slide 20

Slide 20 text

SSGͰWebαΠτΛ࡞Δ • ࣄલʹHTMLΛϏϧυ͢ΔͷͰɺ දࣔ଎౓͕଎͘ͳΓ΍͍͢ • WP / DBʹো֐͕ى͖ͯ΋ɺ webαΠτ͸μ΢ϯ͠ͳ͍ • αʔόʔ͕҆Ձ • FWͷػೳ / API͕๛෋ ϝϦοτ • Ϗϧυ͠ͳ͍ͱެ։Ͱ͖ͳ͍ • ϖʔδ਺ʹൺྫ͢ΔϏϧυ࣌ؒ • FW΁ͷґଘ͕ڧ͘ͳΓ͕ͪ • Ϗϧυͷσόοά͕গ͠େม σϝϦοτ #WPmeetupOsaka

Slide 21

Slide 21 text

Agenda • WordPressΛHeadlessʹ࢖͏ͨΊʹඞཁͳ΋ͷ • SPAͰ࡞Δํ๏ • SSGͰ࡞Δํ๏ • SSRͰ࡞Δํ๏ • Next.js ͱ Gatsby • All In One Content Management System͔Βͷ୤٫ #WPmeetupOsaka

Slide 22

Slide 22 text

S erver S ide R endering • WordPressςʔϚͱಉ͡ख๏ • ౎౓HTMLඳըͳͷͰɺ ϏϧυΛ଴ͭඞཁͳ͠ • αʔόʔଆඳըͳͷͰɺ SEO / OGPͷෆ҆΋ͳ͠ • WPಛԽFW “Frontity”ͷଘࡏ΋ https://frontity.org/ #WPmeetupOsaka

Slide 23

Slide 23 text

FrontityͰ WebαΠτ # ΞϓϦͷηοτΞοϓ $ npx frontity create my-app $ cd my-app # ϩʔΧϧͰͷςεταΠτ্ཱͪ͛ $ npx frontity dev -> http://localhost:3000 # σΟϨΫτϦߏ੒ $ tree my-app/ |__ node_modules/ |__ package.json |__ frontity.settings.js |__ favicon.ico |__ packages/ |__ mars-theme/ • جຊతͳૢ࡞͸CLI͚ͩ • —themeͰςʔϚ͕બ΂Δ • —typescript΋αϙʔτ #WPmeetupOsaka

Slide 24

Slide 24 text

FrontityͰ WebαΠτ "name": "frontity-example", "state": { "frontity": { "url": "https://test.frontity.io", "title": "WordPress Theme Unittest", "description": "Frontity example site using WordPress Theme Unittest posts" } }, "packages": [ { "name": "@frontity/mars-theme", "state": { "theme": { "menu": [ [ “Home", “/“ ], [ "Edge Case Category”, “/category/edge-case-2/“ ], [ “About”, “/about/“ ] ], "featured": { "showOnList": false, "showOnPost": false } } } }, { "name": "@frontity/wp-source", "state": { "source": { "api": "https://test.frontity.io/wp-json" } } }, • frontity.config.jsͰઃఆ • WPςʔϚͷΑ͏ʹ ίʔυΛ৮Βͤͳ͍ ΧελϚΠζํ๏ • ςʔϚͷࣗ࡞ / ެ։΋Մೳ #WPmeetupOsaka

Slide 25

Slide 25 text

S erver S ide R endering • WordPressςʔϚͱಉ͡ख๏ • ౎౓HTMLඳըͳͷͰɺ ϏϧυΛ଴ͭඞཁͳ͠ • αʔόʔଆඳըͳͷͰɺ SEO / OGPͷෆ҆΋ͳ͠ • WPಛԽFW “Frontity”ͷଘࡏ΋ https://frontity.org/ #WPmeetupOsaka

Slide 26

Slide 26 text

FrontityͰ WebαΠτ • Vercel΍HerokuͳͲʹ ެ։ • Node.js͕ಈ͘ඞཁ͋Γ • WPͷαʔόʔʹಉډ΋ https://frontity.org/

Slide 27

Slide 27 text

SSRͰWebαΠτΛ࡞Δ • SSGͱSPAͷܽ఺Λิ͑Δ • SEO / OGP / HeaderͳͲͷग़ྗ • ϏϧυʹΑΔެ։·Ͱͷϥά • Ruby / Go / PythonͳͲͰ΋Մೳ ϝϦοτ • ʮWordPressςʔϚͰΑ͘Ͷʁʯ • WPಉ༷ࣄނΕ͹നը໘ͷHTTP500 • ϑϩϯτͷJS + αʔόʔͷJSͷ ೋॏ؅ཧ͕ൃੜ͠͏Δ σϝϦοτ #WPmeetupOsaka

Slide 28

Slide 28 text

SPA / SSG / SSR͓͞Β͍ 41" 44( 443 )5.-ඳը ϒϥ΢β্ Ϗϧυ࣌ ʢ$*ϩʔΧϧͳͲʣ αʔόʔ্ '8ͳͲ *POJD3FBDU $SFBUF3FBDU"QQ /FYUKT (BUTCZ 'SPOUJUZ XJUI81ͷ αΠτߏங ʮ΍ͬͯΈͨʯهࣄ ॻ੶ͳͲΛࢀߟʹ '8ͷνϡʔτϦΞϧ Λࢀߟʹ '8ͷνϡʔτϦΞϧ Λࢀߟʹ ޲͍͍ͯΔέʔε 8FCΞϓϦ ձһ޲͚αΠτ ϒϩάϙʔτϑΥϦΦ -1ΩϟϯϖʔϯαΠτ ͦΕҎ֎ #WPmeetupOsaka

Slide 29

Slide 29 text

Agenda • WordPressΛHeadlessʹ࢖͏ͨΊʹඞཁͳ΋ͷ • SPAͰ࡞Δํ๏ • SSGͰ࡞Δํ๏ • SSRͰ࡞Δํ๏ • Next.js ͱ Gatsby.js • All In One Content Management System͔Βͷ୤٫ #WPmeetupOsaka

Slide 30

Slide 30 text

ReactͰͷSSG 2TOP: Next.js / Gatsby

Slide 31

Slide 31 text

ReactͰͷSSG 2TOP: Next.js / Gatsby /FYUKT (BUTCZ 3FOEFSJOH 44(443 44( 3PVUJOH OFYUSPVUFS !SFBDISPVUFS 0⒏DJBM )PTUJOH 7FSDFM (BUTCZ$MPVE %BUB 3FRVFTU 3&45"1*(SBQI2- (SBQI2-

Slide 32

Slide 32 text

Next.js / Gatsbyݸਓతൺֱ • σʔλͷऔಘ͕ࣗલ࣮૷ • SSRซ༻Ͱެ։·ͰͷϥάΛ୹ॖ • SSGߴ଎Խ͸3rd partyґଘ • SSR΋Մೳɻ෯޿͘࢖͑Δ Next.js • ϓϥάΠϯͰ؆୯σʔλऔಘ • ϏϧυඞਢͳͷͰެ։ʹϥά༗ • ࠩ෼ϏϧυʹΑΔϏϧυߴ଎Խ • SSGʹಛԽ Gatsby #WPmeetupOsaka

Slide 33

Slide 33 text

Next.js / Gatsbyʹڞ௨͍ͯ͠Δ͜ͱ ࣗࣾαʔϏε͋Γ͖ͷ ػೳ͕ͨ·ʹؚ·ΕΔ ͍͍ͦͯͩͨ͠୭͔ʹʮNetlify൛ʯΛޙൃͰग़͞ΕΔ #WPmeetupOsaka

Slide 34

Slide 34 text

Next.jsͱGatsbyͷσʔλऔಘ export const getStaticPaths = async () => { const posts = await fetcher(url) return { paths: posts.map(post => ({ params: { id: post.id, slug: decodeURI(post.slug) } })), fallback: false } } export const pageQuery = graphql` query SinglePost($slug: String) { wordpressPost(slug: { eq: $slug }) { id slug title content } } ` Next.js Gatsby #WPmeetupOsaka

Slide 35

Slide 35 text

ࣗ෼Ͱࢼͯ͠Έ͍ͨਓ͸Shifterϒϩά΁ https://www.getshifter.io/ja/blog/category/integration-ja/ #WPmeetupOsaka

Slide 36

Slide 36 text

SSGͷϏϧυ஗Ԇ໰୊ • Gatsby͸ʮࠩ෼ͷΈϏϧυ͢Δํ๏ʯΛϕʔλϦϦʔε Incremental Builds: https://www.gatsbyjs.com/blog/2020-04-22-announcing-incremental-builds/ • Next.js͸ʮͳ͍ͳΒͦͷ৔ͰSSG / SSR͠Α͏ʯͱ͍͏ൃ૝ Fallback mode: https://nextjs.org/docs/basic-features/data-fetching#fallback-true • Next.js͸͞ΒʹʮఆظతʹཪଆͰSSG͠ͳ͓ͦ͏ʯͱ΋ߟ͍͑ͯΔ Incremental Static Regeneration: https://nextjs.org/docs/basic-features/data-fetching#incremental-static-regeneration • Gatsby͸ϏϧυΛߴ଎ԽɺNext.js͸SSRతൃ૝Λซ༻ͯ͠ߴ଎Խ #WPmeetupOsaka

Slide 37

Slide 37 text

Agenda • WordPressΛHeadlessʹ࢖͏ͨΊʹඞཁͳ΋ͷ • SPAͰ࡞Δํ๏ • SSGͰ࡞Δํ๏ • SSRͰ࡞Δํ๏ • Next.js ͱ Gatsby.js • All In One Content Management System͔Βͷ୤٫ #WPmeetupOsaka

Slide 38

Slide 38 text

JavaScriptͰϑϩϯτΤϯυΛͳͥ࡞Δʁ • ։ൃ؀ڥɾެ։αʔόʔͷ༻ҙָ͕ • ো֐΍ΞΫηεूதʹର͢Δڧ౓্͕͕Γ΍͍͢ • ڞ༗Մೳͳίϯϙʔωϯτ͕࡞ΕΔ / ར༻Ͱ͖Δ • ʮ࠶ར༻ੑͷߴ͍ٕज़ɾϊ΢ϋ΢ʯ͕ͨ·Γ΍͍͢ #WPmeetupOsaka

Slide 39

Slide 39 text

JavaScriptͰϑϩϯτΤϯυΛͳͥ࡞Δʁ • ։ൃ؀ڥɾެ։αʔόʔͷ༻ҙָ͕ • ো֐΍ΞΫηεूதʹର͢Δڧ౓্͕͕Γ΍͍͢ • ڞ༗Մೳͳίϯϙʔωϯτ͕࡞ΕΔ / ར༻Ͱ͖Δ • ʮ࠶ར༻ੑͷߴ͍ٕज़ɾϊ΢ϋ΢ʯ͕ͨ·Γ΍͍͢ #WPmeetupOsaka

Slide 40

Slide 40 text

ಠࣗλάͷ࡞੒ / ར༻ͰϚʔΫΞοϓͷڞ௨Խ …

Hello, world!

Learn more

.col-md-1
.col-md-1
import React from 'react'; import { Jumbotron, Button, Row, Col } from 'reactstrap'; export const App: FC = () => ( <>

Hello, world!

Learn More

.col > ) WordPress Theme React (Reactstrap) #WPmeetupOsaka

Slide 41

Slide 41 text

ެ։͞Ε͍ͯΔUIϑϨʔϜϫʔΫͷಋೖ / ެ։ • Bootstrap / Material Design / Foundation / etc.. • ଟ͘ͷCSSϑϨʔϜϫʔΫ͸͍͍ͩͨReactnize͞Εͨ΋ͷ͕͋Δ • reactstrap / material-ui / react-foundation / etc.. • Ionic FrameworkͷΑ͏ʹReact / Angular / VueΛԣஅͰ͖Δ΋ͷ΋ • AWS NorthstarͷΑ͏ʹɺ σβΠϯΨΠυϥΠϯΛϥΠϒϥϦԽͯ͠γΣΞ͕Ͱ͖Δ #WPmeetupOsaka

Slide 42

Slide 42 text

JavaScriptͰϑϩϯτΤϯυΛͳͥ࡞Δʁ • ։ൃ؀ڥɾެ։αʔόʔͷ༻ҙָ͕ • ো֐΍ΞΫηεूதʹର͢Δڧ౓্͕͕Γ΍͍͢ • ڞ༗Մೳͳίϯϙʔωϯτ͕࡞ΕΔ / ར༻Ͱ͖Δ • ʮ࠶ར༻ੑͷߴ͍ٕज़ɾϊ΢ϋ΢ʯ͕ͨ·Γ΍͍͢ #WPmeetupOsaka

Slide 43

Slide 43 text

σʔλͱ ϑϩϯτͷ෼཭ • HeadlessԽ͢Δ͜ͱͰɺ CMSґଘগͷϑϩϯτ͕࡞ΕΔ • Gatsby͸Source PluginͰ ෳ਺data source͕ར༻Մೳ • dataʹґଘ͠ͳ͍ϑϩϯτٕज़ ͱͯ͠ͷJavaScript https://www.gatsbyjs.com/plugins?=source #WPmeetupOsaka

Slide 44

Slide 44 text

TL;DR • Headlessʹ͢Δ͜ͱͰɺ ͞·͟·ͳํ๏ / ݴޠ / FWͰαΠτ͕࡞ΕΔ • ReactΛ࢖͏৔߹ɺNext.js / GatsbyͳͲΛ࢖͏ͷ͕ ͍·ͷͱ͜ΖఆੴԽͭͭ͋͠Δ • WordPress͚ͩͰαΠτΛ։ൃ / ӡ༻͍ͯ͠ͳ͍৔߹ʹɺ ؀ڥʹґଘ͠ͳ͍Headless͕׆͖΍͍͢ #WPmeetupOsaka