angular 启动服务器_如何构建无服务器CMS驱动的Angular应用

angular 启动服务器

by Jake Lumetta

杰克·卢米塔(Jake Lumetta)

如何构建无服务器CMS驱动的Angular应用 (How to build a serverless CMS-powered Angular app)

This tutorial is a follow-up to my previous tutorial on how to build a serverless CMS-powered Vue.js application, and shows you how to build a serverless CMS-powered Angular app.

本教程是我之前的教程的后续内容,该教程是关于如何构建无服务器CMS驱动的Vue.js应用程序的,并向您展示了如何构建无服务器CMS驱动的Angular应用程序。

Angular, developed and maintained by Google engineers, has found a place across dynamic web applications and is an increasingly in-demand language. It’s a robust and comprehensive language for front-end development that is unit-testing ready, making it the language of choice for many developers. Angular simplifies the front-end development experience by extending HTML’s syntax to allow you to quickly create content management capability.

由Google工程师开发和维护的Angular已在动态Web应用程序中找到了一席之地,并且是一种越来越受欢迎的语言。 它是用于前端开发的健壮且全面的语言,并且可以进行单元测试,从而成为许多开发人员的首选语言。 Angular扩展了HTML的语法,从而使您可以快速创建内容管理功能,从而简化了前端开发体验。

Because of Angular’s simplicity, developers are increasingly taking advantage of it to add CMS capability to websites.

由于Angular的简单性,开发人员越来越多地利用它来为网站添加CMS功能。

For Wordpress users, one popular way to integrate content management capability is to work with the wp-api-angular library that allows you to interact with the Wordpress API and Angular applications. If you’re using Wordpress as a CMS platform, using Angular and the Wordpress API can decrease load times for content on your page.

对于Wordpress用户,一种集成内容管理功能的流行方法是使用wp-api-angular库,该库允许您与Wordpress API和Angular应用程序进行交互。 如果您将Wordpress用作CMS平台,则使用Angular和Wordpress API可以减少页面上内容的加载时间。

For those not using Wordpress, there’s a new breed of API-based CMSs that greatly simplify things. We’ll discuss one example here.

对于不使用Wordpress的用户,有一种新的基于API的CMS可大大简化操作。 我们将在这里讨论一个示例。

In this article, we’ll use ButterCMS as an alternative to Wordpress and an example of a SaaS-based headless CMS that provides a hosted CMS dashboard and content API that you query from your Angular application. This means you don’t need to spin up any new infrastructure to add CMS to your Angular app.

在本文中,我们将使用ButterCMS替代Wordpress,并使用基于SaaS的无头CMS的示例,该示例提供托管的CMS仪表板和可从Angular应用程序中查询的内容API。 这意味着您无需启动任何新的基础架构即可将CMS添加到Angular应用中。

This tutorial will demonstrate how to build a CMS-powered Angular application that has marketing pages (customer case studies), a blog, and FAQ, all powered via API. No servers needed!

本教程将演示如何构建由CMS驱动的Angular应用程序,该应用程序具有通过API提供支持的营销页面(客户案例研究),博客和常见问题解答。 无需服务器!

安装 (Installation)

First, you’ll get started by installing the Angular cli.

首先,您将开始安装Angular cli。

npm install -g @angular/cli

Setup a new Angular project using Angular cli. By default, angular-cli uses CSS style, so adding the —-style=scss flag tells Angular CLI to use SCSS instead.

使用Angular cli设置一个新的Angular项目。 默认情况下,angular-cli使用CSS样式,因此添加—-style=scss标志可—-style=scss Angular CLI改用SCSS。

ng new hello-buttercms-project --style=scsscd hello-buttercms-project

Install Angular Material and Angular Material related packages.

安装Angular Material和Angular Material相关的软件包。

npm install --save @angular/material @angular/cdknpm install --save @angular/animations

Install ButterCMS. Run this in your command line:

安装ButterCMS。 在命令行中运行:

npm install buttercms --save

Butter can also be loaded using a CDN:

也可以使用CDN加载黄油:

<script src="https://cdnjs.buttercms.com/buttercms-1.1.1.min.js"></script>

快速上手 (Quickly get started)

Open the project in your code editor of choice. Under src/app, create a directory called _services

在您选择的代码编辑器中打开项目。 在src / app下,创建一个名为_services的目录

We’ll create a file called butterCMS.service.js. This allows you to have your API Token in one place and not accidentally alter it.

我们将创建一个名为butterCMS.service.js的文件。 这使您可以将API令牌放在一个位置,而不会意外更改它。

import * as Butter from 'buttercms';
export const butterService = Butter('b60a008584313ed21803780bc9208557b3b49fbb');

You’ll import this file into any component where you want to use ButterCMS.

您可以将此文件导入到要使用ButterCMS的任何组件中。

For a Quickstart, go to src/app/hello-you/hello-you.component.ts and import butterService

对于快速入门,请转到src/app/hello-you/hello-you.component.ts并导入butterService

import {butterService} from '../_services';

Inside the HelloYouComponent, create methods:

HelloYouComponent内部,创建方法:

fetchPosts() {  butter.post.list({    page: 1,    page_size: 10  })  .then((res) => {    console.log(‘Content from ButterCMS’)    console.log(res)  })}

Now call this method when the component is loaded by adding it to the OnInit lifecycle hook:

现在,通过将组件添加到OnInit生命周期挂钩中来在加载组件时调用此方法:

ngOnInit() {  this.fetchPosts();}

This API request fetches a sample blog post. Your account comes with one example post which you’ll see in the response. If you get a response, it means you’re now able to connect to the API.

此API请求将获取样本博客文章。 您的帐户附带一个示例帖子,您将在回复中看到该示例帖子。 如果收到响应,则意味着您现在可以连接到API。

添加营销页面 (Add marketing pages)

Setting up CMS-powered Pages is a three-step process:

设置CMS支持的页面分为三个步骤:

  1. Define the Page Type

    定义页面类型
  2. Create a page

    创建一个页面
  3. Integrate into your applicaton

    集成到您的应用程序中
定义页面 (Define Page)

First, create a Page Type to represent your Customer Case Study pages. Next, define the fields you want for your customer case studies. With your Page Type defined, you can now create the first case study page. Specify the name and URL of the page, and then populate the content of the page.

首先,创建一个页面类型来表示您的客户案例研究页面。 接下来,定义客户案例研究所需的字段。 定义页面类型后,您现在可以创建第一个案例研究页面。 指定页面的名称和URL,然后填充页面的内容。

With your page defined, the ButterCMS API will return it in JSON format like this:

定义页面后,ButterCMS API将以JSON格式返回它,如下所示:

{    "data": {      "slug": "acme-co",      "fields": {        "facebook_open_graph_title": "Acme Co loves ButterCMS",        "seo_title": "Acme Co Customer Case Study",        "headline": "Acme Co saved 200% on Anvil costs with ButterCMS",        "testimonial": "<p>We’ve been able to make anvils faster than ever before! — <em>Chief Anvil Maker</em></p>\r\n<p><img src=\"https://cdn.buttercms.com/NiA3IIP3Ssurz5eNJ15a\" alt=\"\" caption=\"false\" width=\"249\" height=\"249\" /></p>",        "customer_logo": "https://cdn.buttercms.com/c8oSTGcwQDC5I58km5WV",        }     }  }

This guide uses the Angular framework and Angular CLI to generate all the components and package our application.

本指南使用Angular框架和Angular CLI生成所有组件并打包我们的应用程序。

Let’s get to the code.

让我们看一下代码。

建立新专案 (Create new project)
ng new buttercms-project --style=scsscd buttercms-projectnpm install --save @angular/material @angular/cdknpm install --save @angular/animationsnpm install -S buttercmsng serve

Your localhost:4200 should be ready to serve your Angular page.

您的localhost:4200应该已经准备好服务您的Angular页面了。

创建打字稿以导出ButterCMS服务 (Create typescript to export ButterCMS service)

Under src/app create a directory called _services. Create a file called butterCMS.service.js.

src/app创建一个名为_services的目录。 创建一个名为butterCMS.service.js的文件。

import * as Butter from 'buttercms';export const butterService = Butter('your_api_token');
更新组件路线 (Update the component routes)

These components are generated by Angular CLI using:

这些组件由Angular CLI使用以下命令生成:

ng g component <my-new-component>

ng g component <my-new-compone nt>

Under src/app create a file called app-routing.module.ts

src/app创建一个名为app-routing.module.ts的文件

import {NgModule} from '@angular/core';import {RouterModule, Routes} from '@angular/router';import {CustomerComponent} from './customer/listing/customer.listing.component';import {FaqComponent} from './faq/faq.component';import {BlogPostComponent} from './blog-post/listing/blog-post.component';import {HomeComponent} from './home/home.component';import {CustomerDetailsComponent} from './customer/details/customer.details.component';import {BlogPostDetailsComponent} from './blog-post/details/blog-post.details.component';import {FeedComponent} from './feed/feed.component';import {HelloYouComponent} from './hello-you/hello-you.component';
const appRoutes: Routes = [    {path: 'customer', component: CustomerComponent},    {path: 'customer/:slug', component: CustomerDetailsComponent},    {path: 'faq', component: FaqComponent},    {path: 'blog', component: BlogPostComponent},    {path: 'blog/:slug', component: BlogPostDetailsComponent},    {path: 'rss', component: FeedComponent},    {path: 'hello-you', component: HelloYouComponent},    {path: 'home', component: HomeComponent},    {path: '**', redirectTo: 'home'}];
@NgModule({    imports: [RouterModule.forRoot(appRoutes)],    exports: [RouterModule]})export class AppRoutingModule {}

设置客户列表页面 (Set up the Customer List page)

Under apps/customer type: ng g component

apps/customer类型下: ng g component

In the file apps/customer/listing/customer.listing.component.ts :

在文件apps/customer/listing/customer.listing.component.ts

  1. Import butterService

    进口butterService

  2. In OnInit hook, use butterService to get the list of customers

    OnInit挂钩中,使用butterService获取客户列表

  3. Store results in pages variable and markup (HTML) will be updated with the data

    将结果存储在页面变量中,标记(HTML)将与数据一起更新
import {Component, OnInit} from '@angular/core';import {butterService} from '../../_services';
@Component({    selector: 'app-customer',    templateUrl: './customer.listing.component.html',    styleUrls: ['./customer.listing.component.scss']})
export class CustomerComponent implements OnInit {  public pages: any[];  constructor() { }
ngOnInit() {  butterService.page.list(‘customer_case_study’)    .then((res) => {      this.pages = res.data.data;  }); }}

Display the results in customer.listing.component.html

customer.listing.component.html显示结果

&lt;mat-card&gt;  <mat-card-title class="page-title">;Customers</mat-card-title&gt;  <mat-divider></mat-divider>  <mat-card-content class="page-body">    <mat-card *ngFor="let page of pages">      <mat-card-title&gt;        <div class="container">          <a [routerLink]="[page.slug]">            <div fxLayout="row" fxLayout.xs="column"                 fxFlex class="content">            <div class="blocks">              <img src="{{page.fields.customer_logo}}" alt="{{page.fields.seotitle}}" height="64" width="64"/>            </div>            <div class="blocks"&gt;              {{page.fields.headline}}            </div>          </div>        &lt;/a>      </div>    </mat-card-title>  </mat-card></mat-card-content>&lt;mat-divider></mat-divider><mat-card-footer>  <div class="page-footer">    <mat-icon>whatshot</mat-icon>  </div></mat-card-footer></mat-card>

设置客户详细信息页面 (Set up the Customer Detail page)

Under apps/customer, type ng g component details .

apps/customer ,输入ng g component details

apps/customer/details/customer.details.component.ts
创建客户页面 (Create customer page)
  1. Import butterService

    进口butterService

  2. In OnInit hook, use butterService to get the customer page given the slug in the URL path

    OnInit挂钩中,使用butterService来获取URL路径中给出的段的客户页面

  3. Store results in page variable and markup (HTML) will be updated with the customer data

    将结果存储在页面变量中,标记(HTML)将与客户数据一起更新
import {Component, OnInit} from '@angular/core';import {Observable} from 'rxjs/Observable';import {ActivatedRoute} from '@angular/router';import {butterService} from '../../_services';import {map, take} from 'rxjs/operators';
@Component({  selector: 'app-customer-details',  templateUrl: './customer.details.component.html',  styleUrls: ['./customer.details.component.scss']})
export class CustomerDetailsComponent implements OnInit {  constructor(protected route: ActivatedRoute) { }
protected slug$: Observable<string>;  public page: any;
ngOnInit() {    this.slug$ = this.route.paramMap    .pipe(      map(params => (params.get('slug')))   );
this.slug$.pipe(      take(1))        .subscribe(slug => {          butterService.page.retrieve('customer_case_study', slug)            .then((res) => {              this.page = res.data.data;            }).catch((res) => {            console.log(res);          });        });      }    }

Display the results in customer.details.component.html

customer.details.component.html显示结果

&lt;mat-card&gt;  <div class="container"&gt;    <div fxLayout="column" class="details">      <div class="blocks">        <img src="{{page.fields.customer_logo}}" alt="" height="124" width="124"/>      </div>
&lt;h1 class="blocks">        {{page.fields.headline}}      </h1&gt;      <h3 class="is-size-3"&gt;Testimonials</h3>      <div [innerHTML]="page.fields.testimonial"></div>      &lt;div [innerHTML]="page.fields.body"></div>    </div>  </div></mat-card>

You can now navigate to the Customer Page via the list of all Customer Pages or directly via URL.

现在,您可以通过所有“客户页面”列表或直接通过URL导航到“客户页面”。

添加知识库 (Add a knowledge base)

设置内容字段 (Set up content fields)

Let’s suppose you want to add a CMS to a static FAQ page with a title and a list of questions with answers.

假设您想将CMS添加到带有标题和带有答案的问题列表的静态FAQ页面。

Making your content dynamic with Butter is a two-step process:

使用Butter使您的内容动态化是一个两步过程:

  1. Setup custom content fields in Butter

    在Butter中设置自定义内容字段
  2. Integrate the fields into your application

    将字段集成到您的应用程序中

To setup custom content fields, first sign in to the Butter dashboard.

要设置自定义内容字段,请首先登录Butter仪表板。

Create a new workspace or click on an existing one. Workspaces let you organize content fields in a friendly way for content editors and have no effect on development or the API. For example, a real-estate website might have a workspace called “Properties” and another called “About Page”.

创建一个新的工作区或单击一个现有的工作区。 通过工作区,您可以以友好的方式为内容编辑者组织内容字段,而不会影响开发或API。 例如,一个房地产网站可能有一个名为“属性”的工作区,另一个名为“关于页面”。

Once you’re in a workspace click the button to create a new content field. Choose the “Object” type and name the field “FAQ Headline.”

进入工作区后,单击按钮创建一个新的内容字段。 选择“对象”类型,并将字段命名为“ FAQ标题”。

After saving, add another field, but this time choose the “Collection” type and name the field FAQ Items .

保存后,添加另一个字段,但是这次选择“集合”类型,并将字段命名为FAQ Items

On the next screen, setup two properties for items in the collection.

在下一个屏幕上,为集合中的项目设置两个属性。

Now go back to your workspace and update your heading and FAQ items.

现在回到您的工作区并更新标题和常见问题解答。

整合您的应用 (Integrate your app)

创建常见问题组件 (Create FAQ Component)

Under apps type: ng g component faq

在“ apps输入: ng g component faq

apps/faq/faq.component.ts
设置onInit挂钩以加载常见问题 (Set up onInit hook to load FAQ)
import {Component, OnInit} from '@angular/core';import {butterService} from '../_services';
@Component({  selector: 'app-faq',  templateUrl: './faq.component.html',  styleUrls: ['./faq.component.scss']})
export class FaqComponent implements OnInit {  constructor() {}
public faq: any = {      items: [],      title: 'FAQ' };
ngOnInit() {  butterService.content.retrieve(['faq_headline', 'faq_items'])    .then((res) => {      console.log(res.data.data);      this.faq.title = res.data.data.faq_headline;      this.faq.items = res.data.data.faq_items;    });  }}
显示结果 (Display the result)
&lt;mat-card&gt;  <mat-card-title class="page-title"></mat-card-title&gt;  <mat-divider></mat-divider>  <mat-card-content class="page-body">    <mat-card *ngFor="let item of faq.items">      <mat-card-content>        <h3>;          {{item.question}}       &lt;/h3>       <div&gt;         {{item.answer}}       </div>     </mat-card-content>   <;/mat-card&gt; </mat-card-content> <mat-divider&gt;</mat-divider&gt;   &lt;mat-card-footer&gt;     <div class="page-footer">       <mat-icon>whatshot</mat-icon>     </div>   </mat-card-footer> </mat-card>

The values entered in the Butter dashboard will immediately update the content in our app.

在黄油仪表盘中输入的值将立即更新我们应用程序中的内容。

写博客 (Blogging)

To display posts, you need to create a /blog route in your app and fetch blog posts from the Butter API, as well as a /blog/:slug route to handle individual posts.

要显示帖子,您需要在应用中创建一个/blog路由,并从Butter API中获取博客帖子,以及一个/blog/:slug路由来处理各个帖子。

See the API reference for additional options such as filtering by category or author. The response also includes some metadata we’ll use for pagination.

有关其他选项,例如按类别或作者进行过滤,请参阅API参考。 响应中还包含一些我们将用于分页的元数据。

设置博客主页 (Set up Blog Homepage)

Under apps/blog-post, type: ng g component listing .

apps/blog-post ,输入: ng g component listing

apps/blog-post/listing/blog-post.listing.component.ts

Update component to get all posts:

更新组件以获取所有帖子:

  1. Import butterService

    进口butterService

  2. Get all post onInit

    onInit获取所有帖子

import {Component, OnInit} from '@angular/core';import {butterService} from '../../_services';
@Component({  selector: 'app-blog-post',  templateUrl: './blog-post.component.html',  styleUrls: ['./blog-post.component.scss']})export class BlogPostComponent implements OnInit { public posts: any[];
constructor() { }
ngOnInit() {  butterService.post.list({  page: 1,  page_size: 10}).then((res) => {  console.log(res.data)  this.posts = res.data.data;  }); }}

Display the result:

显示结果:

&lt;mat-card&gt; <mat-card-title class="page-title">Blog Posts</mat-card-title>; <mat-divider></mat-divider> <mat-card-content class="page-body">   <mat-card *ngFor=”let post of posts”>     <mat-card-title>
&lt;a [routerLink]="[post.slug]">       <div class="container">;         <div fxLayout="row" fxLayout.xs="column"           fxFlex class="content"&gt;          <div class="blocks">            <img *ngIf="post.featured_image" src="{{post.featured_image}}" height="64" width="64"/>;          </div>          <div class="blocks"&gt;            {{post.title}}          <;/div>        </div>;      </div>      <div class="container"&gt;        <div fxLayout="column" class="summary">          &lt;div [innerHTML]="post.summary"></div>        </div&gt;      </div>    </a>  </mat-card-title></mat-card></mat-card-content><mat-divider></mat-divider>
&lt;mat-card-footer&gt;  <div class="page-footer">    <mat-icon>whatshot&lt;/mat-icon>  &lt;/div> </mat-card-footer></mat-card>
设置博客文章页面 (Set up Blog Post page)

Under apps/blog-post, type: ng g component details

apps/blog-post ,键入: ng g component details

apps/blog-post/details/blog-post.details.component.ts

To show a single post:

显示单个帖子:

  1. Import butterService

    进口butterService

  2. In OnInit hook, use butterService to get the blog-post post given the slug in the URL path

    OnInit挂钩中,使用butterService来获取URL路径中给定了butterService的博客文章。

  3. Store results in post variable and markup (HTML) will be updated with the customer data

    将结果存储在发布变量中,标记(HTML)将与客户数据一起更新
import {Component, OnInit, ViewEncapsulation} from '@angular/core';import {Observable} from 'rxjs/Observable';import {ActivatedRoute} from '@angular/router';import {butterService} from '../../_services';import {map, take} from 'rxjs/operators';
@Component({  selector: 'app-blog-post-details',  templateUrl: './blog-post.details.component.html',  styleUrls: ['./blog-post.details.component.scss'],  encapsulation: ViewEncapsulation.None})
export class BlogPostDetailsComponent implements OnInit {
constructor(protected route: ActivatedRoute) {    }
protected slug$: Observable<string>;    public post = {      meta: null,      data: null};
ngOnInit() {  this.slug$ = this.route.paramMap      .pipe(        map(params => (params.get('slug')))      );
this.slug$.pipe(      take(1))      .subscribe(slug => {        butterService.post.retrieve(slug)          .then((res) => {            this.post = res.data;          }).catch((res) => {          console.log(res);       });   }); }}

Display the result:

显示结果:

<mat-card&gt;  <div class="container"&gt;    <div fxLayout="column" class="blog-details">      <div class="container">        <div fxLayout="row">          <h1 class="blocks">            {{post.data.title}}          </h1>          <div *ngIf="post.meta.previous_post">&lt;a [routerLink]="post.meta.previous_post">&lt;</a></div>          <div *ngIf="post.meta.next_post">;&lt;a [routerLink]="post.meta.next_post">></a></div>        </div>;        <;h4>          {{post.data.author.first_name}}     {{post.data.author.last_name}}        </h4>        <div class="post-body" [innerHTML]="post.data.body"></div>      </div>    </div>  </div></mat-card>

Now your app has a working blog that can be updated easily in the ButterCMS dashboard.

现在,您的应用程序具有一个可以正常运行的博客,可以在ButterCMS仪表板中轻松对其进行更新。

类别,标签和作者 (Categories, tags, and authors)

Use Butter’s APIs for categories, tags, and authors to feature and filter content on your blog.

使用Butter的API来分类,标记和作者,以突出显示和过滤博客中的内容。

列出所有类别并按类别获取帖子 (List all categories and get posts by category)

Call these methods on the onInit() lifecycle hook:

onInit()生命周期挂钩上调用以下方法:

methods: { ... getCategories() {   butter.category.list()     .then((res) => {       console.log('List of Categories:')       console.log(res.data.data)     }) }, getPostsByCategory() {   butter.category.retrieve('example-category', {       include: 'recent_posts'     })     .then((res) => {       console.log('Posts with specific category:')       console.log(res)     })   } }, created() { ... this.getCategories() this.getPostsByCategory()}
getCategories() {  butter.category.list()  .then((res) => {   console.log(‘List of Categories:’)   console.log(res.data.data)  }) }, getPostsByCategory() {  butter.category.retrieve(‘example-category’, {   include: ‘recent_posts’  })  .then((res) => {   console.log(‘Posts with specific category:’)   console.log(res)  }) }},created() { … this.getCategories() this.getPostsByCategory()}

结语 (Wrap up)

Congrats, you’ve successfully turned your static Angular application into a CMS-powered app using content APIs and thereby maintaining a serverless architecture. Your development team can take advantage of the time-saving aspects of Angular, and you’ve saved even more time by using a serverless CMS.

恭喜,您已成功使用内容API将静态Angular应用程序转换为基于CMS的应用程序,从而维护了无服务器架构。 您的开发团队可以利用Angular节省时间的方面,并且通过使用无服务器CMS节省了更多时间。

If you’ve enjoyed this article, please help it spread by clapping below! For more content like this, follow us on Twitter and subscribe to our blog.

如果您喜欢这篇文章,请通过下面的鼓掌帮助传播! 有关此类的更多内容,请在Twitter上关注我们并订阅我们的博客。

And if you want to add a blog or Angular CMS to your website without messing around with Wordpress, you should try Butter CMS.

而且,如果您想在您的网站上添加博客或Angular CMS而不用弄乱Wordpress,则应该尝试Butter CMS

翻译自: https://www.freecodecamp.org/news/how-to-build-a-serverless-cms-powered-angular-app-3eb76605799f/

angular 启动服务器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值