v16.3.0-canary.34
- Update
shortcircuit_if_knowntoeval_shortcircuit(): #94163 - Remove dead code from
JsValue::Binaryinis_truthy: #94165 - Produce valid file URLs for
import.meta.urlon Windows in Turbopack: #94179 - [turbopack] Store TaskDirtyCause in Dirtyness and pass to NativeFunction::span: #94057
- Turbopack: cleanup ModuleHotReferenceAssetReference: #94206
- [feat] updated the documentation for deployment to point to new next.js Docker official guide.: #94185
- docs: correct custom server optimization guidance: #94229
- Add Errors/Insights tab split to the instant error overlay: #94073
- Replace VcStorage with real TurboTasks in tests/benches : #93955
- Redesign the unrendered-segment instant validation overlay: #93879
- turbopack tracing: add chunk_name to
get HMR eventsspan: #94061 - Turbopack: reduce hmr chunk list subscriptions: #94062
- [turbopack] Separate
JsValueinto it's own folder in the analyzer: #94208 - feat(image-optimization): add experimental flag
imgOptOperationCache: #94246
Huge thanks to @sampoder, @sokra, @mischnic, @kristiyan-velkov, @timneutkens, @aurorascharff, @lukesandberg, @wbinnssmith, and @styfle for helping!
v6.30.4
See the changelog for release notes: https://github.com/remix-run/react-router/blob/v6/CHANGELOG.md#v6304
ui v0.3.0
-
BREAKING CHANGE: Remix UI component render functions no longer receive props as an argument. Type component props on
Handle<Props>and read current values fromhandle.propsin both setup and render code. -
Updated
anchor(floating, anchorTarget, options)to accept either anHTMLElementor coordinate target via the newAnchorPoint/AnchorTargettypes. -
Added
menu.contextTrigger()so menus can open from right-click pointer locations while keeping existing keyboard navigation, submenus, and selection behavior.
-
Fixed
css(...)so nested selector objects render recursively instead of serializing deeper nested rules as[object Object](see #11459). -
Dispatch reload events for nested frames when an ancestor frame reloads
-
Prevent non-blocking frames from displaying their fallback when an ancestor frame is reloaded
response v0.3.6
- Bumped
@remix-run/*dependencies:
static-middleware v0.4.11
-
Prevent
staticFiles()from serving files outside its configured root through symlinks. -
Bumped
@remix-run/*dependencies:
session-middleware v0.3.2
- Bumped
@remix-run/*dependencies:
route-pattern v0.22.0
-
Matchers now normalize percent-encoded pathname during matching
Pathname matching now uses the URL parser's normalized pathname, splits it into segments, and canonicalizes each segment as percent-encoded text before matching. This allows equivalent path text like
aand%61, orcaféandcaf%C3%A9, to match consistently:let matcher = createMatcher('/a') matcher.match('https://example.com/%61') // before: null // after: { params: {} }
let matcher = createMatcher('/café') matcher.match('https://example.com/caf%C3%A9') // before: null // after: { params: {} }
Also keeps encoded path separators like
%2Finside the segment where they appear instead of treating them as/separators during matching:let matcher = createMatcher('/files/:dir/:name') matcher.match('https://example.com/files/docs/readme.md') // before: { params: { dir: 'docs', name: 'readme.md' } } // after: { params: { dir: 'docs', name: 'readme.md' } } matcher.match('https://example.com/files/docs%2Freadme.md') // before: { params: { dir: 'docs', name: 'readme.md' } } // after: null
Matched pathname params are still returned decoded.
let matcher = createMatcher('/posts/:slug') let href = createHref('/posts/:slug', { slug: 'hello/world?draft=true#preview' }) matcher.match(`https://example.com${href}`) // before: null // after: { params: { slug: 'hello/world?draft=true#preview' } }
-
createHrefnow encodes pathname params and validates hostname paramsPathname params now encode characters that would otherwise change URL structure when parsed. Variables encode
/,?,#,%, and\\; wildcards preserve/as a path separator but encode the other structural characters.createHref('/posts/:slug', { slug: 'hello/world?draft=true#preview' }) // before: '/posts/hello/world?draft=true#preview' // after: '/posts/hello%2Fworld%3Fdraft=true%23preview' createHref('/files/*path', { path: 'docs/@remix-run/ui?raw#v1' }) // before: '/files/docs/@remix-run/ui?raw#v1' // after: '/files/docs/@remix-run/ui%3Fraw%23v1'
Hostname params are now validated so structural URL characters cannot change the URL authority when parsed. Hostname variables reject
.,@,:,/,?, and#; hostname wildcards allow.to span labels but reject the other structural characters.createHref('://:tenant.example.com/path', { tenant: 'acme.dev' }) // before: 'https://acme%2Edev.example.com/path' // after: throws CreateHrefError createHref('://*tenant.example.com/path', { tenant: 'preview.acme' }) // before: 'https://preview.acme.example.com/path' // after: 'https://preview.acme.example.com/path' createHref('://*tenant.example.com/path', { tenant: 'preview:acme' }) // before: 'https://preview%3Aacme.example.com/path' // after: throws CreateHrefError
-
Route pattern parsing now stores escaped static text without the escape marker
Escaped pattern characters in static text are now parsed into text tokens that contain the literal character without the leading
\\. Serialization keeps emitting the escape marker so the pattern string still round-trips as escaped static text.let pattern = RoutePattern.parse('/docs/npm\\:@scope/package') pattern.pathname.tokens // before: [{ type: 'text', text: 'docs' }, { type: 'separator' }, { type: 'text', text: 'npm\\:' }, ...] // after: [{ type: 'text', text: 'docs' }, { type: 'separator' }, { type: 'text', text: 'npm:' }, ...] pattern.toString() // before: '/docs/npm\\:@scope/package' // after: '/docs/npm\\:@scope/package'
let pattern = RoutePattern.parse('/files/report-\\(final\\).pdf') pattern.pathname.tokens // before: text tokens included '\\(' and '\\)' // after: text tokens include '(' and ')' pattern.toString() // before: '/files/report-\\(final\\).pdf' // after: '/files/report-\\(final\\).pdf'