Remix CLI 来自 @remix-run/dev
包。它还包含编译器。确保它在你的 package.json
devDependencies
中,这样它就不会被部署到你的服务器上。
要获取可用命令和标志的完整列表,请运行
npx @remix-run/dev -h
remix vite:build
使用 Remix Vite 构建你的应用以供生产使用。此命令会将 process.env.NODE_ENV
设置为 production
并压缩输出以进行部署。
remix vite:build
标志 | 描述 | 类型 | 默认值 |
---|---|---|---|
--assetsInlineLimit |
静态资产 base64 内联阈值,以字节为单位 | 数字 |
4096 |
--clearScreen |
允许/禁止在记录时清除屏幕 | 布尔值 |
|
--config , -c |
使用指定的配置文件 | 字符串 |
|
--emptyOutDir |
当 outDir 在根目录之外时,强制清空 outDir | 布尔值 |
|
--logLevel , -l |
使用指定的日志级别 | "info" | "warn" | "error" | "silent" | 字符串 |
|
--minify |
启用/禁用压缩,或指定要使用的压缩器 | 布尔值 | "terser" | "esbuild" |
"esbuild" |
--mode , -m |
设置环境模式 | 字符串 |
|
--profile |
启动内置 Node.js 检查器 | ||
--sourcemapClient |
为客户端构建输出源映射 | 布尔值 | "inline" | "hidden" |
false |
--sourcemapServer |
为服务器构建输出源映射 | 布尔值 | "inline" | "hidden" |
false |
remix vite:dev
使用 Remix Vite 在开发模式下运行你的应用程序。
remix vite:dev
标志 | 描述 | 类型 | 默认值 |
---|---|---|---|
--clearScreen |
允许/禁止在记录时清除屏幕 | 布尔值 |
|
--config , -c |
使用指定的配置文件 | 字符串 |
|
--cors |
启用 CORS | 布尔值 |
|
--force |
强制优化器忽略缓存并重新打包 | 布尔值 |
|
--host |
指定主机名 | 字符串 |
|
--logLevel , -l |
使用指定的日志级别 | "info" | "warn" | "error" | "silent" | 字符串 |
|
--mode , -m |
设置环境模式 | 字符串 |
|
--open |
在启动时打开浏览器 | 布尔值 | 字符串 |
|
--port |
指定端口 | 数字 |
|
--profile |
启动内置 Node.js 检查器 | ||
--strictPort |
如果指定的端口已被使用,则退出 | 布尔值 |
remix build
使用 经典 Remix 编译器 构建你的应用以供生产使用。此命令会将 process.env.NODE_ENV
设置为 production
并压缩输出以进行部署。
remix build
选项 | 标志 | 配置 | 默认值 |
---|---|---|---|
为生产构建生成源映射 | --sourcemap |
N/A | false |
remix dev
以监视模式运行 经典 Remix 编译器 并启动你的应用程序服务器。
Remix 编译器将
NODE_ENV
设置为 development
🎥 要了解 Remix 中 HMR 和 HDR 的介绍和深入分析,请查看我们的视频
什么是“热数据重新验证”?
与 HMR 一样,HDR 是一种热更新应用程序的方法,无需刷新页面。这样,你可以在你的应用程序中应用编辑时保留应用程序状态。HMR 处理客户端代码更新,例如当你更改应用程序中的组件、标记或样式时。同样,HDR 处理服务器端代码更新。
这意味着,只要你在当前页面更改了 loader
(或任何你的 loader
依赖的代码),Remix 就会重新获取你更改过的 loader 的数据。这样,你的应用程序始终保持最新,无论是在客户端还是服务器端。
要了解更多关于 HMR 和 HDR 如何协同工作的信息,请查看 Pedro 在 Remix Conf 2023 上的演讲。
如果你使用模板开始,希望它已经与 remix dev
无缝集成。如果不是,你可以按照以下步骤将你的项目与 remix dev
集成。
替换 package.json
中的开发脚本,并使用 -c
指定你的应用程序服务器命令。
{
"scripts": {
"dev": "remix dev -c \"node ./server.js\""
}
}
确保应用程序服务器启动并运行后调用 broadcastDevReady
。
import path from "node:path";
import { broadcastDevReady } from "@remix-run/node";
import express from "express";
const BUILD_DIR = path.resolve(__dirname, "build");
const build = require(BUILD_DIR);
const app = express();
// ... code for setting up your express app goes here ...
app.all("*", createRequestHandler({ build }));
const port = 3000;
app.listen(port, () => {
console.log(`👉 https://127.0.0.1:${port}`);
if (process.env.NODE_ENV === "development") {
broadcastDevReady(build);
}
});
对于 CloudFlare,使用 logDevReady
代替 broadcastDevReady
。
为什么?broadcastDevReady
使用 fetch
将就绪消息发送到 Remix 编译器,但 CloudFlare 不支持像 fetch
这样的异步 I/O,除非在请求处理中。
选项优先级顺序:1. 标志,2. 配置,3. 默认值。
选项 | 标志 | 配置 | 默认值 | 描述 |
---|---|---|---|---|
命令 | -c / --command |
命令 |
remix-serve <server build path> |
用于运行你的应用程序服务器的命令。 |
手动 | --manual |
手动 |
false |
查看 手动模式指南。 |
端口 | --port |
port |
动态选择的开放端口 | Remix 编译器用于热更新的内部端口。 |
TLS 密钥 | --tls-key |
tlsKey |
N/A | 用于配置本地 HTTPS 的 TLS 密钥。 |
TLS 证书 | --tls-cert |
tlsCert |
N/A | 用于配置本地 HTTPS 的 TLS 证书。 |
例如
/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
dev: {
// ...any other options you want to set go here...
manual: true,
tlsKey: "./key.pem",
tlsCert: "./cert.pem",
},
};
remix dev --port
选项设置用于热更新的内部端口。它不会影响你的应用程序运行的端口。
要设置你的应用程序服务器端口,按照你通常在生产环境中的设置方法进行设置。例如,你可能在 server.js
文件中进行了硬编码。
如果你使用 remix-serve
作为你的应用程序服务器,你可以使用它的 --port
标志设置应用程序服务器端口。
remix dev -c "remix-serve --port 8000 ./build/index.js"
相反,remix dev --port
选项是为需要对网络端口进行精细控制的用户提供的备用方案。大多数用户不应该使用 remix dev --port
。
默认情况下,remix dev
会在每次重建时重新启动你的应用程序服务器。如果你想在重建时保持应用程序服务器运行而无需重新启动,请查看我们的 手动模式指南。
你可以通过比较 remix dev
报告的时间来查看应用程序服务器重启是否成为你项目的瓶颈。
rebuilt (Xms)
👉 Remix 编译器花费了 X
毫秒重建你的应用程序。app server ready (Yms)
👉 Remix 重新启动了你的应用程序服务器,并且它花费了 Y
毫秒使用新的代码更改启动。如果你使用的是单体仓库,你可能希望 Remix 不仅在你的应用程序代码更改时执行热更新,而且在你的任何应用程序依赖项的代码更改时也执行热更新。
例如,你可能有一个在你的 Remix 应用程序(packages/app
)中使用的 UI 库包(packages/ui
)。要获取 packages/ui
中的更改,你可以配置 watchPaths 以包含你的包。
要在开发中使用 Mock Service Worker,你需要
确保你在 -c
标志中为你的应用程序服务器设置你的模拟,以便 REMIX_DEV_ORIGIN
环境变量对你的模拟可用。例如,你可以使用 NODE_OPTIONS
在运行 remix-serve
时设置 Node 的 --require
标志。
{
"scripts": {
"dev": "remix dev -c \"npm run dev:app\"",
"dev:app": "cross-env NODE_OPTIONS=\"--require ./mocks\" remix-serve ./build"
}
}
如果你使用 ESM 作为默认模块系统,你需要设置 --import
标志而不是 --require
标志。
{
"scripts": {
"dev": "remix dev -c \"npm run dev:app\"",
"dev:app": "cross-env NODE_OPTIONS=\"--import ./mocks/index.js\" remix-serve ./build/index.js"
}
}
接下来,你可以使用 REMIX_DEV_ORIGIN
让 MSW 在 /ping
上转发内部“开发就绪”消息。
import { http, passthrough } from "msw";
const REMIX_DEV_PING = new URL(
process.env.REMIX_DEV_ORIGIN
);
REMIX_DEV_PING.pathname = "/ping";
export const server = setupServer(
http.post(REMIX_DEV_PING.href, () => passthrough())
// ... other request handlers go here ...
);
假设你的应用程序服务器和 Remix 编译器都在同一台机器上运行。
https://127.0.0.1:1234
https://127.0.0.1:5678
然后,你在应用程序服务器前面设置一个反向代理。
https://myhost
但是,用于支持热更新的内部 HTTP 和 WebSocket 连接仍然会尝试到达 Remix 编译器未经代理的源。
https://127.0.0.1:5678
/ ws://127.0.0.1:5678
❌要让内部连接指向反向代理,你可以使用 REMIX_DEV_ORIGIN
环境变量。
REMIX_DEV_ORIGIN=https://myhost remix dev
现在,热更新将正确地发送到代理。
https://myhost
/ wss://myhost
✅目前,当 Remix 重建你的应用程序时,编译器必须处理你的应用程序代码及其所有依赖项。编译器会从应用程序中剔除未使用的代码,这样你就不会将任何未使用的代码发布到浏览器,并且你的服务器也能尽可能地保持精简。但是,编译器仍然需要遍历所有代码才能知道保留哪些代码,剔除哪些代码。
简而言之,这意味着你的导入和导出方式会对重建应用程序所需的时间产生很大影响。例如,如果你使用的是 Material UI 或 AntD 等库,你很可能可以通过使用 路径导入 来加快构建速度。
- import { Button, TextField } from '@mui/material';
+ import Button from '@mui/material/Button';
+ import TextField from '@mui/material/TextField';
将来,Remix 可能会在开发中预先打包依赖项以完全避免这个问题。但现在,你可以通过使用路径导入来帮助编译器。
根据你的应用程序和依赖项,你可能正在处理比应用程序需要的代码多得多的代码。查看我们的 捆绑包分析指南 以了解更多详细信息。
如果你希望热更新但得到的是完整页面重新加载,请查看我们的 关于热模块替换的讨论,以了解有关 React Fast Refresh 限制以及常见问题解决方法的更多信息。
热数据重新验证通过尝试捆绑每个 loader,然后对每个 loader 的内容进行指纹识别来检测 loader 更改。它依赖于树摇动来确定你的更改是否影响了每个 loader。
要确保树摇动能够可靠地检测到对 loader 的更改,请确保声明你的应用程序的包是无副作用的。
{
"sideEffects": false
}
当你删除一个 loader 或删除该 loader 返回的一些数据时,你的应用程序应该会正确地进行热更新。但你可能会注意到浏览器中记录的控制台错误。
React 严格模式和 React Suspense 在应用热更新时可能会导致多次渲染。大多数渲染都正确,包括对你可见的最终渲染。但是,中间渲染有时可能会将新的 loader 数据与旧的 React 组件一起使用,这就是这些错误的来源。
我们正在继续调查潜在的竞争条件,看看我们是否可以解决这个问题。在此期间,如果这些控制台错误困扰你,你可以在它们出现时刷新页面。
当 Remix 编译器构建(和重建)你的应用程序时,你可能会注意到轻微的减速,因为编译器需要遍历每个 loader 的依赖项。这样,Remix 就可以在重建时检测到 loader 更改。
虽然初始构建减速本质上是 HDR 的成本,但我们计划优化重建,以便 HDR 重建不会出现明显的减速。