最近, Laravel团队使得只用一个命令就可以轻松建立一个React堆栈, 使Laravel成为一个可行的全栈React框架。
你说,这很疯狂吗?那么,是什么让Next.js和其他类似的React框架如此伟大?
它们之所以伟大,是因为它们允许更好的服务器端渲染,路由,认证,状态管理和会话管理,至少可以这么说。
在这篇文章中, 我们将告诉你为什么Laravel Breeze的Inertia-React堆栈比Next或Gatsby要好得多,也更容易使用。尽管这是关于Laravel作为React框架的适用性,但其中许多观点也可以在Vue或Svelte背景下理解!
什么是Laravel Breeze?
Laravel Breeze是在2020年秋季与Laravel 8一起推出的入门套件之一 - 另一个是Jetstream。Laravel Breeze和Jetstream都带有内置的认证,以及路由,控制器和视图,你需要快速建立一个大型应用程序。Breeze还带有前台脚手架。两者都是用Tailwind CSS来设计风格。
虽然你可以在Laravel Breeze中使用普通的Blade模板, 但你也可以使用Inertia.js栈。
把Inertia.js想象成一个适配器,连接两个没有直接工作的设备:而不是创建一个REST API,Inertia.js允许开发人员将React, Vue, 或Svelte前端与他们的Laravel后端连接起来。
说说你对PHP的看法,但它有很多工具是开箱即用的。是的, 当使用这样一个堆栈而不是一个全JavaScript堆栈时, 是有取舍的, 但这是建立一个强大的单体的好方法 - 这样, 我们可以同时拥有PHP在后端和JavaScript框架在前端的优点.
为什么你应该选择Laravel Breeze作为你的下一个React框架?
设置是,嗯,轻而易举的
开发人员只需要在App.js ,翻看几行代码,就可以让React和Laravel相互对话。
在Laravel团队让Inertia-React堆栈变得简单之前, 开发者不得不做大量的手工工作来让Inertia与React一起工作, 因为Vue是默认的。
现在,开发人员根本不需要写任何东西,因为脚手架是通过运行php artisan breeze:install react 自动完成的。
App.js 文件将看起来像这样。
js
require('./bootstrap')
// Import modules...
import React from "react"
import { render } from "react-dom"
import { InertiaApp } from "@inertiajs/inertia-react"
import { InertiaProgress } from '@inertiajs/progress'
const el = document.getElementById('app')
render(
<InertiaApp
initialPage={el ? JSON.parse(el.dataset.page) : "{}"}
resolveComponent={(name) => require(`./Pages/${name}`).default}
/>,
el
);
InertiaProgress.init({ color: '#4B5563' })
Inertia.js很容易使用
对于一个已经沉浸在JavaScript世界里的开发者来说,如果他们有一些PHP和Laravel的知识,那就几乎没有任何障碍。Inertia的文档非常容易阅读,并且涵盖了你构建应用程序所需的每一个用例。
在过去, 当开发者想拥有一个Laravel后端和一个JavaScript SPA时, 他们必须用Laravel建立一个API并使用一个单独的JavaScript框架.现在, 开发者可以直接使用 Inertia.
它的工作方式是相当天才的:第一次访问页面时加载纯HTML,然后将数据加载到页面上--无需通过XHR和JSON的方式完全重新加载。Inertia还消除了对REST API的需求,让开发者有能力用React前端和PHP后端构建一个大而美的SPA。
它还使直接从数据库向客户端传递数据变得极其简单,消除了其他框架为做同样事情而需要的额外的前端库(如Axios)。
为了说明这一点,让我们比较一下用Laravel API和用Next构建的SPA从客户端向后端发送数据的方式,以及用Inertia做这个的新方式。
Next.js应用程序的数据共享与Laravel Breeze和Inertia.js的比较
首先, 开发者安装和设置类似Laravel Sanctum的东西,以确保请求是通过令牌,cookies,或一些组合来授权的。然后, 他们将需要安装和设置CORS包,以防止CORS问题。
当这些都设置好了,包括中间件,以防止在前端需要CSRF保护,路由设置在routes/api.php 。
所以,假设我们需要一个路由来创建一个银行账户。我们的路由将看起来像这样,其中createAccount 是控制器方法,将处理来自前端的请求。
php
Route::post('create-account', [AccountController::class, 'createAccount']);
然后在Next SPA中,需要做额外的工作以确保CORS和认证问题不会发生。
前端开发者应该非常熟悉CORS问题,当前端和后端分开托管时,它们很可能会出现。为了解决这些问题并处理cookies和其他因素,开发者最终会安装一个认证库,如NextAuth.js或next-iron-session。
当所有这些都设置好后,创建账户的函数将使用fetch 或axios 来提交数据并等待来自API的响应。该函数将看起来像这样。
js
import axios from 'axios'
…
const [account, setAccount] = useState({
phone: "", street: "", unit: "", city: "", state: "", zip: ""
})
async function handleSubmit(){
try {
const accountData = JSON.stringify(account)
const response = await axios(`${apiUrl}/create-account`, accountData, {
header: {
'Authorization': `Bearer ${user.token}`,
}
})
console.log(response.message)
}
catch(e){
console.log(e.errors)
}
}
这是个很大的工作!
有了Inertia,就不需要安装额外的库或写这么多行代码来处理CORS问题和认证。
开发者唯一要做的就是在Laravel和Inertia之间共享数据, 这样数据就会在第一次访问后的后续渲染中发送, 设置路由, 并使用Inertia访问来提交和获取数据.
Inertia访问基本上是Inertia工作方式的核心:当我们点击Inertia<Link /> 或通过手动访问进行编程(下面会有更多介绍),库执行XHR而不是页面重新加载。JSON从服务器返回,Inertia的客户端用新的数据交换旧的数据。
在Laravel和Inertia之间有不同的方法来分享数据, 但就我个人而言, 我喜欢使用闪烁的信息.要做到这一点, 我只需在app/Providers/AppServiceProviders.php:
php
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\ServiceProvider;
use Inertia\Inertia;
class AppServiceProvider extends ServiceProvider
{
...
public function boot()
{
Inertia::share('flash', function(){
return [
'message' => Session::get('message')
];
});
}
}
路线可以看起来和上面一样,我可以在我的前端使用手动访问,其中的方法如onStart,onSuccess, 和onError 帮助在数据交换之前,期间和之后执行事件。
手动访问模仿了Promises,但使创建和处理事件比链式then 语句更好。让我来演示一下。
js
const [account, setAccount] = useState({
phone: "", street: "", unit: "", city: "", state: "", zip: ""
})
function handleSubmit(){
const accountData = JSON.stringify(account)
Inertia.post(`create-account`, {data: accountData}, {
onStart: () => {
// Do something the moment request is made
},
onSuccess: response => {
console.log(response.message)
},
onError: e => {
console.log(e.errors)
}
})
}
虽然Inertia应该是框架无关的,但在后端有对Laravel和Rails的第一方支持,在前端有对React, Vue, 和Svelte的支持。
使用Laravel Breeze进行认证
如果你来自Gatsby或Next的世界, 你已经知道认证是多么复杂.即使是建立一个简单的库,你仍然需要花费大量的时间来设置登录和注册页面,令牌,cookies,电子邮件验证,密码重设,以及路由等内容。
Laravel最漂亮的地方是他们的入门套件, 这也是他们如何让认证变得如此简单的很大一部分原因.使用Laravel Breeze, 你可以建立一个登录, 注册, 密码重置, 电子邮件验证, 和密码确认的系统, 只需一个命令!
如果你选择了Inertia-React堆栈, 登录, 注册, 仪表盘页面和他们相应的路线已经为你完成了!你也可以选择通过使用Laravel Passport扩展Breeze来实现OAuth。
与其他方法相比,这是一个巨大的优势,因为你不需要使用库来处理复杂的会话和状态管理,以使认证正常工作。使用Laravel,你所需要的一切认证都是开箱即用的。
改进的会话和状态管理
在React中,如果不使用任何库或包,大型应用程序的会话和状态管理是非常困难的。尽管如此, 在React中处理状态对于Next和Gatsby的会话管理是很重要的.
Laravel让会话和状态管理变得非常简单。对于会话, Laravel为你提供了几种可以存储会话的方式, 包括:
- 文件
- Cookies
- 数据库
- Memcached/Redis
- AWS DynamoDB
- 数组
你甚至可以使用你自己的自定义会话驱动程序。在这里, 与会话的交互和保存只需要两行代码就可以实现.
Laravel Breeze的Inertia-React堆栈进一步否定了在客户端进行任何状态管理的需要, 这使得在构建认证系统或其他需要复杂状态管理的功能时, 有一个完整而愉快的体验。
你也有更复杂的能力来控制你的Laravel应用如何处理会话, 例如限制在同一时间内的HTTP请求的数量.
在Laravel中这样做的代码真的让人想起了JavaScript中的async-await 。当一个请求被发出时, 一个 "会话锁 "就会被获取, 这样一来, 相同会话ID的后续请求就必须等待第一个会话执行完毕才能执行.
如果你看一下下面的代码样本,你会发现这个块方法接受两个参数。
- 第一个参数定义了会话锁在被释放之前的最大保留秒数。
- 第二个参数定义了一个请求应该等待会话锁的秒数。
如果会话锁的获取时间过长,就会抛出一个异常。这是一个规避PHP异步限制的天才方法。
php
Route::post('/profile', function () {
//
})->block($lockSeconds = 10, $waitSeconds = 10)
Route::post('/order', function () {
//
})->block($lockSeconds = 10, $waitSeconds = 10
更容易的客户端资产编译
就像Gatsby和Next一样, Laravel使用webpack来编译客户端的资产.配置webpack并不是一件容易的事情 - 但是Laravel有一个Laravel Mix的形式来解决这个问题。
Laravel Mix可以让你轻松实现各种工具和技术的前端。它是通过提供一个API来决定编译这些资产的构建步骤。
不相信我吗?下面是一个Laravel Mix文件在使用Tailwind(和PostCSS模块), TypeScript, 和React的项目中的样子。
js
const mix = require('laravel-mix');
mix.ts('resources/js/app.tsx', 'public/js')
.react()
.postCss('resources/css/app.css', 'public/css', [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
])
.webpackConfig(require('./webpack.config'))
if (mix.inProduction()) {
mix.version()
}
上面的代码告诉Laravel Mix在resources/js 中寻找App.js 或App.tsx 文件,并将其内容编译为public/js/app.js ,即网页浏览器所读取的JavaScript文件。Chaining thereact() helper 让Laravel Mix知道期待React和JJS - 如果你使用Vue,还有一个vue() helper。
这段代码还告诉Laravel Mix使用PostCSS来编译resources/css/app.css 中的CSS,这些都是Tailwind指令,并将其放置在public/css 。如果开发者想为路径设置别名,他们可以在webpack配置文件中这样做。
就像Gatsby和Next一样,你不必坚持使用Laravel Mix/webpack的默认配置。如果你想使用Vite,Esbuild, 或任何其他类似的构建工具, Laravel也有相关的说明.
使用Laravel Breeze更简单的路由选择
Next和Gatsby都有一个pages ,在这个文件夹里,你可以放置对应于应用程序页面的文件。两者都使用一个路由API,让你使用括号(Gatsby的括号,Next的方括号)作为文件名来表示动态页面。
这两个框架都努力使路由更简单、更直观,但有时它们需要更多的摆弄才能正常工作。而且由于复杂的业务逻辑经常在这些文件中处理,可读性和良好的代码组织往往受到影响。
Laravel是用一个模型-视图-控制器(MVC)架构建立的, 所以它有路由来引导请求从你在前端的视图到你的控制器.MVC架构迫使良好的代码组织实践, 因为你知道你的逻辑将基于你的控制器和你的客户端是通过路由发送请求,并将响应反馈给客户端.
Inertia-React栈在服务器端处理路由,这与用其他框架构建的SPA不同。路由可以在routes 文件夹中找到,在该文件夹中,你可以找到web.php ,你的大部分路由将被放置在那里。所有的JavaScript文件 - 包括项目的React页面, 组件等 - 都可以在resources 文件夹中找到.
请看下面一个Laravel Breeze和React项目的样本,resources 和routes 文件夹是如何设置的。
更灵活的数据管理
Gatsby对数据的处理方式非常有主见,并规定在大多数情况下都要使用GraphQL。这对喜欢GraphQL的开发者来说是很好的,但对那些不喜欢GraphQL的开发者来说就有点麻烦了。Next没有那么多的意见,但是开发者仍然需要安装和设置很多活动部件,以便将数据从数据库中送到客户端。
Laravel的ORM,Eloquent也很有意见,但这个框架的好处是,你可以非常容易地不使用它。相反, 如果你需要的话, 你可以直接用普通的MySQL语句查询数据库, 或者你可以使用你选择的另一个PHP ORM.
一个流行的ORM是Doctrine,它经常被用于其他框架,如Symfony、Zend和CakePHP。如果你想要速度和性能,Doctrine当然是可以考虑的。
然而,如果你关心它与框架其他部分的融合程度,Eloquent是它们中最好的。为了理解这一点,让我们看看在Eloquent和Doctrine中创建数据库表的方式。
Eloquent
php
Schema::create('User', function($table)
{
$table->id();
$table->string('name');
});
教义
php
<?php
use Doctrine\ORM\Mapping AS ORM;
class User
{
private $id;
private $name;
}
?>
就PHP与哪些数据库兼容而言,你几乎不必担心。PHP有多种数据库系统的驱动和扩展,如SQLite,MongoDB和PostgreSQL,所以你不会只停留在MySQL。
Laravel可以帮助你轻松建立REST APIs, 但你也可以用Laravel创建GraphQL APIs!如果你为你的应用程序选择GraphQL API, 你可以选择Rebing的GraphQL库或Lighthouse.
你甚至可以使用GraphQL APIs - 或者任何你能想到的API - 只需要几行代码:
php
use Illuminate\Support\Facades\Http;
$response = Http::get('http://someapi.com');
dd($response); // dump data
享受一个活跃的社区和插件生态系统
尽管它们是以一种有主见的方式建立的,但Gatsby的插件是优秀的和丰富的。接下来也是可扩展的。不过不要被愚弄了--Laravel的插件生态系统远非微不足道。太阳下的所有东西都有一个Laravel插件, 而且它们都被放在一个叫Packalyst的易于使用的目录中.
虽然PHP只用了几行代码来实现一些需要几百或几千行JavaScript的功能, 但对于其他的东西, 有一些插件和库可以很容易地安装在你的项目中。
当然, 如果你的项目有问题, 或者你只是想和其他Laravel开发者交流 - 特别是那些使用Inertia堆栈的开发者 - 有成千上万的开发者, 你可以在Twitter, Stack Overflow, GitHub, 和Discord上关注他们.这是一个亲切的, 欢迎的, 无毒的社区, 很明显, 他们热爱自己使用的技术, 并希望其他人也能热爱这项技术.
广泛采用的路障
SEO是困难的
目前,Inertia.js在客户端渲染网页。Inertia.js的创造者认为,Inertia并不是为需要SEO的网页而制作的,所以创造者应该用Blade来代替这类网页。还有其他的变通方法,如使用元标签,有些人已经开发了变通方法。
不要让这成为一个破坏因素:Inertia.js的SSR模式很快就会出现。值得一提的是,在本文发表之时,GitHub的赞助商可以提前使用它。也有一些生产中的SaaS应用已经成功使用了Inertia.js。
PHP仍然很棘手
虽然我在前面把它列为优点,但公平地说,PHP在某些方面确实比Node.js差,包括并发、异步请求和速度。Node在异步处理方面的优势使得构建时间更快,并增加了应用程序构建方式的灵活性。PHP确实有一些允许异步处理的插件,但这是不一样的。
不过,这不应该让你把PHP放下来。由于有了一个新的充满活力的社区,这种语言正在增加新的功能,并且已经比过去快了很多,也更灵活了。而且它在很多方面的处理仍然比Node好,比如。
- 对数据库的本地支持,如MySQL、MongoDB和PostgreSQL
- 与大多数主机服务提供商的兼容性
- 面向对象的编程
有限的静态生成能力
像Gatsby和Next这样的React框架可以将页面预渲染成静态HTML、CSS和JS文件。最近,随着Jamstack和无服务器架构的采用激增,静态网站的生成已经成为一个不断增长的范式。
因此,开发人员一直渴望切换到这些和其他类似的框架,这样他们就可以通过只关注前端和数据输入应用的方式来构建全栈应用。
然而,应用程序可以被分解成碎片,其中许多功能和能力是由第三方API和微服务处理的。当然,Laravel Breeze也可以利用第三方服务,但支撑Inertia的概念是,建立强大的单体是你唯一需要做的事情。
为什么你想建立一个单体呢?这里有几个原因。
- 单片机的复杂性较低,更容易维护 - 微服务只会增加应用程序的复杂性,因为有更多的移动部件和区域需要监控
- 这是构建应用程序的传统方式,也是大多数开发人员,特别是更资深的开发人员,学习制作应用程序的方式。这使得它们对许多开发者来说更容易构建
- 部署单体是一个更简单的过程,因为所有的部分都在一个地方,而且由于它们是使用相同的语言或框架构建的,所以保证了它们的工作。
- 调试和测试一个单体应用要简单得多 - 通过一个不可分割的单元, 开发者可以运行简单的端到端测试
如果你想使用Laravel,但也想使用Jamstack,你可以看看其他基于Laravel的技术,如Statamic和Jigsaw。通过这些工具, 你可以获得CMS功能和使用PHP构建的乐趣, Blade模板, 以及其他Laravel功能.
总结
一些开发者抱怨Laravel做了太多的 "魔法",他们没有其他PHP框架的控制能力。但他们错了, 因为Laravel提供了开发者所需要的所有控制,而且代码的抽象性有助于获得更好的开发者体验。
这就是为什么Laravel是迄今为止最受欢迎的PHP框架和最受欢迎的后端框架的原因。另外,一种神奇的感觉不正是一个伟大的框架的标志吗?
作为开发者,我们使用框架来使构建复杂的应用程序更容易,而Laravel,尤其是Laravel Breeze的Inertia-React栈,使构建复杂的React应用程序变得异常简单。
当许多应用程序开发人员去做无服务器,并把他们的应用程序分成许多部分时,Inertia已经证明,你可以建立大而强大的React SPA单体。仅就状态和会话管理而言,Laravel Breeze的Inertia-React堆栈与竞争对手相比是值得一试的。
The postLaravel Breeze's Inertia-React stack vs. Next.js and Gatsbyappeared first onLogRocket Blog.