Minor Changes
-
Protect apps with a nonce-based Content Security Policy using
csp()fromremix/middleware/csp. Add it beforerender()and it generates a nonce for each request along with a matching policy. Generated import maps, module preloads, andcss()styles receive the nonce automatically, and authored tags can read it withgetCspNonce(context): (#12098)import { createRouter } from 'remix/router' import { csp } from 'remix/middleware/csp' import { render } from 'remix/middleware/render' let router = createRouter({ middleware: [ csp({ policy: ({ nonce }) => ({ scriptSrc: [`'nonce-${nonce}'`], styleSrc: [`'nonce-${nonce}'`], }), }), render(), ], })
Frames rendered on the server share the document's nonce, and client navigation keeps it across frame and island updates. HMR updates that add imports and
remix/multiple-import-maps-polyfillalso work under a strict policy, including one without'unsafe-eval'. The middleware supports report-only policies and reporting endpoints; see the CSP middleware docs for setup.Custom integrations can pass
noncetorenderToStream()orrenderToString()fromremix/component/serverand build policies withContentSecurityPolicyfromremix/headers/content-security-policy. -
Added
package.jsonexports: (#12098)remix/headers/content-security-policyto re-export APIs from@remix-run/headers/content-security-policyremix/middleware/cspto re-export APIs from@remix-run/csp-middleware
-
Mocks and method spies in
remix/testcan now swap their implementation withmockImplementation()ormockImplementationOnce(), clear recorded calls withresetCalls(), reportcallCount(), andrestore()the original function. Mocks created witht.mockare restored even when a test or its cleanup fails. (#12097)
Patch Changes
-
Apps created with
remix newnow fingerprint assets in production, close the asset server on shutdown, and run theirpackage.jsonscripts in Windows command shells. See the@remix-run/clichangelog to apply the same setup to an existing app. (#12192) -
Adding or removing
clientEntryduring HMR now restarts the app server, so fresh server responses no longer use stale hydration boundaries. (#11982) -
clientEntryprops inremix/componenthydrate more reliably. JSX elements styled withcss()in props no longer fail hydration withInvalid mix prop, and plain data that contains keys Remix uses for serialization, such as$rmx, now reaches the client entry unchanged. Only elements created with JSX orcreateElement()render; objects that merely look like elements, such as ones parsed from JSON, now throwInvalid child node, so data from a database or API can't inject markup. (#12192) -
css()and thestyleprop inremix/componentnow serialize property names and numbers the way browsers expect, andcss()rerenders take about half as long in our benchmarks. Some existing output changes: (#12192)- Numbers stay unitless for properties that accept bare numbers.
flex: 2is now a grow factor instead of2px, andtabSize,animation, andborderImagenumbers take their unitless meaning. Use strings such as'4px'or'200ms'when you want units. - Custom properties keep their casing, so
'--gapSize'no longer becomes--gap-size. - Vendor-prefixed keys get their leading dash, so
webkitLineClamprenders as-webkit-line-clamp. - Styles that list the same properties in a different order no longer share a class, and generated
rmxc-*class names change. Update tests or selectors that hard-code them.
See the
@remix-run/componentchangelog for migration examples. - Numbers stay unitless for properties that accept bare numbers.
-
Fixes for client navigation and rendering in
remix/component: (#12192)- Navigations no longer flash unstyled content when page-specific
<head>links are added or removed, because keyed stylesheets stay in place instead of being moved and reloaded. - Safari restores the full scroll position on back and forward navigation.
- Boolean
aria-*anddata-*values render as"true"and"false"on the server, matching the browser. Previouslyaria-current={true}rendered as a bare attribute, which assistive technology reads as"false".data-rmx-document={false}anddata-rmx-preserve-dom={false}now omit the attribute in the browser instead of turning those features on. - Doctype-looking text inside scripts, styles, textareas, attributes, and comments is preserved when the browser parses frame HTML.
- Navigations no longer flash unstyled content when page-specific
-
The
remix/componentbrowser runtime is about 10% smaller when minified. Apps that render withcreateRoot()orcreateRangeRoot()and never use<Frame>no longer load the frame runtime at all, which roughly halves their component JavaScript. (#12192) -
A failed upload stream no longer corrupts an existing file stored with
remix/file-storage/fs. The API and disk format are unchanged; see the filesystem storage documentation for failure behavior and filesystem requirements. (#11909) -
The guides installed with
remixare revised as standalone chapters, including a complete Files and Assets chapter and expanded component coverage in Rendering UI. Their links now point to the consolidated docs site, and the Motion link in the animation examples is fixed. (#12077) -
remix/session-storage/fsno longer corrupts a session file when overlapping requests save the same session. Session files that were already corrupted now start a fresh session instead of throwing on every request. (#12192) -
Browser tests in
remix/testno longer fail with syntax errors when they dynamically import modules, and WebKit runs no longer stall until the progress timeout. (#12192) -
Bumped
@remix-run/*dependencies:assets@1.0.2auth@1.0.1auth-middleware@1.0.1cli@1.0.2component@1.2.0component-hmr@1.0.1compression-middleware@1.0.2cookie@1.0.2cors-middleware@1.0.2csp-middleware@1.0.0csrf-middleware@1.0.1fetch-proxy@1.0.2file-storage@1.0.1file-storage-s3@1.1.1form-data-middleware@1.1.1form-data-parser@1.1.1headers@1.1.0multipart-parser@1.1.1multiple-import-maps-polyfill@1.0.1render-middleware@1.1.0response@1.0.2session@1.0.1session-middleware@1.0.2session-storage-memcache@1.0.1session-storage-redis@1.0.1spa@1.0.2static-middleware@1.0.2test@1.1.0