Criando iOS apps utilizando Rails e Turbo Native
joséanchieta / November 2023 (1301 Words, 8 Minutes)
Um novo horizonte para o que pode ser feito com Rails.
Desde o início dos anúncios sobre Hotwire e Turbo, venho acompanhando e formando minhas opiniões a respeito. Confesso que de primeira, fiquei cético e achei que seria apenas mais uma coisa de Javascript para aprender, eu estava terrivelmente enganado
.
Após assistir as palestras do RailsWorld realizado em Berlim no mês passado, percebi de vez que a forma como vejo o ecossistema Rails, mudou muito. Hoje existe um horizonte de possibilidades para criação de aplicações web com Rails com um cardápio grande de opções: Esbuild, ImportMaps, Hotwire, Kamal e etc. Estou bem animado com todas as alternativas que temos e que teremos em breve no ecossistema Rails.
Turbo Native
Há a algum tempo, venho acompanhando o perfil no Twitter (X) do Joe Masilotti, The turbo native guy como ele se auto proclama. Esse era o ponto no qual eu mais duvidava, “aplicativos de celular com Rails?, não me parece uma boa ideia”. Esse pensamento surgiu em mim diante de tantas discussões a respeito de React Native e Flutter, parecem duas torcidas rivais e fervorosas para provar qual a melhor tecnologia.
O Joe foi um dos palestrantes do Rails World e na minha opinião, entregou uma das melhores palestras do evento. Este post basicamente replica e acrescenta algumas considerações ao que foi visto na palestra do Joe. Deixarei o link da palestra ao final deste post e o link para o Twitter do Joe também, vale bastante a pena segui-lo.
Como funciona isso e por que?
Bom, pra quem conhece o conceito de webview em aplicações mobile, não é nada revolucionário. Resumindo de forma muito simples, é um app mobile que exibe um app web. Ou seja, teremos uma aplicação web Rails sendo exibida dentro de um app mobile, neste caso específico iOS.
Já ouvi várias coisas negativas sobre a abordagem de webview, desde que ouvi pela primeira vez sobre ferramentas como Ionic lá em 2014. Concordo com grande parte dos pontos negativos que ouvi naquela época, porém temos de levar em consideração que não estamos mais em 2014 e os devices mudaram muito, principalmente em capacidade de processamento, memória e etc.
Tendo tudo isso em mente, tenho a impressão que estamos entrando em uma nova era do desenvolvimento de software em que as pessoas estão cada vez mais pragmáticas e simplistas, isso faz parte de um conjunto de teorias, pensamentos e opiniões que venho acompanhando e que faz sentido (para mim). Acredito que muito vem dos resultados falhos de overengineering que obtivemos nos últimos anos com separação de back e front, microservices e etc sem que haja de fato um motivo real para aderir a estas técnicas.
Joe cita na palestra um outro exemplo, empresas/pessoas criando apps nativos visando performance e extrair o máximo dos devices sem que haja a necessidade real disso, ou seja, grande parte dos apps mobile não precisam extrair o máximo do aparelho, elas precisam renderizar algumas views, realizar algumas operações de crud e etc. Mais uma vez, estou de acordo com isso e pra mim o uso do Turbo Native faz sentido neste momento.
Criando o projeto
Vamos começar criando um projeto simples em Rails, o intuito do post é criar um app rails e fazer com que o mesmo apareça em um iOS simulator (infelizmente apenas para usuários de Mac, mas sinta-se a vontade para fazer o mesmo para apps Android).
rails new iosapp -T -css tailwind
Vamos adicionar apenas um scaffold ao projeto para que possamos ver o resultado no simulador do iOS.
rails g scaffold Post title body:text
Execute as migrações:
rails db:migrate
Adicione um root_path (root_url) no arquivo routes.rb
:
root "posts#index"
Execute o app:
./bin/dev
Agora acesse o seu browser em localhost:3000
e crie alguns posts.
Assim está o meu app no browser após adicionar alguns estilos utilizando Tailwind:
Criando o app iOS
Neste passo é necessário ter o XCode instalado e estar utilizando um Mac. Abra o XCode, no menu principal clique em File, New, Project.
Na caixa de seleção “Choose a template for your new project” selecione iOS » App e clique em Next. Aqui você terá algumas opções para preencher que são obrigatórias, no nosso caso pode desmarcar a opção Include Tests
e na caixa de Interface, selecione StoryBoard.
Acrescentando o Turbo Native como dependência do projeto
Clique no menu File novamente, encontre a opção Add Package Dependecies
, clique nesta opção e selecione o Turbo Native, caso o Turbo Native não apareça para você, digite a url do github no campo Enter Package URL
.
URL: github.com/hotwired/turbo-ios
O único passo necessário por agora é alterar o arquivo swift SceneDelegate
que se encontra na árvore de arquivos exibida no Xcode.
O código ficará da seguinte forma:
import Turbo
import WebKit
import UIKit
let rootUrl = URL(string: "http://127.0.0.1:3000/")!
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
private let navigationController = UINavigationController()
private lazy var session = {
let config = WKWebViewConfiguration()
config.applicationNameForUserAgent = "Turbo Native iOS"
let session = Session(webViewConfiguration: config)
session.delegate = self
return session
}()
// When the app launches
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
window?.rootViewController = navigationController
let proposal = VisitProposal(url: rootUrl, options: VisitOptions())
visit(proposal: proposal)
}
// 1. Create Screen
// 2. Push the Screen
// 3. Render the HTML
private func visit(proposal: VisitProposal) {
let visitable = VisitableViewController(url: proposal.url)
navigationController.pushViewController(visitable, animated: true)
session.visit(visitable, options: proposal.options)
}
}
extension SceneDelegate: SessionDelegate{
// Web view dies
func sessionWebViewProcessDidTerminate(_ session: Session) {
session.reload()
}
// Link is clicked
func session(_ session: Session, didProposeVisit proposal: VisitProposal){
visit(proposal: proposal)
}
// Link fails
func session(_ session: Session, didFailRequestForVisitable visitable: Visitable, error: Error){
print("Failed to visit: \(error.localizedDescription)")
}
}
Aqui, temos algumas coisas relacionadas a navegação do app (que ficam muito bem explicadas pelo Joe no vídeo na Palestra) e logo no começo é possível ver que estamos apontando para algo no endereço localhost:3000
. Sim, é aqui que indicamos ao app iOS onde buscar o seu conteúdo
.
Agora vamos executar o simulador, isso pode ser feito com o atalho: Command + R
E olha só que maravilha!
Nossa aplicação Rails sendo executada como um app mobile iOS. Sensacional!
Conclusão
Este foi um pequeno exemplo de como é rápido criar um app iOS rodando uma aplicação Rails e isso é só o começo, imagina que para algumas atualizações basta apenas atualizar a aplicação Rails e isso já será refletido no App.
Considerações
Como eu disse anteriormente, isso não é a solução para todos os problemas. Mas é uma boa solução para vários. Reitero que é importante assistir a palestra do Joe, onde ele passa mais detalhes e passa até outras coisas como upload de imagens.
É isso, espero que gostem!
Referências
Palestra: Joe Masilotti - Just enough Turbo Native to be dangerous - Rails World 2023
Link para o Workshop do Joe Masilotti: Workshop
Link para Post no blog do Joe: Masilotti