Criando uma aplicação React+Firebase passo a passo


Ágil de implementar e poderosa, a combinação de React e Firebase vai agilizar muito o desenvolvimento de suas aplicações

Sabemos há algum tempo que o React é a bola da vez no mundo JavaScript, mesmo com um escopo muito reduzido em comparação com Angular ou Vue, esta biblioteca tem se destacado pela fácil utilização e o apoio de uma grande comunidade.

Utilizando React, neste artigo vamos mostrar a criação de uma aplicação utilizando a ferramenta de BaaS (Backend As A Service) Firebase. Esta nos proporciona banco de dados em tempo real, autenticação, hospedagem, agilizando muito o tempo de desenvolvimento.

Caso você já conheça essa arquitetura, temos alguns outros posts interessantes para você:

React + Firebase = ❤

Nossa aplicação irá conter uma tabela exibindo informações, possibilitando inserir, editar e excluir dados de um banco em tempo real do Firebase. Sem mais, vamos a mão na obra.

Passo 0: Configurando o Firebase

Caso você não tenha um projeto firebase criado ainda, entre em seu console do firebase e crie um projeto em Adicionar projeto. Após isso, copie as keys de seu projeto clicando em Adicionar o Firebase ao seu aplicativo da Web.

Em nosso primeiro passo, iremos listar dados do banco em nossa aplicação, utilizamos a seguinte estrutura nesta aplicação:

root
     > leituras 
          > key
             > { 
                 temperatura : float
                 umidade : float,
                 cliente: String,
                 data: String,
               }

Em que key é uma identificação automática criada pelo Firebase. É necessário mencionar que o banco em tempo real do Firebase não é tipado, adicionamos os tipos para explicitar o comportamento posterior. Insira alguns dados de exemplo sem preocupar com o uniq_id.

Após isso, necessitamos um passo especial: configurar as regras de acesso ao banco. Acesse Banco de dados > Regras e adicione as seguintes regras:

{
    "rules": {
        ".read": true,
        ".write": true
    }
}

Jogando tudo que sabemos de segurança de informação no lixo, adicionaremos essas regras de acesso para facilitar o desenvolvimento, possibilitando a leitura e a escrita por qualquer aplicação sem a necessidade de autenticação. Em projetos de produção é altamente recomendado utilizar regras auth!=null , impossibilitando o acesso ao banco por qualquer pessoa ou aplicação ou etc etc.

Passo 1: Criando corpo da aplicação

Agora que já sabemos o tipo de informação que estamos lidando, primeiramente vamos criar nosso template usando o create-react-app. O create-react-app é uma ferramenta criada pelo próprio Facebook para auxiliar a construção de aplicações React, evitando todo um processo de configuração de ambiente e outras dores de cabeça conhecidas pelos desenvolvedores. Caso você não tenha instalado em seu sistema, instale ele usando o seguinte comando npm:

npm install -g create-react-app

Com o create-react-app já instalado, vamos criar nossa aplicação chamada my-app.

create-react-app my-app
cd my-app/
npm start

Após esperarmos alguns minutos já podemos ver a aplicação rodando no localmente na porta 3000.

Tela inicial após criar uma aplicação create-react-app

Agora que já tivemos o deleite de ver uma aplicação React rodando, iremos verificar a fundo sua organização e arquitetura. Inicialmente veremos a seguinte estrutura de pastas:

my-app/
  - public/
      - index.html
      - favicon.ico
      - manifest.json
  - src/
      - App.css
      - App.js
      - App.test.js
      - index.css
      - index.js
      - logo.svg
      - registerServiceWorker.js

Iremos excluir os arquivos logo.svg, App.css, index.css e suas referências do código, e também iremos modificar a estrutura de pastas. Componentes e seus css serão armazenados na pasta components, além disto iremos criar uma pasta útil para .js que não são componentes como mostrado abaixo.

my-app/
  - public/
      - index.html
      - favicon.ico
      - manifest.json
  - src/
      - components/
                 - App/
                      - App.js
                      - App.css
                      - App.test.js
      - util/
      - index.js
      - index.css
      - registerServiceWorker.js

Após essa reestrutura, rode seu projeto e corrija potenciais erros.

Passo 2: O uso do Material-UI para um design mais agradável

Material-UI e seu logo materializado

Material-Ui é uma implementação do Google Material Design para React. Este possui uma série de componentes já com aparência e animações relativas ao Material Design. Ele é reponsível por padrão e bem semelhante ao Android. Em nosso sistema iremos utiliza-lo para melhor vizualização de tabelas e inputs, e para isso, iremos adicionar o Material-UI a nossa aplicação via npm.

npm install material-ui@next --save
npm install material-ui-icons --save

Vamos iniciar em sua versão mais recente, hoje é mais aconselhável utilizar esta versão pelas novas funcionalidades e modo de utilização.

Então iremos adicionar um appBar em nossa aplicação. Iremos necessitar de um componente MuiThemeProvider, este é obrigatório e irá sobre todos os outros componentes. Logo, editaremos por completo o arquivo App.js como abaixo:

import React, {Component} from 'react';
import './App.css';
import {MuiThemeProvider} from "material-ui/styles/index";
import {AppBar, Toolbar, Typography} from "material-ui";
import {createMuiTheme} from 'material-ui/styles';
import red from 'material-ui/colors/red';

const theme = createMuiTheme({
    palette: {
        primary: red,
    },
});

class App extends Component {
    render() {
        return (
            <MuiThemeProvider theme={theme}>
                <React.Fragment>
                    <AppBar position="static">
                        <Toolbar>
                            <Typography type="title" color="inherit">
                                My Awesome React App
                            </Typography>
                        </Toolbar>
                    </AppBar>
                </React.Fragment>
            </MuiThemeProvider>
        );
    }
}

export default App;

Podemos ver que o boilerplate inicial do material-ui para inserirmos uma appBar é relativamente grande, podemos destacar que theme estabelece a cor vermelha como padrão para a aplicação, e sim, é claro que isso é possível de ser mudado. Logo, temos o seguinte resultado exibido em nosso navegador:

Nossa incrível barra superior vermelha.

Passo 3: Adicionando um estado e uma tabela

Agora que já temos um corpo para nossa aplicação, vamos adicionar mais elementos do material-ui: a tabela, e para isso teremos que adicionar várias coisas…

Vamos criar um componente chamado DataTable.js no diretório ./components/DataTable/ e adicionar o seguinte conteúdo:

import React from 'react';
import {Table, TableBody, TableCell, TableHead, TableRow, Typography} from "material-ui";

export const DataTable = ({data}) => {
    return <React.Fragment>
        <Typography variant="headline" component="h2">Add New</Typography>
        <Table selectable={false}>
            <TableHead>
                <TableRow>
                    <TableCell>Key</TableCell>
                    <TableCell>Temperature</TableCell>
                    <TableCell>Humidity</TableCell>
                    <TableCell>Client</TableCell>
                    <TableCell>Data</TableCell>
                </TableRow>
            </TableHead>
            <TableBody>
                {
                    data.map((item, index) =>
                        <TableRow key={index}>
                            <TableCell>{item.key}</TableCell>
                            <TableCell>
                                {item.temperatura}
                            </TableCell>
                            <TableCell>{item.umidade}</TableCell>
                            <TableCell>{item.cliente}</TableCell>
                            <TableCell>{item.data}</TableCell>
                        </TableRow>
                    )
                }
            </TableBody>
        </Table>
    </React.Fragment>
};

Este componente recebe como props uma lista de itens chamada data, em que cada item é um objeto na forma:

{
    key,
    temperatura,
    umidade,
    cliente,
    data,
}

Com isso já temos uma tabela, e agora só falta seu conteúdo. Para isto, será necessário adicionarmos essas informações no estado do componente App. Como esta informação será oriunda do firebase, vamos faze-la estática inicialmente adicionando o seguinte código dentro de App.

state = {
    data: [
        {
            key: 'test key key',
            temperatura: 'test key temperatura',
            umidade: 'test key umidade',
            cliente: 'test key cliente',
            data: 'test key data',
        }
    ]
};

E no método render vamos adicionar o componente DataTable com a propriedade data apontando para o estado do componente:

render() {
    return (
        <MuiThemeProvider theme={theme}>
            <React.Fragment>
                <AppBar position="static">
                    <Toolbar>
                        <Typography type="title" color="inherit">
                            My Awesome React App
                        </Typography>
                    </Toolbar>
                </AppBar>
                <DataTable data={this.state.data}/>
            </React.Fragment>
        </MuiThemeProvider>
    );
}

E nossa aplicação já está mais palpável, porém ainda é uma lista estática como na imagem abaixo:

Praticidade e lindeza com o componente de tabela do Material-ui.

Agora vamos a brincadeira de verdade, adicionar o Firebase e suas funcionalidade a nossa aplicação.

Passo 4: Integrando Firebase a nossa aplicação

Então vamos instalar a biblioteca do Firebase dentro de nosso projeto com o seguinte comando:

npm install --save firebase

Lembra daquelas credenciais que foram faladas lá no passo zero, então, necessitamos delas agora. Criaremos um arquivo chamado firebaseUtils.js dentro da pasta ./utils e adicionaremos o seguinte conteúdo abaixo. Após isso adicionaremos nossas credenciais dentro da variável config.

import firebase from 'firebase';

const config = {
    apiKey: "**************************",
    authDomain: "**************************",
    databaseURL: "**************************",
    projectId: "**************************",
    storageBucket: "**************************",
    messagingSenderId: "**************************"
};

export const firebaseImpl = firebase.initializeApp(config);
export const firebaseDatabase = firebase.database();

O manejo de dados em aplicações React pode ser um pouco problemático se não for tomado cuidado. Podemos nos deparar com fluxo de dados assíncronos, alto acoplamento e entre outros problemas. Em uma aplicação final neste caso já seria a hora de pensar em arquitetura flux, utilizando Redux ou MobX, porém este não é o caso, vamos usar uma solução mais simples e fácil visando a implementação rápida.

Logo, com um pouco mais de cuidado, separaremos os acessos ao Firebase dentro de uma camada de Service, criando um arquivo chamado FirebaseService.js dentro do diretório ./services/. Inicialmente criaremos um método para recuperarmos todas as informações de um determinado nó do banco de dados do Firebase.

import {firebaseDatabase} from '../utils/firebaseUtils'

export default class FirebaseService {
    static getDataList = (nodePath, callback, size = 10) => {

        let query = firebaseDatabase.ref(nodePath)
                                   .limitToLast(size);
        query.on('value', dataSnapshot => {
            let items = [];
            dataSnapshot.forEach(childSnapshot => {
                let item = childSnapshot.val();
                item['key'] = childSnapshot.key;
                items.push(item);
            });
            callback(items);
        });

        return query;
    };

}

Este método irá retornar a lista através de um callback para o método setState de nossa classe App. Repare que o método recebe como parametros um caminho para o nó nodePath, uma função de callback e o tamanho limitante para a listagem size com um valor padrão de dez items.

Dentro de App.js vamos modificar o estado e adicionar o método componentDidMount:

state = {
    data: []
};

componentDidMount() {
    FirebaseService.getDataList('leituras', (dataReceived) =>    this.setState({data: dataReceived}))
}

Em que leituras é nosso nó de pesquisa no banco, logo listará os últimos dez itens deste nó. Porém não temos dez itens no nosso banco, na verdade não temos nada, então ou teríamos que inserir na mão uma massa de dados; ou então criar uma funcionalidade para inserirmos via tela em nossa aplicação, e é isto que iremos fazer no próximo passo.

Passo 5: React-Router

Nossa aplicação tem exatamente uma tela, e queremos criar mais uma para inserção de dados no nosso banco. O React por si só não nos proporciona uma ferramenta de rotas, então, vamos instalar o react-router em sua última versão:

npm install --save react-router-dom

É importante mencionar que o React não possui uma funcionalidade de router pois é simplesmente uma biblioteca de criação de interfaces, com o tempo iremos perceber que falta muita coisa no React e que ela já deve existe em um projeto que a comunidade React dá apoio, como é o caso do React-Router.

E então dar inicio a implementação do router, vamos criar um arquivo urlUtils.js com as urls que estarão presentes no sistema que serão visíveis em uma tela futuramente.

export const urls = {
    home: { name: 'Home', path:'/'},
    data: { name: 'Data', path:'/data'},
    add:  { name: 'Add',  path:'/add'},
};

Então dentro de index.js adicionaremos um Router:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App/App';
import registerServiceWorker from './registerServiceWorker';
import {BrowserRouter as Router, Route} from 'react-router-dom';
import {urls} from "./utils/urlUtils";

ReactDOM.render(
    <Router>
        <Route path={urls.home.path} component={App}/>
    </Router>
    , document.getElementById('root'));
registerServiceWorker();

Preste atenção na linha:

<Route path={urls.home.path} component={App}/>

Com esta declaração estamos explicitando uma rota para o componente App.js, ao acessar o caminho ‘/’, o sistema irá renderizar o componente lá dentro. Ao subirmos o sistema podemos ver o comportamento citado acima, porém, ao entrar em ‘/data’ não é exibido nada. Então, dentro do render adicionaremos as seguintes rotas onde tínhamos <DataTable/>

<Card style={{margin: '50px'}}>
    <CardContent>

        <Route exact
               path={urls.home.path}
               render={(props) => <Welcome {...props}/>}
        />

        <Route exact
               path={urls.data.path}
               render={(props) => 
                  <DataTable {...props} data={this.state.data}/>}
        />

        <Route exact
               path={urls.add.path}
               render={(props) => 
                        <Add {...props}/>}
        />
    </CardContent>
</Card>

Os componentes Welcome e Add serão criados agora em ./src/components/Welcome e ./src/components/Add, para Welcome.js será criada uma tela de boas vindas com os links presentes em urls:

import {urls} from "../../utils/urlUtils";
import {Button, Typography} from "material-ui";
import React from "react";
import {Link} from "react-router-dom";

export const Welcome = () => {
    return (
        <React.Fragment>
            <Typography variant="headline"
                        component="h2"
                 >
                   Welcome
                 </Typography>
            {
                Object.values(urls).map((url, index) => {
                    return <Button raised 
                                   key={index} 
                                   component={ props => 
                                 <Link to={url.path} {...props}/>
                                   }
                            >
                        {url.name}
                    </Button>
                })
            }
        </React.Fragment>
    )
};

Relativamente simples, mapeamos os valores de urls para botões contendo links paras as respectivas páginas. Também vamos extrair o componente de AppBar de App e inseri-lo no novo arquivo TopBar.js

import {urls} from "../../utils/urlUtils";
import {AppBar, IconButton, Toolbar, Typography} from "material-ui";
import MenuIcon from "material-ui-icons/Menu";
import React from "react";
import {Link} from "react-router-dom";

export const TopBar = () => <AppBar position="static">
    <Toolbar>

        <IconButton color="inherit" aria-label="Menu" 
                    component={props => 
                             <Link to={urls.home.path} {...props}/>}
            >
            <MenuIcon/>
        </IconButton>

        <Typography type="title" color="inherit">
            My Awesome React App
        </Typography>

    </Toolbar>
</AppBar>;

Perceba que adicionamos um IconButton com o link para Welcome nocomponente TopBar, este será o resultado ao terminamos o componente Add:

Nossa tela de boas vindas.

Passo 6: Inserção

Para o componente Add, criaremos um componente para inserirmos os dados diretamente via tela, então adicionaremos o seguinte conteúdo em Add.js:

import {Button, TextField, Typography} from "material-ui";
import React, {Component} from "react";
import FirebaseService from "../../services/FirebaseService";
import {urls} from "../../utils/urlUtils";
import {withRouter} from "react-router-dom";

class Add extends Component {

    submit = (event) => {
        event.preventDefault();

        const {temperatura} = this;
        const {umidade} = this;
        const {data} = this;
        const {cliente} = this;

        const newid = FirebaseService.pushData('leituras', {
            temperatura,
            umidade,
            data,
            cliente
        });

        this.props.history.push(urls.data.path);

    };

    render = () => (<React.Fragment>

        <Typography variant="headline" component="h2">Add New</Typography>
        <form onSubmit={this.submit}>

            <TextField className="input-field"
                       type="text"
                       defaultValue={''}
                       label="Temperature"
                       required
                       onChange={e => this.temperatura = e.target.value}/>


            <TextField className="input-field"
                       type="text"
                       label="Humidity"
                       defaultValue={''}
                       required
                       onChange={e => this.umidade = e.target.value}/>


            <TextField className="input-field"
                       type="text"
                       label="Date"
                       defaultValue={''}
                       required
                       onChange={e => this.data = e.target.value}/>


            <TextField className="input-field"
                       type="email"
                       label="Client"
                       defaultValue={''}
                       required
                       onChange={e => this.cliente = e.target.value}/>

            <Button type="submit"
                    style={{marginTop: '20px', display: 'inline-block'}}>
                Add
            </Button>
        </form>
    </React.Fragment>)
}

export default withRouter(Add);

Lembre-se de também adicionar a classe css abaixo ao arquivo index.css

.input-field {
  clear: left;
  float: left;
  width: 100%;
  display: inline-block;
  margin-top: 2vh !important;
}

Agora que já criamos o corpo para a tela de novos dados, necessitamos da inclusão de uma forma de inseri-los em nosso FirebaseService, vamos adicionar o método pushData que já estava sendo utilizado no em Add.js:

static pushData = (node, objToSubmit) => {
    const ref = firebaseDatabase.ref(node).push();
    const id = firebaseDatabase.ref(node).push().key;
    ref.set(objToSubmit);
    return id;
};

Este método insere um filho no nó com caminho node dentro do banco do Firebase. Agora, já podemos testar a inserção, com o auxilio do material-ui o resultado ficou muito satisfatório:

Nenhum animal foi morto para fazer esse form.

Passo 7: Remoção

Nossa aplicação está quase completa, já é possível inserir e listar dados, agora passamos a tarefa de remover e por fim editar.

Para remoção, adicionaremos o método abaixo dentro de FirebaseService, este remove o filho contendo a chave id dentro do nó node.

static remove = (id, node) => {
    return firebaseDatabase.ref(node + '/' + id).remove();
};

Dentro do componente DataTable será adicionado uma função remove e então um botão para edição, confira abaixo como ficou o componente após a alteração:

import React from 'react';
import {Button, Table, TableBody, TableCell, TableHead, TableRow, Typography} from "material-ui";
import FirebaseService from "../../services/FirebaseService";

export const DataTable = ({data}) => {

    const remove = (id) => {
        FirebaseService.remove(id, 'leituras');
    };

    return <React.Fragment>
        <Typography variant="headline" component="h2">Data</Typography>
        <Table selectable="false">
            <TableHead>
                <TableRow>
                    <TableCell>Key</TableCell>
                    <TableCell>Temperature</TableCell>
                    <TableCell>Humidity</TableCell>
                    <TableCell>Client</TableCell>
                    <TableCell>Data</TableCell>
                    <TableCell>Actions</TableCell>
                </TableRow>
            </TableHead>
            <TableBody>
                {
                    data.map((item, index) =>
                        <TableRow key={index}>
                            <TableCell>{item.key}</TableCell>
                            <TableCell>{item.temperatura}
                            </TableCell>
                            <TableCell>{item.umidade}</TableCell>
                            <TableCell>{item.cliente}</TableCell>
                            <TableCell>{item.data}</TableCell>
                            <TableCell>
                                <Button
                                   onClick={() => remove(item.key)}>
                                    Remove
                                </Button>
                            </TableCell>
                        </TableRow>
                    )
                }
            </TableBody>
        </Table>
    </React.Fragment>
};

Passo 8: Edição

Para a edição, adicionaremos outro botão na tabela com um link para edição:

<Button component={props => 
<Link to={privateUrls.edit.pathWithouParam + item.key}    
         {...props}/>}>
    Edit
</Button>

Adicionaremos ao arquivo urlUtils o seguinte código:

export const privateUrls = {
    edit: { 
     name: 'Edit',
     path:'/edit/:id',
     pathWithouParam:'/edit/'}
};

Estas são urls que não queremos adicionar no componente Welcome, porém são necessários em outros lugares.

Então modificaremos o componente Add para este receber por parâmetro pela url o id de um item do banco, carregar este item e exibir as informações caso o arquivo exista, segue abaixo o arquivo resultante:

import {Button, TextField, Typography} from "material-ui";
import React, {Component} from "react";
import FirebaseService from "../../services/FirebaseService";
import {urls} from "../../utils/urlUtils";
import {withRouter} from "react-router-dom";

class Add extends Component {

    state = {id: null, temperatura: '', umidade: '', data: '', cliente: ''};

    componentWillMount = () => {
        const {id} = this.props.match.params;

        if (!(id === undefined || !id)) {
            this.setState({id});
            FirebaseService.getUniqueDataBy('leituras', id, (data) => this.setState({...data}, () => console.log(this.state)));
        }

    };

    submit = (event) => {
        event.preventDefault();

        const {temperatura} = this.state;
        const {umidade} = this.state;
        const {data} = this.state;
        const {cliente} = this.state;

        let objToSubmit = {
            temperatura,
            umidade,
            data,
            cliente
        };

        if (this.props.match.params.id === undefined) {
            FirebaseService.pushData('leituras', objToSubmit);
        } else {
            FirebaseService.updateData(this.props.match.params.id, 'leituras', objToSubmit)
        }

        this.props.history.push(urls.data.path);

    };

    handleChange = name => event => {
        this.setState({
            [name]: event.target.value,
        });
    };

    render = () => {
        return (<React.Fragment>

            <Typography variant="headline" component="h2">Add New</Typography>
            <form onSubmit={this.submit}>
                <TextField className="input-field"
                           type="text"
                           value={this.state.temperatura}
                           label="Temperature"
                           required
                           onChange={this.handleChange('temperatura')}/>

                <TextField className="input-field"
                           type="text"
                           label="Humidity"
                           value={this.state.umidade}
                           required
                           onChange={this.handleChange('umidade')}/>

                <TextField className="input-field"
                           type="text"
                           label="Date"
                           value={this.state.data}
                           required
                           onChange={this.handleChange('data')}/>

                <TextField className="input-field"
                           type="email"
                           label="Client"
                           value={this.state.cliente}
                           required
                           onChange={this.handleChange('cliente')}/>

                <Button type="submit"
                        style={{marginTop: '20px', display: 'inline-block'}}>
                    Add
                </Button>
            </form>
        </React.Fragment>)
    }
}

export default withRouter(Add);

Por último adicionaremos a rota em nosso componente App:

<Route exact
       path={privateUrls.edit.path}
       render={(props) => <Add {...props} />}
/>

E com isso finalizamos o escopo básico de nossa aplicação contemplando inserção, remoção, atualização e listagem de dados de um banco do Firebase.

Neste momento poderíamos dar nosso trabalho como completo, porém vamos adicionar um quesito de segurança antes de iniciarmos a fase final: utilização de testes automáticos.

Passo 9: Testes automáticos com Jest

Caso você goste de TDD, ainda dá tempo de apagar todo o seu código e iniciar o desenvolvimento pelos testes, como estamos em fase final, vamos realizar um único e mais importante teste, o teste de renderização do componenet App.

O create-react-app já nos provém uma suite de testes chamada Jest, ela nos proporciona grandes habilidades, como realizar mock de componentes React.

Caso você não o tenha instalado, o instale via npm executando o com o comando.

npm install jest --save-dev

O arquivo App.test.js irá conter nosso teste de renderização:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {BrowserRouter as Router} from 'react-router-dom';

it('renders without crashing', () => {
    const div = document.createElement('div');

    ReactDOM.render(
        <Router>
            <App/>
        </Router>, div);

    ReactDOM.unmountComponentAtNode(div);
});

Para verificar se ele roda corretamente execute o comando npm run test

Uma vez que nosso aplicação está rodando perfeitamente sem erros, podemos colocar ela em produção.

Passo 10: Deploy em produção com Firebase Hosting

Antes da parte final, devemos ter noção que nosso aplicativo estará em produção, e que não seria a melhor prática utilizarmos o mesmo projeto do Firebase tanto para desenvolvimento quanto para o sistema em produção.

Para resolver este dilema, vamos editar o arquivo firebase.js e adicionar a possibilidade de utilizar mais uma credencial. Onde tínhamos a variável config vamos substituir pelo código abaixo.

const prodConfig = {
    apiKey: "***************",
    authDomain: "***************",
    databaseURL: "***************",
    projectId: "***************",
    storageBucket: "***************",
    messagingSenderId: "***************"
};

const devConfig = {
    apiKey: "***************",
    authDomain: "***************",
    databaseURL: "***************",
    projectId: "***************",
    storageBucket: "***************",
    messagingSenderId: "***************"
};

const config = process.env.NODE_ENV === 'production'
    ? prodConfig
    : devConfig;

Isso nos proporciona utilizar uma credencial para produção e outra para desenvolvimento. O próprio script de build do create-react-app seleciona a variável de ambiente NODE_ENV para production automaticamente.

Nesta etapa também é necessário configurar suas regras de acesso ao banco para termos o mínimo de segurança em nossa aplicação. Como não implementamos autenticação, e nossa aplicação é um somente demostrativa; vamos deixar as regras publicas e ignorar esta etapa. É claro que em produção isso não é aconselhável.

Então por último, temos a tarefa de realizar o deploy de nossa aplicação dentro da hospedagem do Firebase. Relativamente simples, necessitamos realizar uma build do projeto. O Firebase proporciona uma ferramenta de configuração e deploy. Logo é necessária a instalação desta ferramenta via npm:

npm install -g firebase-tools

Após isso é necessário realizar o login no firebase utilizando o comando:

firebase login

Então, dentro da pasta raiz do projeto, execute o comando

firebase init

Selecione o projeto e após isso hosting.

Então necessitaremos editar o arquivo firebase.json criado na raiz do projeto, adicione o seguinte conteúdo:

{
  "hosting": {
    "public": "build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

Em build, esta é a pasta referência para a build da aplicação utilizando o create-react-app, e será a pasta que o Firebase utiliza para deploy, logo todos os arquivos presentes nela serão levados ao servidor. O seguinte passo é realizar o build de produção via:

npm run build

E então o deploy:

firebase deploy

Será exibida uma mensagem de sucesso e o link para sua aplicação, entre e confira se está tudo certo.

Caso você tenha um certo apreço pela preguiça, recomento automatizar estes dois comandos adicionando-os ao scripts do package.json. Adicionaremos a seguinte linha dentro de “scripts”:

"deploy": "npm run build && firebase deploy"

E com isso você terá sua aplicação online com somente um comando. ❤


Após todo este trabalho temos uma aplicação completa React + Firebaserodando diretamente no servidor do Firebase e com resposta em tempo real com o banco de dados.

O projeto completo está disponível para teste online aqui e seu código aqui. Sintam-se a vontade caso queiram tirar alguma dúvida ou simplesmente puxar um papo sobre tecnologias e outras loucuras em alguma rede social.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s