肆術 發表於 2020-5-31 22:07:00

基于 Next.js 和云开发 CMS 的内容型网站应用实战开发

<p><strong>作者简介</strong>:</p>
<p>董沅鑫,云开发 CloudBase 团队研发工程师,侧重于前端工程化、node 服务开发,业余时间出没在 xin-tan.com。</p>
<p><strong>本文目录</strong>:</p>
<ul>
<li>引言</li>
<li>总览</li>
<li>背景介绍</li>
<li>安装 CMS</li>
<li>使用 CMS 创建动态内容</li>
<li>项目搭建</li>
<li>获取 CMS 内容</li>
<li>自动构建与部署</li>
<li>最后</li>
</ul>
<h2 id="引言">引言</h2>
<p>随着腾讯云云开发能力的日渐完善,有经验的工程师已经可以独立完成一个产品的开发和上线。<strong>但网上云开发相关的实战文章非常少,很多开发者清楚云开发的能力,但是不清楚如何在现有的开发体系下引入云开发</strong>。</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gez0z9axp8j31e10u0b2a.jpg"></p>
<p>本文从云开发团队开发者+能力使用者的角度,以云开发官网 (http://cloudbase.net/) 的搭建思路为例,分享云开发结合流行框架与工具的实战经验。</p>
<p><strong>涉及到的知识点有</strong>:</p>
<ul>
<li>云开发:
<ul>
<li>扩展能力(CMS 扩展)</li>
<li>静态托管</li>
<li>云数据库</li>
<li>CloudBase CLI 工具</li>
</ul>
</li>
<li>React 框架:Next.js</li>
<li>CI 自动构建</li>
</ul>
<h2 id="总览">总览</h2>
<p><strong>系统设计图</strong>:</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gf5xg2rlggj31t00o8q6n.jpg"></p>
<h2 id="背景介绍">背景介绍</h2>
<p>随着云开发团队业务的迅猛发展,团队需要一个官网来更直观、更即时地向开发者们展示云开发的相关能力,包括但不限于工具链、SDK、技术文档等。</p>
<p>同时,为了降低开发者的上手成本,积累业界的优秀实战经验,官网也承载着营造社区氛围、聚合重要资料、增强用户黏度的重要任务。</p>
<p>我们最初使用 VuePress 作为静态网站工具,遇到了一些痛点:</p>
<ul>
<li><strong>问题 1: 每次更新内容,都需要配合 git。运营同学对 git 不熟悉</strong></li>
<li><strong>问题 2: 学习资料方面的内容更新过于频繁,“污染”了 git 记录</strong></li>
<li><strong>问题 3: 内容和网站代码耦合</strong></li>
<li><strong>问题 4: 缺少可视化的内容编辑工具</strong></li>
</ul>
<p>我们使用「CMS 扩展」、「云开发基础能力」、「Next.js」、「CI 工具」,很好地解决了以上问题。在实现网站内容动态化的同时,保证了 SEO,运营同学也可以通过 CMS 对内容进行可视化管理。</p>
<h2 id="安装-cms">安装 CMS</h2>
<p>进入云开发扩展能力控制台,根据引导,安装 CMS 内容管理系统。</p>
<p>在进行扩展程序配置的时候,有两种账号:管理员账号和运营者账号。管理员账号权限更高,可以创建新的数据集合;而运营者账号只能在已有的数据集合上进行增删改的操作。</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gezbi2twy0j31gl0u041d.jpg"></p>
<blockquote>
<p><strong>注意:</strong></p>
<p>安装时间有些长,请耐心等待</p>
</blockquote>
<p>安装成功后,云数据库会自动创建 3 个集合,分别是 <code>tcb-ext-cms-contents</code>、<code>tcb-ext-cms-users</code>、<code>tcb-ext-cms-webhooks</code>,存放 CMS 系统配置信息以及内容数据。会自动创建 3 个云函数,分别是 <code>tcb-ext-cms-api</code>、<code>tcb-ext-cms-init</code>、<code>tcb-ext-cms-auth</code>,封装了初始化、身份验证以及数据流的相关逻辑。</p>
<p>进入「静态网站托管」,可以看到 CMS 系统的静态文件已经自动部署到<code>tcb-cms/</code>目录下了:</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gezbunf926j31mt0u0afk.jpg"></p>
<p>点击上方的「基础配置」,就可以查看到域名信息。</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gezbvpy0fpj31a70u0dnt.jpg"></p>
<p>在浏览器中访问对应链接(http://pagecounter-d27cfe-1255463368.tcloudbaseapp.com/tcb-cms/)即可看到 CMS 系统:</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gezbxipje4j31oi0tokge.jpg"></p>
<p>到此为止,无任何开发成本,一个 CMS 内容管理系统就正式上线了~</p>
<h2 id="使用-cms-创建动态内容">使用 CMS 创建动态内容</h2>
<p>对于动态化的数据内容,我们将其划分为不同的模块。每个内容模块,对应 CMS 系统的一个数据集合。例如「云开发官网」-「社区页」中,推荐好课的内容就是动态的。</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gezc29itjnj31e10u0kjl.jpg"></p>
<p>从图中可以看到,每节课程有着多个属性。而在云数据库中,每节课程就对应一个文档,课程属性就对应文档的字段。字段类型与含义如下:</p>
<pre><code>name&lt;string&gt;: 课程名称
time&lt;number&gt;: 课程时间
cover&lt;string&gt;: 课程封面
url&lt;string&gt;: 课程链接
level&lt;0 | 1 | 2&gt;: 课程难度
</code></pre>
<p>以管理员身份登录 CMS 系统,在「内容设置页」新建内容。在 CMS 中,支持多种高级数据类型,例如 url、图片、markdown、富文本、标签数组、邮箱、网址等,并对这些类型进行了智能识别和更友好地展示。</p>
<blockquote>
<p><strong>注意:</strong></p>
<p>CMS 自带图床功能。当数据类型是「图片」时,图片会自动上传到当前云开发环境下的云存储中。图片信息以 <code>cloud://</code> 开头的特殊链接,存放在数据集合中。</p>
</blockquote>
<p>新建内容时,默认情况下,CMS 会自动填充 4 个字段:name、order、createTime、updateTime。可以根据自身需要,对不需要的字段进行删除。</p>
<blockquote>
<p><strong>建议:</strong></p>
<p>保留 order 字段,它可以被用作数据排序。对运营者来说,数据的 order 的值越大,在 CMS 系统中展示的位置越靠前;对开发者来说,可以根据 order 来进行排序搜索。从而保证了体验和逻辑的一致性。</p>
</blockquote>
<p>根据字段创建集合后,CMS 系统左侧会看到「推荐好课」。它对应的内容被保存在云数据库的<code>recommend-course</code>(创建时指定)集合中,它的字段信息保存在云数据库的<code>tcb-ext-cms-contents</code>(CMS 初始化时创建)集合中。</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gezcvlw9b4j312b0u0gu1.jpg"></p>
<p>按照设定添加新的课程内容后,再次进入「推荐好课」,如下所示:</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gezcwwgnb0j322c0tk44l.jpg"></p>
<p>图片、链接等内容,更友好地展示给运营者。</p>
<h2 id="项目搭建">项目搭建</h2>
<p>按照 Next.js Docs 的指引,创建 Next.js 项目:</p>
<pre><code>npm i --save next react react-dom axios
</code></pre>
<p>因为我们要将网站部署到「静态托管」上,所以要使用 Next.js 的<strong>静态导出</strong>功能。<code>package.json</code> 中的打包脚本更新为:</p>
<pre><code class="language-json">"scripts": {
    "dev": "next",
    "build": "next build &amp;&amp; next export",
    "start": "next start"
}
</code></pre>
<p>为了快速部署静态网站,以及发布云函数。需要全局安装 <code>@cloudbase/cli</code>:</p>
<pre><code>npm install -g @cloudbase/cli
</code></pre>
<p>安装后,添加两个脚本:</p>
<ul>
<li><code>deploy:hosting</code>: 将 Next.js 的静态导出文件部署到「静态托管」</li>
<li><code>deploy:function</code>: 发布项目中的云函数</li>
</ul>
<pre><code class="language-json">"scripts": {
    "deploy:hosting": "npm run build &amp;&amp; cloudbase hosting:deploy out -e jhgjj-0ae4a1",
    "deploy:function": "echo y | cloudbase functions:deploy --force"
}
</code></pre>
<blockquote>
<p><strong>注意:</strong></p>
<p>准备两个云环境,防止静态部署时文件覆盖。envId 为 <code>jhgjj-0ae4a1</code> 的云环境只用于部署 Next.js 的静态导出文件。envId 为 <code>pagecounter-d27cfe</code> 的云环境用来部署 CMS 系统。</p>
</blockquote>
<h2 id="获取-cms-内容">获取 CMS 内容</h2>
<p>配合 CloudBase 的 Node 端 SDK-<code>@cloudbase/node-sdk</code>,我们可以在 Next.js 的 <code>getStaticProps()</code> 方法中读取到云数据库中的数据。</p>
<p>为了使逻辑更清晰,我们将获取外部数据的方法统一封装到单独文件中。以获取「推荐课程」为例:</p>
<pre><code class="language-javascript">// provider.js

const cloudbase = require("@cloudbase/node-sdk");
const config = {
    secretId: "your secretId", // 前往「腾讯云控制台」-「访问密钥」获取
    secretKey: "your secretKey", // 前往「腾讯云控制台」-「访问密钥」获取
    env: "your envid" // 前往「腾讯云控制台」-「云开发 CloudBase」获取
};

const app = cloudbase.init(config);

/**
* 获取云数据库数据
*/
async function getCourses() {
    const db = app.database();
    const result = await db.collection("recommend-course").get();
    if (result.code) {
      throw new Error(
            `获取「推荐课程」失败, 错误码是${result.code}: ${result.message}`
      );
    }

    return result.data.map(item =&gt; {
      if (item.createTime instanceof Date) {
            item.createTime = item.createTime.toLocaleString();
      }
      if (item.updateTime instanceof Date) {
            item.updateTime = item.updateTime.toLocaleString();
      }
      item.cover = getBucketUrl(item.cover); // 处理云存储的特殊链接
      return item;
    });
}
</code></pre>
<p>前文有讲到,CMS 自带图床功能,拖拽上传的图片会被存储在同一环境下的云存储中,并且获取图片的链接存放在集合中。<strong>云存储的链接是以 <code>cloud://</code> 开头的特殊链接,需要在前端进行识别和特殊处理</strong>。</p>
<p>举个 🌰,图片的存储链接是:<code>cloud://pagecounter-d27cfe.7061-pagecounter-d27cfe-1255463368/uploads/1589990230404.png</code>。将其转成可访问的 http 链接:<code>https://7061-pagecounter-d27cfe-1255463368.tcb.qcloud.la/uploads/1589990230404.png</code>。</p>
<p>转换思路是:识别 envid 后面的信息,将其与<code>tcb.qcloud.la</code>域名重新拼接即可:</p>
<pre><code class="language-javascript">// provider.js

/**
* 获取云存储的访问链接
* @param {String} url 云存储的特定url
*/
function getBucketUrl(url) {
    if (!url.startsWith("cloud://")) {
      return url;
    }

    const re = /cloud:\/\/.*?\.(.*?)\/(.*)/;
    const result = re.exec(url);
    return `https://${result}.tcb.qcloud.la/${result}`;
}
</code></pre>
<blockquote>
<p><strong>注意</strong>:</p>
<p>云存储的「权限设置」应为:所有用户可读,仅创建者及管理员可写。否则链接无法访问。</p>
</blockquote>
<blockquote>
<p><strong>推荐</strong>:</p>
<p>除了自带的图床功能,开发者可以根据自身需求使用其他稳定图床服务,例如微博图床。如果使用其他图床,对应字段类型不能设置为「图片」,可以是「字符串」或者「超链接」。</p>
</blockquote>
<p>目前为止,我们使用 SDK 获取了云数据库数据,剩下要做的就是将其注入到 Next.js 页面组件的 <code>props</code> 上:</p>
<pre><code class="language-javascript">// pages/index.js

const HomePage = ({ courses }) =&gt; {
    return (
      // 尽情使用数据吧...
    )
}

export async function getStaticProps() {
    const { getCourses } = require('./../provider')
    return {
      props: {
            courses: await getCourses()
      }
    }
}

export default HomePage
</code></pre>
<p>打开浏览器,进入 http://localhost:3000/ ,可以看到效果如下:</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gf006o852jj319d0u0guf.jpg"></p>
<p>进入 view-source:http://localhost:3000/ ,可以看到网页的 html 源码中包含了课程数据,解决了 SEO 的问题:</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gf007i7i7hj32la0goaq2.jpg"></p>
<blockquote>
<p><strong>注意:</strong></p>
<p>Next.js 的一些方法是双端都会运行的,但 <code>getStaticProps()</code> 只会在 server 端运行</p>
</blockquote>
<h2 id="自动构建与部署">自动构建与部署</h2>
<p>目前为止,开发工作基本结束。执行 <code>npm run build</code> 命令,网站静态文件被打包到了 <code>out/</code> 目录下:</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gf00fkl5j1j30m80ucdj0.jpg"></p>
<p>执行 <code>npm run deploy:hosting</code> 将 <code>out/</code> 目录下的文件上传到「静态网站托管」。访问静态网站托管的链接:https://jhgjj-0ae4a1.tcloudbaseapp.com/ ,效果如下:</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/007S8ZIlgy1gf00jcjxjsj31o90u0wsy.jpg"></p>
<p>借助成熟的 CI 工具,例如 Travis、Circle 等,可以定时触发构建工作。如此一来,内容和开发彻底分离。</p>
<p>在构建发布的时候,需要用到 CloudBase CLI 工具。在 CI 工具中,不再使用 <code>cloudbase login</code> 进行交互式输入登录,而是使用密钥登录: <code>cloudbase login --apiKeyId $TCB_SECRET_ID --apiKey $TCB_SECRET_KEY</code> 。</p>
<blockquote>
<p><strong>注意:</strong></p>
<p>前往 云 API 密钥 获得 <code>TCB_SECRET_ID</code> 和 <code>TCB_SECRET_KEY</code> 的值</p>
</blockquote>
<p>在 CI 工具的控制台中,配置 <code>TCB_SECRET_ID</code> 和 <code>TCB_SECRET_KEY</code>。并为<code>package.json</code>新添加一个脚本:</p>
<pre><code class="language-json">"scripts": {
    "login": "echo N | cloudbase login --apiKeyId $TCB_SECRET_ID --apiKey $TCB_SECRET_KEY"
}
</code></pre>
<p>总结来说,CI 构建的流程是:</p>
<ul>
<li>tcb 密钥登录:<code>npm run login</code></li>
<li>获取最新数据,导出静态文件:<code>npm run build</code></li>
<li>发布到「静态网站托管」:<code>npm run deploy:function</code></li>
</ul>
<p>如果数据需要紧急修改上线,可以在本地或者 CI 工具控制台,手动触发构建。</p>
<h2 id="最后">最后</h2>
<p>借助云开发 CMS,可以实现评论系统、预约系统、发布博客等各式各样的内容模板,从而快速搭建网站。在现有开发体系下,合理运用云开发,使得人力成本、开发成本以及运维成本大幅度降低。真正实现前后端一把梭,构成“闭环”。</p>
<p>本文实战仅是抛砖引玉,涉及了云开发能力的一部分,还有更多好玩的东西等待你的探索,比如使用云函数实现 SSR、托管后端服务、图像服务、各端 SDK 等。</p>
<p><strong>探索能力,发散思路,以更低成本开发高可用的 web 服务,云开发绝对是你最好的选择!</strong></p>
<p><strong>更多资料</strong>:</p>
<ul>
<li>云开发社区官网</li>
<li>CMS 内容管理系统</li>
</ul>
<p>公众号:腾讯云云开发</p>
<p>腾讯云云开发:https://cloudbase.net</p>
<p>云开发控制台:https://console.cloud.tencent.com/tcb?from=12304</p>
<p>☁<br>
更多精彩<br>
扫描二维码了解更多</p>
<p><img src="https://wyd-1301665037.cos.ap-guangzhou.myqcloud.com/640-20200428110734710.jpeg"></p><br><br>
来源:https://www.cnblogs.com/CloudBase/p/13021911.html
頁: [1]
查看完整版本: 基于 Next.js 和云开发 CMS 的内容型网站应用实战开发