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 内联阈值(以字节为单位) | number |
4096 |
--clearScreen |
允许/禁用日志记录时清除屏幕 | boolean |
|
--config , -c |
使用指定的配置文件 | string |
|
--emptyOutDir |
当 outDir 在根目录之外时强制清空 outDir | boolean |
|
--logLevel , -l |
使用指定的日志级别 | "info" | "warn" | "error" | "silent" | string |
|
--minify |
启用/禁用缩小,或指定要使用的缩小器 | boolean | "terser" | "esbuild" |
"esbuild" |
--mode , -m |
设置 env 模式 | string |
|
--profile |
启动内置的 Node.js 检查器 | ||
--sourcemapClient |
为客户端构建输出源映射 | boolean | "inline" | "hidden" |
false |
--sourcemapServer |
为服务器构建输出源映射 | boolean | "inline" | "hidden" |
false |
remix vite:dev
使用 Remix Vite 在开发模式下运行你的应用。
remix vite:dev
标志 | 描述 | 类型 | 默认值 |
---|---|---|---|
--clearScreen |
允许/禁用日志记录时清除屏幕 | boolean |
|
--config , -c |
使用指定的配置文件 | string |
|
--cors |
启用 CORS | boolean |
|
--force |
强制优化器忽略缓存并重新打包 | boolean |
|
--host |
指定主机名 | string |
|
--logLevel , -l |
使用指定的日志级别 | "info" | "warn" | "error" | "silent" | string |
|
--mode , -m |
设置 env 模式 | string |
|
--open |
在启动时打开浏览器 | boolean | string |
|
--port |
指定端口 | number |
|
--profile |
启动内置的 Node.js 检查器 | ||
--strictPort |
如果指定的端口已被占用则退出 | boolean |
remix build
使用 经典 Remix 编译器 构建你的生产应用。此命令会将 process.env.NODE_ENV
设置为 production
,并压缩输出以进行部署。
remix build
选项 | 标记 | 配置 | 默认值 |
---|---|---|---|
为生产构建生成 sourcemaps | --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 不支持请求处理之外的异步 I/O(如 fetch
)。
选项优先级顺序为:1. 标记,2. 配置,3. 默认值。
选项 | 标记 | 配置 | 默认值 | 描述 |
---|---|---|---|---|
命令 | -c / --command |
命令 |
remix-serve <服务器构建路径> |
用于运行你的应用服务器的命令 |
手动 | --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
毫秒来启动新的代码更改如果你正在使用 monorepo,你可能希望 Remix 不仅在你的应用代码更改时执行热更新,还希望在你更改任何应用的依赖项中的代码时执行热更新。
例如,你可以有一个 UI 库包 (packages/ui
),它在你的 Remix 应用 (packages/app
) 中使用。要获取 packages/ui
中的更改,你可以配置 watchPaths 以包含你的包。
要在开发中使用 Mock Service Worker,你需要
确保你在 -c
标记中为你的应用服务器设置模拟,以便 REMIX_DEV_ORIGIN
环境变量可用于你的模拟。例如,你可以在运行 remix-serve
时使用 NODE_OPTIONS
来设置 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 的限制和常见问题的解决方法。
热数据重新验证通过尝试捆绑每个加载器,然后为每个加载器的内容进行指纹识别来检测加载器更改。它依赖于摇树优化来确定你的更改是否会影响每个加载器。
为确保摇树优化可以可靠地检测到加载器的更改,请确保声明你的应用的包是无副作用的
{
"sideEffects": false
}
当你删除加载器或删除该加载器返回的某些数据时,你的应用应正确热更新。但是你可能会注意到浏览器中记录的控制台错误。
应用热更新时,React 严格模式和 React Suspense 可能会导致多次渲染。其中大多数渲染是正确的,包括你看到的最终渲染。但是,中间渲染有时会使用带有旧 React 组件的新加载器数据,这就是这些错误出现的原因。
我们正在继续调查潜在的竞争条件,以查看是否可以解决该问题。同时,如果这些控制台错误困扰你,你可以在每次发生这些错误时刷新页面。
当 Remix 编译器构建(和重新构建)你的应用时,你可能会注意到,随着编译器需要爬取每个加载器的依赖项,速度会稍微变慢。这样,Remix 可以在重新构建时检测到加载器更改。
虽然初始构建变慢是 HDR 的固有代价,但我们计划优化重建,以便 HDR 重建不会出现可察觉的减速。