通过这篇文章,我想用我一贯的80/20方法帮助你开始使用Remix:跳过花哨的东西,学习核心的东西。
什么是Remix?它是一个新的基于React的框架,刚刚达到1.0版本,并以MIT许可公开发布,这是我们都喜欢的许可。
注意:直到昨天,它还是赞助商软件,现在它是公开和免费的。
你知道Next.js吗?或者SvelteKit?嗯,Remix是类似的东西,但有一些独特的功能,使它成为一个有趣的选择。但是它没有静态网站支持,所以它总是需要一个服务器。这使得它在某些情况下是好的,在其他情况下是坏的。
对那些有数据库、动态数据、有私人数据的用户账户等使用情况来说是好的。比如Rails、Django或Laravel应用。
或者在JS世界里,它更像是RedwoodJS或Blitz.js的替代品,也就是说,它更多地是关于构建应用程序而不是网站。
是的,这看起来是一个很好的桶,可以把它定位到。
我们使用npx
,创建一个新的Remix项目,所以我们不需要安装任何东西,甚至不需要在前面创建一个文件夹。
只要在包含你的项目的文件夹中(对我来说通常是dev
或www
),然后输入
npx create-remix@latest
选择你想安装的文件夹。
选择Remix App Server选项,也就是内置的服务器(你可以稍后更改)。
选择JavaScript,或者TypeScript(如果你愿意)。
确保你告诉安装程序运行npm install
,这样它就能为你设置好一切。
然后cd <foldername>
,并运行npm run dev
。
看看默认安装的结果总是好的。
产生这个的代码是这样的。
但我们实际上只对app
文件夹感兴趣,其余的是锅炉板/配置。
让我们来分析一下。
在src
文件夹中,我们有3个文件。
entry.client.jsx
entry.server.jsx
root.jsx
它们用于设置网站的整体功能,包括所有页面的HTML输出。它们是那些如果你碰了它们,整个应用程序就会受到影响的文件。这也是错误处理的地方,这是Remix的一个一流的方面,这有点酷。
然后我们有一个routes
文件夹,里面有一个index.jsx
文件,还有一个demos
文件夹,里面有一些演示应用程序。
让我们从routes/index.jsx
开始。
这是一个很长的React组件。
import { useLoaderData, json, Link } from "remix";
// Loaders provide data to components and are only ever called on the server, so
// you can connect to a database or run any server side code you want right next
// to the component that renders it.
// https://remix.run/api/conventions#loader
export let loader = () => {
let data = {
resources: [
{
name: "Remix Docs",
url: "https://remix.run/docs"
},
{
name: "React Router Docs",
url: "https://reactrouter.com/docs"
},
{
name: "Remix Discord",
url: "https://discord.gg/VBePs6d"
}
],
demos: [
{
to: "demos/actions",
name: "Actions"
},
{
to: "demos/about",
name: "Nested Routes, CSS loading/unloading"
},
{
to: "demos/params",
name: "URL Params and Error Boundaries"
}
]
};
// https://remix.run/api/remix#json
return json(data);
};
// https://remix.run/api/conventions#meta
export let meta = () => {
return {
title: "Remix Starter",
description: "Welcome to remix!"
};
};
// https://remix.run/guides/routing#index-routes
export default function Index() {
let data = useLoaderData();
return (
<div className="remix__page">
<main>
<h2>Welcome to Remix!</h2>
<p>We're stoked that you're here. 🥳</p>
<p>
Feel free to take a look around the code to see how Remix does things,
it might be a bit different than what you’re used to. When you're
ready to dive deeper, we've got plenty of resources to get you
up-and-running quickly.
</p>
<p>
Check out all the demos in this starter, and then just delete the{" "}
<code>app/routes/demos</code> and <code>app/styles/demos</code>{" "}
folders when you're ready to turn this into your next project.
</p>
</main>
<aside>
<h2>Demos In This App</h2>
<ul>
{data.demos.map(demo => (
<li key={demo.to} className="remix__page__resource">
<Link to={demo.to} prefetch="intent">
{demo.name}
</Link>
</li>
))}
</ul>
<h2>Resources</h2>
<ul>
{data.resources.map(resource => (
<li key={resource.url} className="remix__page__resource">
<a href={resource.url}>{resource.name}</a>
</li>
))}
</ul>
</aside>
</div>
);
}
现在,这个文件可以简化成一个超级简单的React组件,就像这样。
export default function() {
return (
<div className="remix__page">
Test
</div>
);
}
如果你这样做并保存该文件,你会在应用程序中看到这个。
但这个文件所做的事情不仅仅是输出一些JSX。它正在通过loader()
函数在服务器端加载数据。
import { json } from "remix";
export let loader = () => {
let data = {
//.... some data
};
return json(data);
};
json()
是一个特殊的工具,可以轻松地创建一个JSON端点,当页面加载时,Remix将调用该端点,以填充它所需要的数据。
这个loader()
函数在渲染前被调用,并且只在服务器端运行。
为了在组件的JSX中使用这些数据,我们必须导入并调用useLoaderData()
。
import { useLoaderData, json } from "remix"
export let loader = () => json({
name: 'Flavio'
})
export default function() {
let data = useLoaderData()
return (
<div className="remix__page">
Hi {data.name}
</div>
)
}
该文件还导出了一个meta()
函数,用于设置页面HTML头部的元数据。
路由是Remix中的 "肉 "发生的地方。这是可以理解的,因为它是由制作React Router的人创建的,所以路由器是应用程序的中心部分。
官方教程已经谈到了创建自定义路由和处理表单,所以我现在就不多说了。
我建议你看一下,特别是表单。
为什么?因为在React中,表单是一个很大的问题,所以很高兴看到这种非常简单的方法,允许你创建表单,而不需要写很多很多的模板代码。
我认为这是Remix最棒的部分,如果我想拥有一个拥有一流表单的网站,我会考虑使用它,以避免使用我需要从头开始学习的库,并且是另一个需要担心的依赖。
另一个有趣的事情是子路由,这基本上复制了我们在前React时代用Ember和它的出口做的事情,这很有意义,因为我记得Ryan Florence当年在Ember社区很活跃。
很高兴看到这个领域的进展,在这个领域中,没有任何大的现任者,Next.js基本上是房间里的大象,到目前为止,当涉及到编写应用程序时,我都会默认使用它。
目前,我仍然会默认它。我喜欢新技术,但它也需要很长的时间才能变得成熟,让人们编写库、教程,等等等等。
但竞争会促进创新,所以有一个足够奇特的选择总是好的,不会成为现有替代品的山寨品。