Construir um aplicativo front-end moderno geralmente requer muitas ferramentas. Pense em Babel, webpack, Parcel, Rollup etc. Há um motivo pelo qual os empacotadores de módulo são tão populares.
Existem muitas ferramentas excelentes para ajudar a simplificar o processo de início de um novo projeto de front-end. Se você está vagamente familiarizado com o React, então deve ter usado o create-react-app
(a menos que você tenha codificado embaixo de uma rocha). É fácil e conveniente. Teimoso, sim, mas elimina muito da configuração dolorosa que você pode ter tido que fazer sozinho.
Então, o que quero dizer com configuração zero?
Neste artigo, vou orientá-lo na construção de um aplicativo React full-stack com Node.js no back-end, e faremos isso sem escrever nenhuma configuração! Sem webpack, sem configurações complexas-nenhum. Nada. Zilch.
A ferramenta que nos permite essa facilidade é chamada de Zero. Também conhecido como Zero Server, ele orgulha-se de ser um zero – estrutura da web de configuração .
Acho que é uma estrutura decente com potencial. Definitivamente, evita muito estresse e é capaz de lidar com configurações de projeto muito diferentes. Seu back-end pode estar em Python ou Node! Seu front-end pode ser em Vue, React ou Svelte!
Como com tudo, existem alguns truques com o Zero-alguns maiores, alguns menores, dependendo do seu caso de uso. Vou me certificar de destacá-los no artigo enquanto construímos o projeto.
O aplicativo full-stack
Estaremos desenvolvendo um aplicativo para a famosa Angela McReynolds. Dê uma olhada na versão final do aplicativo para saber tudo sobre ela. Dê um clique!
As partes principais do aplicativo incluem uma página inicial construída no React:
E uma lista de projetos anteriores para que clientes em potencial possam dar uma olhada:
Instalação e primeiros passos com Zero
Escrever a primeira linha do código e colocar algo na tela é tão fácil quanto com o Zero.
Crie uma nova pasta em qualquer lugar do seu computador e abra-a no editor de código.
Dentro deste diretório, crie um novo arquivo, index.tsx
. Este será o ponto de entrada do aplicativo-a página inicial. Vou explicar como isso funciona em breve.
Vá em frente e escreva um componente básico do App
conforme mostrado abaixo:
import React from"react"; const App=()=> { returnOlá!
; }; exportar aplicativo padrão;
Isso apenas renderiza o texto Hello!
. Nada sofisticado-ainda.
Não instalamos o React ou qualquer módulo neste momento. Isso é bom. Zero cuidará disso. Em seu terminal, vá em frente e escreva npx zero
para executar Zero no diretório.
O que acontece depois de executar o comando zero
é interessante. Ele vai em frente e resolve os módulos em index.tsx
, instala as dependências e cria automaticamente arquivos de configuração para que você não precise fazer isso!
Agora vá para http://localhost: 3000
e você deve ter o componente index.tsx
servido:
Isso não é muito empolgante, mas ainda há algo para aprender aqui!
<”NB . , executamos o
zero
comando do servidor sem uma instalação global. Isso é possível porque usamos npx . Vou favorecer isso em todo o artigo. Se você preferir terzero
instalado globalmente, executenpm install-g zero
e inicie o aplicativo apenas executandozero
, nãonpx zero
.
Como funciona o roteamento no Zero Server
Zero usa um sistema de roteamento baseado em arquivo. Se você trabalhou com determinados geradores de sites estáticos, isso pode não ser novidade para você. Este também é um sistema adotado por Next .js .
A maneira como funciona é simples. O aplicativo Zero Server atual está sendo executado em http://localhost: 3000/
. A página servida ao navegador será o arquivo raiz index
. Pode ser index.html
ou index.jsx
ou index.tsx
-não importa. Zero ainda iria compilar e servir o arquivo.
Se você visitou /about
no navegador, Zero iria procurar um arquivo sobre
associado no diretório raiz, independentemente do tipo de arquivo, desde que seja compatível ( ou seja, .vue
, .js
, .ts
, .svelte
ou .mdx ). Da mesma forma, se você visitar
/pages/about
, Zero iria procurar um arquivo sobre
no diretório pages
.
Roteamento simples, mas eficaz. Aqui está um exemplo prático.
Crie um novo arquivo chamado about.tsx
no diretório raiz e tenha o seguinte componente básico retornado:
import React from"react"; const Sobre=()=> { returnSobre mim!
; }; exportação padrão Sobre;
E com certeza, se você visitar http://localhost: 3000/about
, você verá o seguinte:
<”NB . , Zero procurará a entidade exportada padrão no arquivo sendo renderizado. Certifique-se de ter uma exportação padrão que não seja chamada de
exports
em seus arquivos React públicos.
E quanto aos subdiretórios?
Crie um diretório blog
e, nele, crie um arquivo hello.mdx
.
Escreva o seguinte:
# Olá ## Este é um novo blog
Este é o Markdown. Mesmo assim, Zero renderiza isso perfeitamente!
Você notará que a extensão do arquivo é .mdx
. Este é um superconjunto de M arkdown .md
. Em termos elementares, mdx
é markdown mais JSX. A imagem pode renderizar um componente React em um arquivo Markdown! Sim, é isso que MDX permite que você faça.
Estrutura de pastas para seu aplicativo Zero
Como o roteamento é baseado em arquivos, você deve pensar um pouco mais em como estrutura seu aplicativo. Durante o desenvolvimento, você não gostaria que todos os seus arquivos de cliente fossem expostos publicamente. Alguns componentes existirão apenas para serem compostos em páginas e não para serem exibidos por si próprios.
Minha recomendação seria colocar os arquivos que você deseja publicar no diretório principal ( 2 ) e todo o resto deve ir em um diretório cliente
( 1 ):
O nome desse diretório é com você; você pode chamá-lo de componentes
se desejar. Mas certifique-se de ter essa separação de interesses em seu aplicativo Zero. Você verá por que isso é ouro em breve.
Ignorando arquivos com um arquivo .zeroignore
Arquivos ou diretórios que você não deseja publicar podem ser comunicados ao Zero por meio de um arquivo .zeroignore
.
Como um arquivo gitignore
, você escreve o nome do diretório ou arquivo a ser ignorado.
Neste exemplo, esta é a aparência do arquivo .zeroignore
:
cliente servidor
Ignorando os diretórios cliente
e servidor
. O diretório client
manterá os arquivos do lado do cliente que não queremos públicos; o mesmo vale para servidor
.
Construindo a página inicial
No momento, temos uma página inicial que diz apenas “Olá”. Ninguém nunca ficará impressionado com isso! Vamos melhorar.
Uma vez que esta postagem é focada em trabalhar com Zero Server, não irei explicar as mudanças estilísticas da interface do usuário feitas. Para prototipagem rápida, instale Chakra e componentes estilizados:
npx yarn add @ chakra-ui/react @ emotion/react @ emotion/styled framer-motion styled-components
Agora atualize o arquivo index.tsx
para o seguinte:
import React from"react"; import { Flex, Caixa, Título, Texto, Botão, Centro, Imagem, Espaçador, } de"@ chakra-ui/react"; const Home=()=> { Retorna ({/* Cartão de Perfil */} {/* Detalhes */}Angela McReynolds Leia meu blog Sobre mim{""} &cópia de; 2020 Angela McReynolds ); }; exportar Página inicial padrão; O
MELHOR DO MUNDO
FRONTEND
ENGENHEIROEsqueça o hype, a autoafirmação e outras besteiras. Eu não faço Essa. Eu tenho resultados. em 2015, 2016, 2017, 2018 e 2020 fui eleito o o melhor engenheiro de front-end do mundo por colegas e designers em todo o mundo. Uma eleição completa foi conduzida e eu fiquei por cima. Eu tenho cérebros e eu os uso, você tem sorte de ter tropeçado aqui. Enquanto vivia em Marte, passei décadas dominando a arte do computador programação. Ao chegar à Terra em 2013, eu constantemente ria de nosso patéticos os desenvolvedores na terra eram. Todos vocês têm sorte de me ter. Veja projetos anteriores
Agora você deve ter algo assim quando visitar localhost: 3000
:
Configurações globais de página centralizada
Isso aqui é uma das maiores desvantagens do Zero. Fora da caixa, não há como lidar com configurações de página centralizadas; você tem que ser criativo. Em muitos casos, você pode descobrir isso, enquanto outros podem virar hacky .
Neste cenário específico, queremos adicionar configurações centralizadas para a biblioteca Chakra UI.
Você terá casos como este em seu aplicativo, então aqui está o que eu recomendo.
Comece preenchendo o diretório client
com alguma estrutura que permita hospedar cada página independente do arquivo exposto publicamente.
Não se confunda-é o que quero dizer. Crie um diretório pages
e tenha os subdiretórios Home
e About
criados. Mova o código do index.tsx
público e About.tsx
para os respectivos diretórios.
Neste exemplo, movi todo o código para Home
desta forma:
//Home/Home.tsx export const Home=()=> { //copie o código } //Home/index.ts exportar {Home as HomePage} de'./Home'
Vá em frente e faça o mesmo para a página Sobre
e exporte de pages/index.tsx
:
exportar {AboutPage} de"./Sobre"; exportar {HomePage} de"./Home";
Agora, aí vem a parte boa.
Centralize qualquer lógica de criação de página central que você tenha em um arquivo separado no diretório client
. Eu chamei isso de makePages.tsx
Temas, metadados, fontes personalizadas... tudo isso adicionado em um só lugar. Aqui está o que precisamos para o aplicativo de exemplo.
Install react-helmet-async:
npx yarn add react-helmet-async
Then add the following to makePages.tsx
:
import React from"react"; import { Helmet } from"react-helmet-async"; import { ChakraProvider, Box } from"@chakra-ui/react"; import { extendTheme } from"@chakra-ui/react"; const appTheme=extendTheme({ colors: { brand: { 100:"#CCD0E7", 200:"6E769E60", 800:"BDC3DD", 900:"#9094B4", }, }, fonts: { heading: `"Roboto Condensed", sans-serif`, body:"Roboto, sans-serif", mono:"Menlo, monospace", }, textStyles: { h1: { fontSize: ["4xl","5xl"], fontWeight:"bold", lineHeight:"56px", }, p: { fontWeight:"bold", py: 4, color:"rgba(204, 208, 231, 0.5)", }, }, }); type PageWrapperProps={ children: React.ReactNode; title: string; }; export const PageWrapper=({ children, title, }: PageWrapperProps & React.ReactNode)=> { return ( <>{title} > ); }; {children}
Now, your app will be different, of course, but you will still benefit from the structure described here. And you’ll perhaps save yourself a lot of time debugging and duplicating code.
Now, we need to use the PageWrapper
component from makePages.tsx
. PageWrapper
takes a page component and ensures it’s got all the centralized logic.
Go to Home/index.tsx
and have it use PageWrapper
, as seen below:
//client/pages/Home/index.tsx import { PageWrapper } from"../../makePages"; import { Home } from"./Home"; export const HomePage=()=> ();
Do the same for the About
page by following the pattern established above.
In the exposed index.tsx
home page, i.e. the root file served for localhost:3000
, go ahead and use the new HomePage
component:
//index.tsx import { HomePage } from"./client/pages"; export default ()=>;
This now has all the centralized configuration for our client pages. Here’s the result:
Everything’s coming along nicely!
Go ahead and build yourself an About
page. Use the same structure as above and see how that works too!
Customizing the 404 pages
If you go ahead and visit a random page like http://localhost:3000/efdfdweg
, you should see the following:
That’s OK. This is the default 404 page from Zero. To customize this, you just have to create a 404
file (in any supported file format) and Zero will serve it.
Let’s try that.
Create a 404.jsx
file and have the following copied over:
//404.jsx import React from"react"; import { Container, Heading, Text, Link, Center, Image, } from"@chakra-ui/react"; import { PageWrapper } from"./client/makePages"; export default ()=> (); You seem lost:({""} Ir para casa
And sure enough, we’ve got an arguably nicer 404 page. Creative, huh?
Server-side development with Zero
We’ve got the essential functionality you need to be aware of on the client covered. This includes tricky bits such as centralizing your page setup. Now let’s switch focus to the backend for a bit. I’ll be using Node.js to keep things familiar.
Before any code implementation, you should be aware that routing works just the same here! And as with the client implementation, Zero supports different backend languages: Python and Node.
OK, so first things first.
When a user clicks See past projects, we want to display a new page with a list of projects served from our backend written in Zero. Let’s set up a basic Node.js backend.
Create an api
directory and a projects.ts
file. All endpoints will be written in this api
directory. Essentially, the endpoint will be something like ${APP_BASE_URL}/api/projects
— which is semantic!
Since we’re using TypeScript, install the typing for Node as follows:
npx yarn add @types/node-D
Now paste the following in the projects.ts
file:
const PROJECTS=[ { id: 1, client:"TESLA", description:"Project Lunar: Sending the first humans to Mars", duration: 3435, }, { id: 2, client:"EU 2020", description: "Deploy COVID tracking mobile and TV applications for all of Europe", duration: 455, }, { id: 3, client:"Tiktok", description: "Prevent US app ban and diffuse security threat claims by hacking the white house", duration: 441, }, ]; module.exports=function (req, res) { res.send({ data: PROJECTS }); };
This is a basic implementation, but note the Express style syntax:
module.exports=function (req, res) { res.send({ data: PROJECTS }); };
Where req
and res
represent the request and response objects. If you visit localhost:3000/api/projects
, you should now receive the JSON object.
Now all we’ve got to do is make the fronted call this API endpoint.
In the pages
directory, add a new Projects
folder. Go ahead and paste the following in projects.tsx
within this folder. Don’t worry, I’ll explain the important bits.
import { Thead, Tbody, Table, Tr, Th, Td, Heading, TableCaption, Box, } from"@chakra-ui/react"; import { useState, useEffect } from"react"; export const Projects=()=> { const [projects, setProjects]=useState([]); useEffect(()=> { const fetchData=async ()=> await fetch("/api/projects") .then((res)=> res.json()) .then(({ data })=> setProjects(data)); fetchData(); }, []); return (); }; Past Projects
Mere mortals can't achieve what I have {projects.map((project)=> ( Client Description Hours spent ))} {project.client} {project.description} {project.duration}
What’s most important here is the data fetch logic:
const [projects, setProjects]=useState([]); useEffect(()=> { const fetchData=async ()=> await fetch("/api/projects") .then((res)=> res.json()) .then(({ data })=> setProjects(data)); fetchData(); }, []);
Note the URL called: /api/projects
. Zero supports another form of data fetching that works great with SSR, but the example here shows a client-side data fetch.
Now to link to the Projects
page, we just need to edit the Button
on the homepage to link to this page.
//client/pages/Home/Home.tsx //add as and href props to the button. ...
And now you should have this:
Query parameters
The Node backend we’ve got now is truly basic. But Zero supports a lot more. For example, we can handle query parameters sent from the frontend in the API function by retrieving that from req.body
:
//api/projects.ts module.exports=function (req, res) { const {id}=req.query.id res.send({ data: PROJECTS }); }; //frontend call e.g./api/projects?id=1
HTTP methods other than GET
It is worth mentioning that your exported API function will be called for other HTTP methods. e.g., POST, PUT, PATCH, and DELETE methods. These have to be handled specifically. For example, req.body
will be populated with data sent via a POST request.
Global API endpoint configuration
As with the frontend implementation, no global configuration options are provided by default with Zero. A common use case for this on the backend is centralizing logic via middleware. This is a common Express pattern.
The recommended way to do this is to move all middleware to a central directory or file, e.g., the server
directory created earlier.
Here’s an example middleware:
//server/middleware.ts const corsMiddleware=(req, res, next)=> { res.header("Access-Control-Allow-Origin","*"); res.header( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept" ); next(); };
Note the call next()
. Like Express, this makes sure the next middleware in the chain is called.
The benefit of centralization comes when you’ve got more than one middleware.
//server/middleware.ts //middleware 2 const basicLoggerMiddleware=function(req, res, next) { console.log("method", req.method); next(); };
Now, instead of exporting each middleware singly, we centrally call each middleware, and then whatever handler is passed:
//server/middleware.ts module.exports=(req, res, handler)=> { basicLoggerMiddleware(req, res, ()=> { corsMiddleware(req, res, ()=> { handler(req, res); }); }); };
Then you can invoke the middleware in your handler, e.g., api/projects.ts
:
const middleware=require("./server/middleware"); const handler=(req, res)=> { res.send({data: PROJECTS}); } module.exports=(req, res)=> middleware(req, res, handler);
Not the most elegant solution there is, I agree.
Conclusion
These are the basics of getting a full-stack app built with Zero. I strongly recommend checking out the official docs for cases I may not have mentioned in this article.
The premise of Zero is particularly impressive, largely because of the varying file formats supported on the fronted and backend — React, Vue, Svelte, all the way to Python.
However, for it to be widely adopted, especially for production cases, there’s still work to be done.
Some quick downsides you may notice include:
- Slow compile time
- Poor error handling, e.g., if you use a named export, not default, the browser keeps loading forever
- Poor handling of global defaults, as mentioned in the article
- Poor OS support. The project hasn’t received any reasonable updates in months; numerous issues unanswered, too
Regardless, I must say it’s a potentially great library with a clever take on “simple” web development. Good thing it’s open-source, so motivated individuals like me and you can contribute to improve it — if we find the time.
The post Build a full-stack React app with zero configuration appeared first on LogRocket Blog.