---
# System prepended metadata

title: Content Mange System Spike
tags: [cms]

---

---
tags: [cms]
---
# Content Mange System Spike

## Agenda
* CMS 是什麼？什麼是無頭CMS？ 差異
* 無頭CMS的優勢和劣勢
* 第三方服務比較
* Angular 資料接介實作

---    

## CMS 是什麼？什麼是無頭CMS？ 差異


> Headless CMS 即: 這是一個CMS（內容管理系統），少了Head（對網站的外觀和感覺的控制）! 是的，這是 Headless 概念中最難理解的事情!
在傳統的 CMS 中，前端（頭部）和後端是一體的。 它是通過將 HTML 這一前端技術納入伺服器端程式來實現的。 因此你可以同時處理網站的外觀和圖片等內容。而相反地 - 無頭 CMS 則是將前端（頭部）與 CMS 分開，並通過 API 將後端管理的內容傳遞給每個設備。 前端（Head）是為每個設備創建的。 與基於網路的傳統 CMS 不同，你可以在每個設備上自由的控制內容到你想要的裝置上做不同的呈現。


![](https://i.imgur.com/LV0oyFG.png)

在傳統的 CMS 中，前端（頭部）和後端是一體的。 它是通過將 **HTML 這一前端技術納入伺服器端程式來實現的。** 因此你可以同時處理網站的外觀和圖片等內容。而相反地 - 無頭 CMS 則是將前端（頭部）與 CMS 分開，並**通過 API 將後端管理的內容傳遞給每個設備**。 前端（Head）是為每個設備創建的。 與基於網路的傳統 CMS 不同，你可以在每個設備上自由的控制內容到你想要的裝置上做不同的呈現。




## 無頭CMS的優勢和劣勢
**優點:**
1. 更大的覆蓋面（網站、手機 App、戶外看板、Kiosk、電腦應用程式、可穿戴設備、語音助理、物聯網設備等）
2. 為每個設備優化用戶體驗
3. 通過分離前端和後端開發，提高開發效率 (我相信在任何一個有好的工程師文化的團隊都會喜愛 Headless 用於網站開發上的節奏)
4. 由於前端和後端開發的分離，不容易受到網路攻擊的影響

**缺點:**
1. 需要更廣泛的網頁開發知識（HTML和其他前端知識）來創建頁面。以我們的經驗的話，通常開發者建議為全端 Full Stack 團隊會比較得心應手。
2. 前端工程師也需要熟悉全 API 的工作流程
3. <a style="color:red">你不能預覽或編輯你所看到的頁面（你需要找到輔助工具幫助你預覽開發內容於多平台）。</a>


## 第三方服務比較

> 參考文章[最受歡迎的 headless CMS 最受歡迎的 Headless CMS 介紹](https://tenten.co/learning/headless-cms-collections/amp/)，透過此文章中的提到的 headless 來分析較為適合 tdc 所要用的第三方服務。

### [cosmicjs](https://www.cosmicjs.com/)
**優點：**
1. 價格相對平價

**缺點：**

1. 編輯畫面相對較簡陋
2. 沒有留下 comment 的功能
3. 無法直接在服務中直接 preview page


### [contentful](https://www.contentful.com/)
**優點：**

1. 有較多的分析 request 畫面 & 團隊管理畫面
2. 有 tags 管理功能
3. 可留下 comment 的功能

**缺點：**

1. 價格較貴
2. 無法直接在服務中直接 preview page


### [storyblok](https://www.storyblok.com/)

**優點：**

1. 可連接 s3 bucket，等等一盤 app (publish release automatically with scheduling … etc)
2. 編輯時可直接 preview 未來網站的畫面
3. 有 tags 管理功能
4. 可留下 comment 的功能
5. storyblok 內部文章轉跳
6. 有 table 的 edit

**缺點：**

1. 沒有 json 的編輯器



## Angular 資料接介實作


[Storyblok and Angular 13 in 5 min (more or less 😉 ) ](https://www.storyblok.com/tp/add-a-headless-cms-to-angular-in-5-minutes#let%E2%80%99s-start-setting-up-our-angular-environment)

會用到的 npm 

``` bash
npm install storyblok-js-client # 用來打 storybloc api 用

npm install ng-dynamic-component --save # 用來插拔 component 用的
```
:::info
ng-dynamic-component  的功能有一點點像 vue 的 `<component :is ></component>`
:::


### npm install storyblok-js-client 用法
建立 service 用來特別打 storyblok 的 api services

```javascript
import Client from 'storyblok-js-client';
import { Injectable } from '@angular/core';

@Injectable()
export class StoryblokService {
    private sbClient = new Client({
        accessToken: 'YOU_TOKEN', // Add your token here
        https: true,
    });

    constructor() {}

    getStory(slug: string, params?: object): Promise<any> {
        return this.sbClient.getStory(slug, params).then((res) => res.data);
    }

    getStories(params?: object): Promise<any> {
        return this.sbClient.getStories(params).then((res) => res.data);
    }
}
```

### ng-dynamic-component 用法
```

├── components
    ├── cms
        ├── banner
        ├── grid        // 多語系檔案
        └── cms-component.ts
```

用一個 cms-component.ts 的檔案管理所有會用到的component

```javascript
// cms-component.ts

import { BannerComponent } from './feature/banner.component';
import { GridComponent } from './grid/grid.component';

let Components = {
    banner: BannerComponent,
    grid: GridComponent,
};

export { Components };
```

CMS 的 page html 把 ndc-dynamic 的套件引入

```html
<div class="root">
    <div *ngIf="story">
        <ndc-dynamic [ndcDynamicComponent]="components['teaser']" [ndcDynamicInputs]="story.content"> </ndc-dynamic>
    </div>
</div>

<!-- ndcDynamicComponent 插拔 component 的開關 -->
<!-- ndcDynamicInputs 傳入的資料內容 -->
```

### 實作的概念
從不同的 url 打去 storyblok 拿到不同的資料。

```javascript
const url = 'cms' 
this.storyblokService.getStory(url, { version: 'draft' }).then((data) => {
    this.story = data.story;
    console.log('story => ', this.story.content);
});
```

取得到的 content 會把資料送入到 component 中，會有一個統一的入口，此入口會轉到不同的 component 的中，在 component 中作畫面的 render


cms-component.ts // 這個檔案作為一個中心的管理
所引用的 component 的名稱，應該要和要 storyblok 的 命名一樣 ( 或是要做一個轉接層把東西轉調 )。







參考資料

https://www.letswrite.tw/postmessage/
https://tenten.co/learning/headless-cms-insight/
https://blog.huli.tw/2022/04/07/iframe-and-window-open/

