-
built-in tls support (#6483)
New options:
--tls-key
/tlsKey
: TLS key--tls-cert
/tlsCert
: TLS Certificate
If both TLS options are set,
scheme
defaults tohttps
Install mkcert and create a local CA:
brew install mkcert mkcert -install
Then make sure you inform
node
about your CA certs:export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"
👆 You'll probably want to put that env var in your scripts or
.bashrc
/.zshrc
Now create
key.pem
andcert.pem
:mkcert -key-file key.pem -cert-file cert.pem localhost
See
mkcert
docs for more details.Finally, pass in the paths to the key and cert via flags:
remix dev --tls-key=key.pem --tls-cert=cert.pem
or via config:
module.exports = { future: { unstable_dev: { tlsKey: "key.pem", tlsCert: "cert.pem", }, }, };
That's all that's needed to set up the Remix Dev Server with TLS.
🚨 Make sure to update your app server for TLS as well.
For example, with
express
:import express from "express"; import https from "node:https"; import fs from "node:fs"; let app = express(); // ...code setting up your express app... let appServer = https.createServer( { key: fs.readFileSync("key.pem"), cert: fs.readFileSync("cert.pem"), }, app ); appServer.listen(3000, () => { console.log("Ready on https://localhost:3000"); });
remix-serve
does not yet support TLS. That means this only works for custom app server using the-c
flag for now. -
Reuse dev server port for WebSocket (Live Reload,HMR,HDR) (#6476)
As a result the
webSocketPort
/--websocket-port
option has been obsoleted. Additionally, scheme/host/port options for the dev server have been renamed.Available options are:
Option flag config default Command -c
/--command
command
remix-serve <server build path>
Scheme --scheme
scheme
http
Host --host
host
localhost
Port --port
port
Dynamically chosen open port No restart --no-restart
restart: false
restart: true
Note that scheme/host/port options are for the dev server, not your app server. You probably don't need to use scheme/host/port option if you aren't configuring networking (e.g. for Docker or SSL).
-
Add caching to PostCSS for regular stylesheets (#6505)
-
Fix warnings when importing CSS files with
future.unstable_dev
enabled (#6506) -
Fix Tailwind performance issue when
postcss.config.js
containsplugins: { tailwindcss: {} }
andremix.config.js
contains bothtailwind: true
andpostcss: true
. (#6468)Note that this was not an issue when the plugin function had been explicitly called, i.e.
plugins: [tailwindcss()]
. Remix avoids adding the Tailwind plugin to PostCSS if it's already present but we were failing to detect when the plugin function hadn't been called — either because the plugin function itself had been passed, i.e.plugins: [require('tailwindcss')]
, or the plugin config object syntax had been used, i.e.plugins: { tailwindcss: {} }
. -
Faster server export removal for routes when
unstable_dev
is enabled. (#6455)Also, only render modulepreloads on SSR. Do not render modulepreloads when hydrated.
-
Add
HeadersArgs
type to be consistent with loaders/actions/meta and allows for using afunction
declaration in addition to an arrow function expression (#6247)import type { HeadersArgs } from "@remix-run/node"; // or cloudflare/deno export function headers({ loaderHeaders }: HeadersArgs) { return { "x-my-custom-thing": loaderHeaders.get("x-my-custom-thing") || "fallback", }; }
-
better error message when
remix-serve
is not found (#6477) -
restore color for app server output (#6485)
-
Fix route ranking bug with pathless layout route next to a sibling index route (#4421)
- Under the hood this is done by removing the trailing slash from all generated
path
values since the number of slash-delimited segments counts towards route ranking so the trailing slash incorrectly increases the score for routes
- Under the hood this is done by removing the trailing slash from all generated
-
Support sibling pathless layout routes by removing pathless layout routes from the unique route path checks in conventional route generation since they inherently trigger duplicate paths (#4421)
-
fix dev server crashes caused by ungraceful hdr error handling (#6467)
-
Updated dependencies:
@remix-run/[email protected]
- Cross-module
loader
change detection for HDR (#6299) - Normalize path for dev server
PATH
envvar so that it works cross-platform (e.g. Windows) (#6310) - Fix CSS imports in JS files that use JSX (#6309)
- Kill app server when dev server exits (#6395)
- Wait until app server is killed before starting a new app server (#6289)
- Ensure CSS bundle changes result in a new manifest hash (#6374)
- Normalize file paths before testing if a changed file is a route entry (#6293)
- Fix race where app server responds with updated manifest version before dev server is listening for it (#6294)
- dev server now listens for updated versions before writing the server changes, guaranteeing that it is listening before the app server gets a chance to send its 'ready' message
- Only process
.css.ts
/.css.js
files with Vanilla Extract if@vanilla-extract/css
is installed (#6345) - Stop modifying a user's
tsconfig.json
when running usinggetConfig
(remix dev
,remix routes
,remix build
, etc) (#6156) - Cancel previous build when rebuild is kicked off to prevent rebuilds from hanging (#6295)
- Update minimum version of Babel dependencies to avoid errors parsing decorators (#6390)
- Support asset imports when detecting loader changes for HDR (#6396)
- Updated dependencies:
@remix-run/[email protected]
-
Enable support for CSS Modules, Vanilla Extract and CSS side-effect imports (#6046)
These CSS bundling features were previously only available via
future.unstable_cssModules
,future.unstable_vanillaExtract
andfuture.unstable_cssSideEffectImports
options inremix.config.js
, but they have now been stabilized.In order to use these features, check out our guide to CSS bundling in your project.
-
Stabilize built-in PostCSS support via the new
postcss
option inremix.config.js
. As a result, thefuture.unstable_postcss
option has also been deprecated. (#5960)The
postcss
option isfalse
by default, but when set totrue
will enable processing of all CSS files using PostCSS ifpostcss.config.js
is present.If you followed the original PostCSS setup guide for Remix, you may have a folder structure that looks like this, separating your source files from its processed output:
. ├── app │ └── styles (processed files) │ ├── app.css │ └── routes │ └── index.css └── styles (source files) ├── app.css └── routes └── index.css
After you've enabled the new
postcss
option, you can delete the processed files fromapp/styles
folder and move your source files fromstyles
toapp/styles
:. ├── app │ └── styles (source files) │ ├── app.css │ └── routes │ └── index.css
You should then remove
app/styles
from your.gitignore
file since it now contains source files rather than processed output.You can then update your
package.json
scripts to remove any usage ofpostcss
since Remix handles this automatically. For example, if you had followed the original setup guide:{ "scripts": { - "dev:css": "postcss styles --base styles --dir app/styles -w", - "build:css": "postcss styles --base styles --dir app/styles --env production", - "dev": "concurrently \"npm run dev:css\" \"remix dev\"" + "dev": "remix dev" } }
-
Stabilize built-in Tailwind support via the new
tailwind
option inremix.config.js
. As a result, thefuture.unstable_tailwind
option has also been deprecated. (#5960)The
tailwind
option isfalse
by default, but when set totrue
will enable built-in support for Tailwind functions and directives in your CSS files iftailwindcss
is installed.If you followed the original Tailwind setup guide for Remix and want to make use of this feature, you should first delete the generated
app/tailwind.css
.Then, if you have a
styles/tailwind.css
file, you should move it toapp/tailwind.css
.rm app/tailwind.css mv styles/tailwind.css app/tailwind.css
Otherwise, if you don't already have an
app/tailwind.css
file, you should create one with the following contents:@tailwind base; @tailwind components; @tailwind utilities;
You should then remove
/app/tailwind.css
from your.gitignore
file since it now contains source code rather than processed output.You can then update your
package.json
scripts to remove any usage oftailwindcss
since Remix handles this automatically. For example, if you had followed the original setup guide:{ // ... "scripts": { - "build": "run-s \"build:*\"", + "build": "remix build", - "build:css": "npm run generate:css -- --minify", - "build:remix": "remix build", - "dev": "run-p \"dev:*\"", + "dev": "remix dev", - "dev:css": "npm run generate:css -- --watch", - "dev:remix": "remix dev", - "generate:css": "npx tailwindcss -o ./app/tailwind.css", "start": "remix-serve build" } // ... }
-
The Remix dev server spins up your app server as a managed subprocess. (#6133) This keeps your development environment as close to production as possible. It also means that the Remix dev server is compatible with any app server.
By default, the dev server will use the Remix App Server, but you opt to use your own app server by specifying the command to run it via the
-c
/--command
flag:remix dev # uses `remix-serve <serve build path>` as the app server remix dev -c "node ./server.js" # uses your custom app server at `./server.js`
The dev server will:
- force
NODE_ENV=development
and warn you if it was previously set to something else - rebuild your app whenever your Remix app code changes
- restart your app server whenever rebuilds succeed
- handle live reload and HMR + Hot Data Revalidation
In order to manage your app server, the dev server needs to be told what server build is currently being used by your app server. This works by having the app server send a "I'm ready!" message with the Remix server build hash as the payload.
This is handled automatically in Remix App Server and is set up for you via calls to
broadcastDevReady
orlogDevReady
in the official Remix templates.If you are not using Remix App Server and your server doesn't call
broadcastDevReady
, you'll need to call it in your app server after it is up and running. For example, in an Express server:// server.js // <other imports> import { broadcastDevReady } from "@remix-run/node"; // Path to Remix's server build directory ('build/' by default) const BUILD_DIR = path.join(process.cwd(), "build"); // <code setting up your express server> app.listen(3000, () => { const build = require(BUILD_DIR); console.log("Ready: http://localhost:" + port); // in development, call `broadcastDevReady` _after_ your server is up and running if (process.env.NODE_ENV === "development") { broadcastDevReady(build); } });
Options priority order is: 1. flags, 2. config, 3. defaults.
Option flag config default Command -c
/--command
command
remix-serve <server build path>
HTTP(S) scheme --http-scheme
httpScheme
http
HTTP(S) host --http-host
httpHost
localhost
HTTP(S) port --http-port
httpPort
Dynamically chosen open port Websocket port --websocket-port
websocketPort
Dynamically chosen open port No restart --no-restart
restart: false
restart: true
🚨 The
--http-*
flags are only used for internal dev server <-> app server communication. Your app will run on your app server's normal URL.To set
unstable_dev
configuration, replaceunstable_dev: true
withunstable_dev: { <options> }
. For example, to set the HTTP(S) port statically:// remix.config.js module.exports = { future: { unstable_dev: { httpPort: 8001, }, }, };
You should only need to use the
--http-*
flags and--websocket-port
flag if you need fine-grain control of what scheme/host/port for the dev server. If you are setting up SSL or Docker networking, these are the flags you'll want to use.🚨 Remix will not set up SSL and custom host for you. The
--http-scheme
and--http-host
flag are for you to tell Remix how you've set things up. It is your task to set up SSL certificates and host files if you want those features.If you want to manage server changes yourself, you can use the
--no-restart
flag to tell the dev server to refrain from restarting your app server when builds succeed:remix dev -c "node ./server.js" --no-restart
For example, you could purge the
require
cache of your app server to keep it running while picking up server changes. If you do so, you should watch the server build path (build/
by default) for changes and only purge therequire
cache when changes are detected.🚨 If you use
--no-restart
, it is your responsibility to callbroadcastDevReady
when your app server has picked up server changes. For example, withchokidar
:// server.dev.js const BUILD_PATH = path.resolve(__dirname, "build"); const watcher = chokidar.watch(BUILD_PATH); watcher.on("change", () => { // 1. purge require cache purgeRequireCache(); // 2. load updated server build const build = require(BUILD_PATH); // 3. tell dev server that this app server is now ready broadcastDevReady(build); });
- force
- Fix absolute paths in CSS
url()
rules when using CSS Modules, Vanilla Extract and CSS side-effect imports (#5788) - look for @remix-run/serve in
devDependencies
when running remix dev (#6228) - add warning for v2 "cjs"->"esm"
serverModuleFormat
default change (#6154) - write mjs server output files (#6225)
- fix(react,dev): dev chunking and refresh race condition (#6201)
- Use correct require context in
bareImports
plugin. (#6181) - use minimatch for regex instead of glob-to-regexp (#6017)
- add
logDevReady
as replacement for platforms that can't initialize async I/O outside of the request response lifecycle. (#6204) - Use the "automatic" JSX runtime when processing MDX files. (#6098)
- forcibly kill app server during dev (#6197)
- show first compilation error instead of cancelation errors (#6202)
- Resolve imports from route modules across the graph back to the virtual module created by the v2 routes plugin. This fixes issues where we would duplicate portions of route modules that were imported. (#6098)
- Updated dependencies:
@remix-run/[email protected]
-
Added deprecation warning for
v2_normalizeFormMethod
(#5863) -
Added a new
future.v2_normalizeFormMethod
flag to normalize the exposeduseNavigation().formMethod
as an uppercase HTTP method to align with the previoususeTransition
behavior as well as thefetch()
behavior of normalizing to uppercase HTTP methods. (#5815)- When
future.v2_normalizeFormMethod === false
,useNavigation().formMethod
is lowercaseuseFetcher().formMethod
is uppercase
- When
future.v2_normalizeFormMethod === true
:useNavigation().formMethod
is uppercaseuseFetcher().formMethod
is uppercase
- When
-
Added deprecation warning for
browserBuildDirectory
inremix.config
(#5702) -
Added deprecation warning for
CatchBoundary
in favor offuture.v2_errorBoundary
(#5718) -
Added experimental support for Vanilla Extract caching, which can be enabled by setting
future.unstable_vanillaExtract: { cache: true }
inremix.config
. This is considered experimental due to the use of a brand new Vanilla Extract compiler under the hood. In order to use this feature, you must be using at leastv1.10.0
of@vanilla-extract/css
. (#5735) -
Added deprecation warning for
serverBuildDirectory
inremix.config
(#5704)
- Fixed issue to ensure changes to CSS inserted via
@remix-run/css-bundle
are picked up during HMR (#5823) - We now use
path.resolve
when re-exportingentry.client
(#5707) - Added support for
.mjs
and.cjs
extensions when detecting CSS side-effect imports (#5564) - Fixed resolution issues for pnpm users installing
react-refresh
(#5637) - Added deprecation warning for
future.v2_meta
(#5878) - Added optional entry file support for React 17 (#5681)
- Updated dependencies:
@remix-run/[email protected]
- dev server is resilient to build failures (#5795)
- Updated dependencies:
@remix-run/[email protected]
- remove premature deprecation warnings (#5790)
- Updated dependencies:
@remix-run/[email protected]
- Add types for importing
*.ico
files (#5430) - Allow
moduleResolution: "bundler"
in tsconfig.json (#5576) - Fix issue with x-route imports creating multiple entries in the module graph (#5721)
- Add
serverBuildTarget
deprecation warning (#5624) - Updated dependencies:
@remix-run/[email protected]
- Hot Module Replacement and Hot Data Revalidation (#5259)
- Requires
unstable_dev
future flag to be enabled - HMR provided through React Refresh
- Features:
- HMR for component and style changes
- HDR when loaders for current route change
- Known limitations for MVP:
- Only implemented for React via React Refresh
- No
import.meta.hot
API exposed yet - Revalidates all loaders on route when loader changes are detected
- Loader changes do not account for imported dependencies changing
- Requires
- Make
entry.client
andentry.server
files optional (#4600)- we'll use a bundled version of each unless you provide your own
-
Fixes flat route inconsistencies where
route.{ext}
wasn't always being treated likeindex.{ext}
when used in a folder (#5459)-
Route conflict no longer throw errors and instead display a helpful warning that we're using the first one we found.
⚠️ Route Path Collision: "/dashboard" The following routes all define the same URL, only the first one will be used 🟢️️ routes/dashboard/route.tsx ⭕️️ routes/dashboard.tsx
⚠️ Route Path Collision: "/" The following routes all define the same URL, only the first one will be used 🟢️️ routes/_landing._index.tsx ⭕️️ routes/_dashboard._index.tsx ⭕️ routes/_index.tsx
-
-
Log errors thrown during initial build in development. (#5441)
-
Sync
FutureConfig
interface between packages (#5398) -
Add file loader for importing
.csv
files (#3920) -
Updated dependencies:
@remix-run/[email protected]
- We are deprecating
serverBuildTarget
inremix.config
. See the release notes for v1.13.0 for more information. (#5354) - Add built-in support for PostCSS via the
future.unstable_postcss
feature flag (#5229) - Add built-in support for Tailwind via the
future.unstable_tailwind
feature flag (#5229)
- Mark Vanilla Extract files as side effects to ensure that files only containing global styles aren't tree-shaken (#5246)
- Support decorators in files using CSS side-effect imports (#5305)
- We made several Flat route fixes and enhancements. See the release notes for v1.13.0 for more information. (#5228)
- Updated dependencies:
@remix-run/[email protected]
- Added a new development server available in the Remix config under the
unstable_dev
flag. See the release notes for a full description. (#5133)
- Fixed issues with
v2_routeConvention
on Windows so that new and renamed files are properly included (#5266) - Server build should not be removed in
remix watch
andremix dev
(#5228) - The dev server will now clean up build directories whenever a rebuild starts (#5223)
- Updated dependencies:
@remix-run/[email protected]
- Fixed a bug with
v2_routeConvention
that preventedindex
modules from being recognized for route paths (195291a3d
) - Updated dependencies:
@remix-run/[email protected]
- Specify file loader for
.fbx
,.glb
,.gltf
,.hdr
, and.mov
files (#5030) - Added support for Vanilla Extract via the
unstable_vanillaExtract
future flag. IMPORTANT: Features marked withunstable
are … unstable. While we're confident in the use cases they solve, the API and implementation may change without a major version bump. (#5040) - Add support for CSS side-effect imports via the
unstable_cssSideEffectImports
future flag. IMPORTANT: Features marked withunstable
are … unstable. While we're confident in the use cases they solve, the API and implementation may change without a major version bump. (#4919) - Add support for CSS Modules via the
unstable_cssModules
future flag. IMPORTANT: Features marked withunstable
are … unstable. While we're confident in the use cases they solve, the API and implementation may change without a major version bump. (#4852)
- Add new "flat" routing conventions. This convention will be the default in v2 but is available now under the
v2_routeConvention
future flag. (#4880) - Added support for
handle
in MDX frontmatter (#4865) - Updated dependencies:
@remix-run/[email protected]
- Update babel config to transpile down to node 14 (#5047)
- Updated dependencies:
@remix-run/[email protected]
- Fixed several issues with TypeScript to JavaScript conversion when running
create-remix
(#4891) - Resolve asset entry full path to support monorepo import of styles (#4855)
- Updated dependencies:
@remix-run/[email protected]
- Allow defining multiple routes for the same route module file (#3970)
- Added support and conventions for optional route segments (#4706)
- The Remix compiler now supports new Typescript 4.9 syntax (like the
satisfies
keyword) (#4754) - Optimize
parentRouteId
lookup indefineConventionalRoutes
. (#4800) - Fixed a bug in
.ts
->.js
conversion on Windows by using a relative unix-style path (#4718) - Updated dependencies:
@remix-run/[email protected]
- Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Added a missing type definition for the Remix config
future
option to the@remix-run/dev/server-build
virtual module (#4771) - Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Added support for a new route
meta
API to handle arrays of tags instead of an object. For details, check out the RFC. (#4610)
- Importing functions and types from the
remix
package is deprecated, and all exported modules will be removed in the next major release. For more details,see the release notes for 1.4.0 where these changes were first announced. (#4661) - Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Update
create-remix
to use the new examples repository when using--template example/<name>
(#4208) - Add support for setting
moduleResolution
tonode
,node16
ornodenext
intsconfig.json
. (#4034) - Add resources imported only by resource routes to
assetsBuildDirectory
(#3841) - Ensure that any assets referenced in CSS files are hashed and copied to the
assetsBuildDirectory
. (#4130) - Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Added support for importing
.gql
and.graphql
files as plain text (#3923) - Added support for importing
.zip
and.avif
files as resource URLs (#3985)
- Removed our compiler's React shim in favor of esbuild's new automatic JSX transform (#3860)
- Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Added support for
.mjs
and.cjs
file extensions forremix.config
(#3675) - Added support for importing
.sql
files as text content (#3190) - Updated the compiler to make MDX builds deterministic (and a little faster!) (#3966)
- Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Remove logical nullish assignment, which is incompatible with Node v14. (#3880)
- Don't show ESM warnings when consumed via dynamic import. (#3872)
- Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]
- Write server build output files so that only assets imported from resource routes are written to disk (#3817)
- Add support for exporting links in
.mdx
files (#3801) - Ensure that build hashing is deterministic (#2027)
- Fix types for
@remix-run/dev/server-build
virtual module (#3743) - Updated dependencies:
@remix-run/[email protected]
@remix-run/[email protected]