npm install -g @aws-amplify/cli
Após a instalação, podemos configurar o amplify executando o seguinte comando:
amplify configure
Ele solicitará que você faça login na AWS. Depois de fazer login, você receberá as instruções para criar um usuário do IAM.
*** Nota: IAM significa (Gerenciamento de Acesso à Identidade). Você pode aprender mais sobre isso com este ligação. ***
Você verá algo semelhante ao abaixo em seu terminal.
Specify the AWS Region?
region: # Type Your preferred region (for me I choose ca-central)
Specify the username of the new IAM user:
user name: # User name for Amplify IAM user
Complete the user creation using the AWS console (Y/n)
Selecione suas opções preferidas. O Amplify abrirá uma guia do navegador e você deverá fazer login no console da AWS no navegador. Em seguida, ele solicitará que você crie um usuário. Certifique-se de criar o usuário com privilégios administrativos.
** Siga este pequeno exemplo de vídeo se não tiver certeza de como proceder:
Depois que o usuário é criado, salve o accessKeyId
e a secretAccessKey
em um local seguro. O Amplify solicitará que você forneça esses valores no terminal. Quando você vir um prompt de entrada do usuário na linha de comando, insira esses valores.
E é isso. Agora você está tudo configurado com o Amplify.
Criando um novo aplicativo React
Agora que estamos todos configurados com o Amplify, vamos em frente e crie um novo aplicativo React.
npx create-react-app serverless-blog
cd serverless-blog
npm start
Tudo bem, agora estamos prontos para adicionar um back-end sem servidor ao nosso aplicativo React.
Adicionando uma API sem servidor para reagir
Adicionar uma API sem servidor é muito simples com o Amplify. Tudo o que precisamos fazer é executar o seguinte comando e o amplify cli
nos guiará pelo processo de criação da API.
Na raiz do nosso aplicativo de reação, precisamos executar o seguinte comando:
amplify add api
O CLI do Amplify agora nos fará algumas perguntas:
Please select from one of the below mentioned services: GraphQL # select GraphQL
Provide API name: serverlessblog # choose a name for your api
O Amplify nos dá as opções para escolher REST ou GraphQL. Para este projeto, escolheremos o GraphQL.
Passando para a próxima pergunta, você perguntará que tipo de autorização gostaríamos.
Choose the default authorization type for the API
Para esta opção, escolha Amazon Cognito User Pool
. Escolheremos essa opção, porque em nosso aplicativo queremos que os usuários possam se inscrever, fazer login e logout. Também permitiremos apenas que usuários inscritos criem postagens.
A seguir, veremos mais algumas perguntas. Podemos escolher todas as opções padrão para essas perguntas.
Do you want to use the default authentication and security configuration? # Select Default
How do you want users to be able to sign in? # Select Username
Do you want to configure advanced settings? # Select No
Do you want to configure advanced settings for the GraphQL API # Select No
Do you have an annotated GraphQL schema? # Select No
Do you want a guided schema creation? # Select Yes
Finalmente, ele perguntará como você descreveria seu projeto. Para esta opção, selecione um para muitos.
What best describes your project: One-to-many relationship
(e.g., “Blogs” with “Posts” and “Comments”)
Em seguida, a API será gerada. Veremos que uma pasta chamada Amplify
foi gerado. Localize o amplify/backend/api/schema.graphql
Arquivo. Este é o nosso esquema para o banco de dados. Vamos dar uma olhada dentro deste arquivo.
type Post @model @auth(
rules: [
{allow: owner, ownerField: "owner", operations: [create, update, delete]},
]
) {
id: ID!
title: String!
content: String!
owner: String
comments: [Comment] @connection(keyName: "byPost", fields: ["id"])
}
type Comment @model @key(name: "byPost", fields: ["postID", "content"]) {
id: ID!
postID: ID!
post: Post @connection(fields: ["postID"])
content: String!
}
Temos dois modelos definidos acima, um modelo de postagem e um modelo de comentário. Um modelo representa uma tabela em nosso banco de dados. Por padrão, estamos usando o DynamoDB da Amazon.
Você pode fazer login no console da AWS no navegador e dar uma olhada nas tabelas do DynamoDB. Para nós Post
modelo, temos campos obrigatórios id
, title
e content
. o !
O símbolo representa campos obrigatórios. similarmente Comment
O modelo também possui alguns campos obrigatórios.
Agora o Post
modelo tem um @connection
chave definida no campo de comentários. Isso representa uma junção de chave estrangeira. A chave estrangeira está associada ao id
campo do Comment
modelo por um nome de chave byPost
.
Se olharmos para o Comment
modelo, podemos ver um @key
chave que está fazendo o mesmo. Esta junção é criar um has_many
relação entre dois modelos. Portanto, nossos posts têm muitos comentários. Se você conhece os bancos de dados relacionais, provavelmente conhece esse conceito.
Observe que temos outra palavra-chave, @auth
. Essa chave garante a propriedade. Se observarmos as regras associadas a essa chave, veremos que estamos apenas permitindo que um proprietário (um usuário autenticado) crie, atualize e exclua um registro. Também impedirá que um usuário exclua uma postagem criada por outra pessoa.
Tudo bem, agora vamos enviar nosso código para a nuvem da AWS com o seguinte comando:
Amplify push
O Amplify cli solicitará uma opção para escolher o idioma de geração de código. Escolha Javascript. Isso irá gerar algum código para nós. Usaremos esse código gerado para consultas e mutações no GraphQL.
Você pode encontrar o código do projeto até este ponto no seguinte link:
👉 https://github.com/Shadid12/serverless-blog/tree/01-initial-setup
Vamos criar uma página inicial “
Gostaríamos de ter uma página inicial com todas as últimas postagens listadas. Então vamos ao nosso src/App.js
e crie um novo Home
Reagir componente.
// src/App.js
import React from 'react';
import Home from './components/Home'
function App() {
return (
);
}
export default App;
Podemos criar um novo diretório chamado component e criar um novo arquivo Home.js
para o nosso componente Home.
// src/components/Home.js
import React from 'react';
function Home() {
const posts = [
{
id: 'id-1',
title: 'dummy title',
content: 'dummy content'
},
{
id: 'id-2',
title: 'dummy title 2',
content: 'dummy content 2'
}
];
return (
{posts.map(p => (
-
{p.title}
{p.content}
))}
);
}
export default Home;
Criamos alguns valores codificados para as postagens. Nós o substituiremos por uma chamada à API posteriormente.
Autenticação de usuário com o Cognito
Vamos mergulhar na autenticação. Antes de tudo, precisamos instalar alguns pacotes npm.
npm i aws-amplify-react aws-amplify --save
Esses dois pacotes tornam muito fácil adicionar autenticação de usuário com o React. Antes de tudo, precisamos configurar o back-end do Amplify com o React. Vamos abrir src/index.js
e adicione o seguinte código:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import Amplify from 'aws-amplify';
import aws_export from './aws-exports';
Amplify.configure(aws_export);
ReactDOM.render(
,
document.getElementById('root')
);
Estamos fazendo algumas coisas aqui. Antes de tudo, estamos importando aws_export
. Este arquivo foi gerado através do gerador de código do Amplify. Este arquivo contém os metadados do nosso projeto. Sempre gitignore esse arquivo, pois ele contém dados confidenciais. Em seguida, importamos a instância do Amplify e chamamos o método configure com aws_export como parâmetro.
Em seguida, iremos ao nosso componente inicial e importaremos um componente de ordem superior chamado withAuthenticator
de aws-amplify-react
pacote. Tudo o que precisamos fazer é embrulhar nossa Home
componente com este componente de ordem superior para torná-lo protegido por autenticação.
import React from 'react';
import { withAuthenticator } from 'aws-amplify-react';
function Home() {
const posts = [
{
id: 'id-1',
title: 'dummy title',
content: 'dummy content'
},
{
id: 'id-2',
title: 'dummy title 2',
content: 'dummy content 2'
}
];
return (
{posts.map(p => (
-
{p.title}
{p.content}
))}
);
}
export default withAuthenticator(Home );
Esse é o truque. Simples e fácil. Agora, se formos ao nosso aplicativo, veremos uma tela de login. Só podemos ver o componente Início quando estamos logados.
Agora isso é puro ✨✨. A Amplify até criou um processo de verificação de autenticação para nós. Os usuários iniciantes receberão um email de confirmação para verificar sua conta.
Consultas GraphQL
CRUD clássico
Praticamente todos os aplicativos da Web têm a funcionalidade básica CRUD (Criar, Ler, Atualizar, Excluir). Em nosso aplicativo, teremos essa funcionalidade também. Um usuário poderá criar, ler, atualizar e excluir postagens e comentários.
Criando uma postagem
Quando o usuário estiver logado, ele deverá ver um link para criar uma nova postagem. Quando o usuário clica no link, ele deve ser levado para uma nova página com um formulário. Em seguida, o usuário envia o formulário e uma nova postagem é criada.
Para conseguir isso, precisamos ser capazes de rotear para links diferentes. Nós estaremos usando o react-router-dom
pacote para fazer o roteamento.
Vamos instalar este pacote e trazê-lo em nosso projeto.
npm i react-router-dom --save
Agora, em nosso arquivo App.js, podemos modificar nosso código para rotear para diferentes URLs.
import React from 'react';
import Home from './components/Home';
import Post from './components/Post';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
function App() {
return (
-
Home
-
New Post
);
}
export default App;
Como você pode ver no código acima, criamos uma lista de links de navegação. Os links correspondem a diferentes componentes do React. Quando mudamos para um link diferente, esse componente é montado. o Home
O componente é renderizado no URL raiz e Post
componente será renderizado no /posts/new
ligação. Ainda não criamos o componente de postagem, então vamos criar esse componente.
import React from 'react';
function Post() {
const [title, setTile] = React.useState();
const [content, setContent] = React.useState();
const handleSubmit = event => {
event.preventDefault();
}
return (
);
}
export default Post;
Este é um componente React muito básico, onde temos um formulário e temos dois ganchos que estão alterando o estado do componente com base na entrada do usuário. Quando o usuário envia o formulário, chamamos de handleSubmit
função. Faremos nossa chamada de API nesta função. Então, vamos implementar isso.
Se navegarmos para o src/graphql/mutations.js
veremos que o amplify já gerou algum código para nós. Nesse arquivo, temos uma função chamada createPost
. Temos que importar esta função em nosso componente e executar a mutação. Aqui está o código para fazer isso:
import React from 'react';
import { API, graphqlOperation } from 'aws-amplify';
import { createPost } from '../graphql/mutations';
function Post() {
const [title, setTitle] = React.useState();
const [content, setContent] = React.useState();
const handleSubmit = async event => {
event.preventDefault();
try {
let input = {
title,
content
}
let newPost = await API.graphql(graphqlOperation(createPost, {input}));
setTitle('');
setContent('');
console.log('new post created ->>', newPost)
}catch (error) {
console.log(error)
}
}
return (
);
}
export default Post;
Você pode fazer login no console da AWS no navegador e navegar para o AppSync e selecionar nosso aplicativo. Selecione Consultas no menu.

A partir daqui, clique em documentos e você poderá ver documentos detalhados sobre todas as consultas e mutações do nosso aplicativo. Também podemos verificar quais parâmetros são necessários para uma função de mutação gerada.
Listando todas as postagens
Vamos listar todas as postagens em nossa página inicial agora. Se formos olhar para o src/graphql/queries.js
arquivo veremos um listPosts
função de consulta. Podemos chamar essa função para listar todas as postagens. Vamos chamar essa função em nossa Home
componente na montagem do componente. Esta função retornará todas as postagens do banco de dados e as renderizaremos em nossa home page.
// Home.js
import React from 'react';
import { withAuthenticator } from 'aws-amplify-react';
import { API, graphqlOperation } from 'aws-amplify';
import { listPosts } from '../graphql/queries';
function Home() {
const [posts, setPosts] = React.useState([])
React.useEffect(() => {
getPosts();
}, []);
const getPosts = async () => {
try {
let resp = await API.graphql(graphqlOperation(listPosts));
console.log('===>>>>',resp);
setPosts(resp.data.listPosts.items)
} catch (error) {
console.log('Something went wrong', error);
}
}
return (
{posts.map(p => (
-
{p.title}
By {p.owner}
))}
);
}
export default withAuthenticator(Home);
O código até este ponto pode ser encontrado no seguinte link:
👉 https://github.com/Shadid12/serverless-blog/tree/03-create-read-update-delete
Excluindo uma postagem
Vamos implementar a capacidade de excluir uma postagem agora. Já estamos renderizando um botão de exclusão para cada postagem. Agora, anexaremos uma ação quando o botão for pressionado.
Como você pode imaginar, há uma mutação no GraphQL para excluir uma postagem. Tudo o que precisamos fazer é chamar essa mutação. Aqui está a implementação do código
import React from 'react';
import { withAuthenticator } from 'aws-amplify-react';
import { API, graphqlOperation } from 'aws-amplify';
import { listPosts } from '../graphql/queries';
import { deletePost } from '../graphql/mutations';
import {
Link
} from "react-router-dom";
function Home() {
const [posts, setPosts] = React.useState([])
React.useEffect(() => {
getPosts();
}, []);
const getPosts = async () => {
try {
let resp = await API.graphql(graphqlOperation(listPosts));
console.log('===>>>>',resp);
setPosts(resp.data.listPosts.items)
} catch (error) {
console.log('Something went wrong', error);
}
}
const deleteSelected = async id => {
try {
let input = {
id
}
let deleted = await API.graphql(graphqlOperation(deletePost, {input}));
let newPosts = posts.filter(p => p.id !== id);
setPosts(newPosts);
console.log('Post delete', deleted);
} catch (error) {
alert('Not Allowed', error);
}
}
return (
{posts.map(p => (
-
{p.title}
By {p.owner}
Edit
))}
);
}
export default withAuthenticator(Home);
Como você pode ver acima, passamos o postId como um parâmetro na função e chamamos o deletePost
mutação.
Atualizar uma postagem
Para cada post, temos um botão de atualização. Quando um usuário clica nesse botão, devemos encaminhar para uma rota de atualização. Vamos criar uma nova rota em nosso componente de aplicativo.
// App.js
Vamos criar um novo componente chamado EditPost
. Este componente receberá o id
de uma postagem a partir do URL e consulte essa postagem no banco de dados. Depois de recuperar uma postagem, ele permitirá que o usuário atualize seu conteúdo. Quando um usuário atualiza a entrada e pressiona o botão de envio, ele faz uma chamada de atualização para nossa API. Vamos implementar isso EditPost
componente.
import React from 'react';
import { API, graphqlOperation } from 'aws-amplify';
import { updatePost } from '../graphql/mutations';
import { getPost } from '../graphql/queries';
import { useParams } from "react-router-dom";
function EditPost() {
let { id } = useParams();
const [title, setTitle] = React.useState();
const [content, setContent] = React.useState();
React.useEffect(() => {
queryPostById();
}, [])
const queryPostById = async () => {
const resp = await API.graphql(graphqlOperation(getPost, { id }));
console.log('--->>>>', resp)
setTitle(resp.data.getPost.title);
setContent(resp.data.getPost.content);
}
const handleSubmit = async event => {
event.preventDefault();
try {
let input = {
id,
title,
content
}
let newPost = await API.graphql(graphqlOperation(updatePost, {input}));
setTitle('');
setContent('');
console.log('Post Updated ->>', newPost)
} catch (error) {
console.log(error)
}
}
return (
);
}
export default EditPost;
Este componente é muito semelhante ao nosso componente de postagem. A única diferença principal é que, no carregamento do componente, buscamos uma postagem e preenchemos a entrada com as informações da postagem. Um usuário pode atualizar o conteúdo e o título. Quando um usuário envia o formulário, chamamos a mutação de atualização do graphql.
Temos que mudar uma última coisa em nossa Home
componente. Temos que adicionar, alterar o link de edição, para que ele direcione para a postagem apropriada.
return (
{posts.map(p => (
-
{p.title}
By {p.owner}
Edit
))}
)
Perfeito, terminamos com a funcionalidade de atualização.
Você pode encontrar o código fonte até este ponto no seguinte repositório:
👉https://github.com/Shadid12/serverless-blog/tree/04-delete-view
Visualizando uma postagem
Vamos ver como podemos obter uma visão detalhada de uma postagem específica. Quando um usuário clica na postagem, ele deve direcionar para uma visualização detalhada, onde o usuário pode ver o título, os detalhes e os comentários da publicação.
Essa funcionalidade é muito semelhante à funcionalidade de atualização. Vamos começar com a criação de uma nova rota no App
componente.
Agora vamos criar o componente ViewPost.
import React from 'react';
import { API, graphqlOperation } from 'aws-amplify';
import { getPost } from '../graphql/queries';
import { useParams } from "react-router-dom";
function ViewPost() {
let { id } = useParams();
const [post, setPost] = React.useState();
React.useEffect(() => {
queryPostById();
}, [])
const queryPostById = async () => {
const resp = await API.graphql(graphqlOperation(getPost, { id }));
console.log('--->>>>', resp)
setPost(resp.data.getPost);
}
if(!post) {
return Loading....
}
return (
{post.title}
By {post.owner}
{post.content}
{
post.comments.items.map(com => (- {com.content}
))
}
);
}
export default ViewPost;
Como você pode ver no código acima, o componente de exibição da consulta está consultando a postagem por ID no banco de dados e, em seguida, está exibindo o conteúdo da postagem.
Agora, em nosso componente inicial, precisamos alterar o URL como abaixo:
return (
{posts.map(p => (
-
{p.title}
By {p.owner}
Edit
))}
);
E é isso. Implementamos a funcionalidade de criação, leitura e atualização e exclusão. Como exercício, você pode tentar adicionar comentários a cada postagem.
Espero que os tópicos discutidos neste artigo tenham sido úteis. Os conceitos básicos que discutimos devem ser suficientes para você começar com seus próprios aplicativos sem servidor de pilha completa.
Se você tiver alguma dúvida, sinta-se à vontade para entrar em contato comigo. Até a próxima vez