Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
No Install CMS戦略 〜 5年先を見据えたフロントエンド開発を考える / no_i...
Search
Masahiko Sakakibara
July 25, 2025
Programming
690
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
No Install CMS戦略 〜 5年先を見据えたフロントエンド開発を考える / no_install_cms
https://techramenconf.net/
登壇資料です
Masahiko Sakakibara
July 25, 2025
More Decks by Masahiko Sakakibara
See All by Masahiko Sakakibara
決済端末ビジネスを、決済会社だけのものにしない/stripe_terminal_business
rdlabo
0
56
JavaScriptで始める店舗インフラ決済構築/stripe_terminal_workshop
rdlabo
0
44
本当に欲しかったのはモノレポツールではなく、tsconfigの設定だった / monorepo-tsconfig
rdlabo
1
380
Reactフレームワークプロダクトを モバイルアプリにして、もっと便利に。 ユーザに価値を届けよう。/React Framework with Capacitor
rdlabo
0
560
プライベートプロダクト戦略 - フロントエンドカンファレンス沖縄 / private_product_frontend
rdlabo
3
4.9k
GitHubをCMSとして使う話/ using_github_as_CMS
rdlabo
0
680
JavaScriptから デバイスの力を100%引き出すための Web APIとCapacitor入門 / power_from_javascript
rdlabo
0
640
Capacitor4_release
rdlabo
0
730
Web技術で稼ぐため選択肢を俯瞰しよう/options_to_earn_web_technology
rdlabo
0
170
Other Decks in Programming
See All in Programming
go-spidermonkeyでAIエージェントのCode Modeを実装する
syumai
3
1.5k
AIの中の人になってみる
htkym
0
150
AI時代に学ぶ 好きなルール 嫌いなルール Linter編
shorty5121
0
760
AIと壁打ちしながら進めるコスト管理
fufuhu
2
1.9k
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
210
自分的「カンファレンスの楽しみ方」
syumai
0
170
PyO3 で既存 Python 評価器を Rust core 化する ー wasm-bindgen でブラウザにも配るための設計
kdash
1
200
Jindong: Introducing Declarative Haptics in Compose Multiplatform
l2hyunwoo
0
140
Oxlintはいいぞ(続)
yug1224
1
520
自動化したのに回らない テスト運用の壁―AI時代の品質責任と生産性
mfunaki
0
570
Flow は今どうなっているか
mizdra
PRO
0
830
ハーネス設計入門 〜プロンプト、コンテキストの次〜
kinopeee
52
32k
Featured
See All Featured
A Tale of Four Properties
chriscoyier
163
24k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
Abbi's Birthday
coloredviolet
3
9.7k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
440
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Utilizing Notion as your number one productivity tool
mfonobong
4
560
Skip the Path - Find Your Career Trail
mkilby
1
210
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
4
540
Bash Introduction
62gerente
615
220k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Transcript
/P*OTUBMM$.4ઓུ ʙઌΛݟਾ͑ͨϑϩϯτΤϯυ։ൃΛߟ͑Δ
ࣗݾհ ࡗݪণ Ұൠࣾஂ๏ਓϦϨʔγϣϯσβΠϯ ݚڀॴදཧࣄ *POJD%FWFMPQFS&YQFSU 4USJQF$PNNVOJUZ&YQFSU
UJQTZT
৯දࣔҹ εϚϗͱϓϦϯλ͚ͩͰ৯දࣔϥ ϕϧΛͭ͘ΕΔຊॳͷઐ༻ΞϓϦ
XJOFDPEF ଟछྨଟྔͷϫΠϯΛෳڌͰཧͰ ͖Δຊ།ҰͷΞϓϦɻ
Ͳ͏ҧ͍·͔͢ʁ ϒϥβ 18" J04ΞϓϦ
8FCඪ४Λϕʔεʹͨ͠ϚϧνϓϥοτϑΥʔϜల։ 888
ຊͱҧ͏͚Ͳɺ࣋ͪؼͬͯ΄͍͜͠ͱ ϞόΠϧ6*Λ࠶ݱ͢ΔͨΊͷ6*ϑϨʔϜϫʔΫ 8FCΞηοτΛϞόΠϧΞϓϦʹ͢ΔϥΠϒϥϦ *POJD'SBNFXPSL $BQBDJUPS
5IFBOTXFS JOBOVUTIFMM JTCFDBVTF UIBU`TXIFSFUIFTBSF 5IFBOTXFS JOBOVUTIFMM JTCFDBVTF UIBU`TXIFSFUIFTBSF ͑؆୯ɻͦ͜ʹϢʔβ͕͍Δ͔ΒͰ͢ɻ IUUQTNFEJVNDPNGSFFDPEFDBNQJCVJMUBQXBBOEQVCMJTIFEJU
JOBQQTUPSFTIFSFTXIBUJMFBSOFEDCGEBGC
$.4ߏங᠘͕͍ͬͺ͍
ιϑτΣΞͷϝϯςφϯε IUUQTFOEP fl JGFEBUF
ϓϥάΠϯͷ࠾༻
όοΫΞοϓͷϝϯςφϯε %#ਧ͖ඈͼ·ͨ͠ɻ ࠷ऴόοΫΞοϓͬͯࡢͰ͢ΑͶʁʂ ઌ݄͔ΒόοΫΞοϓͱΕͯ·ͤΜͰͨ͠ɻ σΟεΫ༰ྔ͕͍ͬͺ͍ͩͬͨΑ͏Ͱ͢ɻ Ͳ͏ͨ͠Β͍͍ΜͰ͔͢ʁʂʁʂ Ͳ͏ʹͳΓ·ͤΜɾɾɾɻ
ΞΫηεूதͨ࣌͠ͷରԠ 8FCαΠτ͕ݟΕͳ͍Μ͚ͩͲͲ͏ͯ͠ʁ ͔ͤͬ͘ςϨϏʹऔΓ্͛ΒΕͨͷʹɻ ΞΫηε͕ूதͯ͠αʔό͕མ͔ͪͨΒͰ͢Ͷɻ མͪண͘·Ͱ͔ͭ͠Ͱ͖ͳ͍Ͱ͢ɻ Ͳ͏ͨ͠Β͍͍ΜͰ͔͢ʁʂʁʂ ͕ͬͭΓαʔόʹ͓͍ۚΕͯ࠶ൃࢭΛʂ
Ϣʔβ͕ϨΠΞτΛյ͢ Ͳ͜Λߋ৽ͨ͠Β͍͍ʁ "ͱ#ͷϑΟʔϧυΛߋ৽͍ͯͩ͘͠͞ɻ $ͷϑΟʔϧυΛߋ৽ͨ͠Β͜ΘΕͨʂ $ͷϑΟʔϧυΛߋ৽͔ͨ͠ΒͰ͢ɻ
ύεϫʔυཧͬͯͪΌΜͱ͞ΕͯΔʁ ύεϫʔυΈΜͳͰಉ͡Ͱ͍͍Ͱ͔͢ʁ ୀ৬͋Δͱࢥ͏ͷͰɺݸਓ୯ҐͰ͓ئ͍͠·͢ Εͯ͠·͏͔ɻᝦʹॻ͍ͯɺ1$ʹ షΓ͚͓ͯ͜͏ 🙈🙉🙊
ϗεςΟϯάྉۚ ֹ݄ Φʔτεέʔϧ 1)1.Z42- /FUMJGZ 0ԁʙ ͋Γ ෆՄ 'JSFCBTF )PTUJOH
0ԁʙ ͋Γ ෆՄ 4ࣾ 425ԁʙ ͳ͠ Մ "ࣾ 20999.70ԁʙ ͳ͠ Մ
Ϣʔβ͕ߋ৽͢ΔࣗࣾαΠτͰɺ$.4ߏஙɻ ͦΕɺඞཁͰ͔͢ʁ
ཧͯ͠ߟ͑Α͏ ͳͥ$.4ߏங͕ඞཁʁ ̍ɽ)5.-Λॻ͚ͳ͍Ϣʔβ͕ߋ৽Ͱ͖ΔΑ͏ʹ͢ΔͨΊ ̎ɽಉҰςϯϓϨʔτͰྔ࢈ͨ͠هࣄΛཧ͢ΔͨΊ ɹɹʢྫɿχϡʔεαΠτʣ ̏ɽ&$αΠτߏஙͳͲෳࡶͳखॱ͕ඞཁͳͷΛखܰʹߏங͢ΔͨΊ
͜Ε(JU)VCͰղܾͰ͖Δʂ
Ϩετϥϯϧϕφτϯ IUUQTHJUIVCDPNMFCFOBUPOCFOBUPOOFU
ίϯηϯτϚʔέοτ IUUQTHJUIVCDPNDPODFOUNBSLFUDPNXFCTJUF
ࢢܦӦϓϩϑΣογϣφϧεΫʔϧ
̍ɽ)5.-Λॻ͚ͳ͍Ϣʔβ͕ߋ৽Ͱ͖ΔΑ͏ʹ͢ΔͨΊ ؆୯ͳϖϥΠνͩͬͨΒɺ͜ͷϨϕϧͰ͍͚Δɻ ఆٳใ͚ͩ$.4Ͱهࣄ࡞ͬͯΔҙٛͱɾɾɾɻ
ϑϨϯνͷΦʔφʔγΣϑ ʮ͜ΕݟͨΒߋ৽Ͱ͖ͨΑʯ
·ͪͮ͘Γձࣾͷελοϑ ʮΩʔࣗମΛؒҧͬͯআͨ͠Βɺࣦഊͨͬͯ͠ϝʔϧ͖ͨʯ
·ͪͮ͘Γձࣾͷελοϑ ॻ͖͙͑Β͍Ͱ͖ΔΑɻ
࣮ྫ̍ɿࣗ࡞ςϯϓϨʔτ <ul class="list-news"></ul> export interface IItem { selector: string; template:
string; data: Array<{ title?: string; ja?: string; price?: string; body?: string; image?: string }>; } export const news: IItem = { selector: '<ul class="list-news"></ul>', template: '<li><label class="form-label">{{ title }}</label><p>{{ body }}</ p></li>', data: [ { title: 'ίϩφײછ༧ରࡦ', body: 'ίϩφײછ༧ରࡦͱͯ͠ɺۭؾͷೖΕସ͑ɺִؒʹ༨༟ͷ͋Δ੮ͷ͝ҊɺΞΫϦ ϧ൘ɺ٬ελοϑͷϚεΫண༻ͳͲͷରԠΛ͓ͯ͠٬༷Λ͓ܴ͍͑ͨ͠·͢ɻ<br>ళɺ৽ܕίϩ φΠϧεରࡦೝূళͰ͢ɻ<br>2࣌ؒఔͰͷ͓৯ࣄΛ͓ئ͍͍ͨ͠·͢ɻ', }, ], }; )5.- 5ZQF4DSJQU
࣮ྫ̍ɿ͜Μͳ/PEFΛ࣮ߦͯ͠#VJME const targets = ['index.html']; const items: IItem[] = [news,
redWine, whiteWine, champagneWine, announcement]; const build = () => { execSync(`rm -r -f ${process.cwd() + '/www'}`); mkdirSync(process.cwd() + '/www'); execSync(`cp -r ${process.cwd() + '/src/template'}/* ${process.cwd() + '/www'}`); for (const templateFile of targets) { let template = readFileSync(process.cwd() + '/www/' + templateFile).toString('utf-8'); for (const item of items) { const insertData: string[] = []; for (const line of item.data) { let template = item.template; for (const [key, value] of Object.entries(line)) { const re_url = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/ gi; const replaceText = (value as string).replace(re_url, '<a href="$1" target="_blank" rel="noreferrer">$1</a>'); template = template.replace(new RegExp(`{{ ${key} }}`, 'g'), replaceText as string); } insertData.push(template); } const changeSelector = item.selector.replace(/></g, `>${insertData.join('')}<`); template = template.replace(item.selector, changeSelector); } writeFileSync(process.cwd() + '/www/' + templateFile, template); } }; build(); createWineSearchIndex(); apiBuild(); 5ZQF4DSJQU
࣮ྫ̎ɿ+BWB4DSJQUϑϨʔϜϫʔΫ <h4> <img src="assets/svg/list.svg" class="svg" decoding="async" /> ͓Βͤ </h4> <ul
class="list-news"> {news.map(d => <li><label class="form-label" innerHTML={d.title}></label><p innerHTML={d.body}></p> </li>)} </ul> +49 ͜Ε͚ͩͰॻ͚ͪΌ͏ɻ؆୯ʂ
ಉҰςϯϓϨʔτͰྔ࢈ͨ͠هࣄΛཧ͢ΔͨΊ ϔουϨε$.4Λͬͯಈతʹσʔλऔಘ͠Α͏ 8PSE1SFTTDPN NJDSP$.4 LJOUPOF
ಉҰςϯϓϨʔτͰྔ࢈ͨ͠هࣄΛཧ͢ΔͨΊ { path: ':id', component: ArticlePage, }, this.route.paramMap.subscribe(as ync (params:
ParamMap) => { this.articleId = parseInt(params.get('id'), 10); const {article} = await this.articleService.getCategory( this.articleId ); this.article = article; }); <article> <h3 [innerHTML]="item.title"></ h3> <p class="attribute"> <ion-note>{{ item.date | date: "yyyyMM݄dd" }}</ion-note> <ion-note *ngIf="item.count"> / {{ item.count }}Point</ion-note> </p> <p class="excerpt" [innerHTML]="item.excerpt"></p> </article>
44(443QSFSFOEFSJPΛͬͯϨϯμϦϯάͰ͖Δ ༰ $43 ϢʔβڥͰHTMLΛϨϯμϦϯά 44( αʔόϗεςΟϯάલʹHTMLΛϨϯμϦϯά 443 ϦΫΤετ࣌ʹHTMLΛϨϯμϦϯά QSFSFOEFSJP ಛఆIP͔ΒͷϦΫΤετ͚࣌ͩɺαʔό͕ϨϯμϦ
ϯάࡁΈHTMLΛฦ٫
ߏ͕͍͠ͷγϯϓϧʹͭ͘ΕΔ
$%/Λͬͨ৴͕༰қʹͳΓߴʹ
ٕज़ͷ՝ٕज़Ͱղܾ͠Α͏ ಈతݴޠ͕ΔαʔόͷόοΫΞοϓαʔόෛՙͷίϯτ ϩʔϧηΩϡϦςΟϢʔβ͕յͨ͠ΒͲ͏͠Α͏FUD ϦεΫϚωʔδϝϯτ͠ͳ͕Β$.4ߏங͋Γ͚ͩͲɺ੩తαΠ τԽ͢Δ͜ͱͰ͜ΕΒͷΛΓӽ͑ΕΔՄೳੑ͕͋ΔͷͰҰ ߟ͑ͯΈ·ͤΜ͔ɻ 8FCΞηοτΛ৴͢Δ͚ͩͷͨΊʹɺຊʹඞཁʁ
ઌͷ͜ͱΛߟ͑Α͏ ʢ8FCαΠτ͕΄͍͠Ͱ͢ɻޙ͓ళ͕ ɹͲ͏ͳͬͯΔ͔Θ͔Βͳ͍ʣ ʢೲͨ͠ΒऴΘΓɻϝϯςܖͱΕΔͱخ͍͠ʣ ͓ؒئ͍͢Δ͜ͱͳ͔͔ͬͨΒ ϝϯςܖͷܧଓΊ͓ͯ͜͏ ʢܖऴΘΓͳͷͰɺҰࣜͯ͠ऴΘΓ·͢Ͷʣ