hunk.code_window:         );
         } else if (isBlockLinkDescriptor(descriptor)) {
           return [descriptor.link];
         } else if (descriptor.rel === "stylesheet") {
           // add styles as preloads so they download with higher priority than
           // modulepreloads in `<Scripts>`. Otherwise rendering is blocked by
           // modules because rendering is blocked by styles by the browser, and
           // styles, without preloading, would be lower priority than the
           // modulepreloads.
           let { type, rel, ...rest } = descriptor;
           return [{ rel: "preload", as: "style", ...rest }, descriptor];
         } else {
           return [descriptor];
         }
       })
  
hunk.labels: keep keep keep replace replace replace replace replace replace replace replace keep keep keep keep
hunk.file_path: packages/remix-react/linksPreloading.ts
hunk.type: replace
file: ---
  published: 2021-02-17
  ---
  
  # v0.13.0 Release Notes
  
  Lots of bug fixes, some new features, and we ALMOST made it w/o a breaking change, but there is one, it's super easy though.
  
  ## New Entry File Names
  
  This is the only thing you have to do to upgrade from `v0.12.x`:
  
  - Rename `app/entry-browser.js` to `app/entry.client.js` (or `.tsx`)
  - Rename `app/entry-server.js` to `app/entry.server.js` (or `.tsx`)
  
  This brings our file naming conventions in alignment with one of the new features in this release.
  
  ## Excluding modules from the client and server bundles
  
  We haven't talked about this very much publicly, but generally speaking the Remix compiler does a decent job at deciding which modules to include in your browser bundles vs. which are meant only for the server. It does this through a feature known as "tree-shaking" that permits the compiler to remove dead code from the output bundles.
  
  Let's say you have a module that contains a few functions for accessing your backend database. You could `import` this module into one of your route modules so you can use it in your `loader` and/or `action`, like this:
  
  ```js
  import { useRouteData } from "remix";
  import { json } from "@remix-run/data";
  
  import { db } from "../database";
  
  export async function loader({ params }) {
    let user = await db.select("users", (where: { userId: params.userId }));
    return json({ user });
  }
  
  export function MyPage() {
    let { user } = useRouteData();
    // ...
  }
  ```
  
  At compile time, we can see that the only place you're using anything from `../database` is in your `loader`, so when we build the client bundle we can remove that code entirely ("tree-shake" it) from the build. This includes both the `loader` function itself, as well as the `import` of `../database`!
  
  This works great most of the time, but sometimes you get into weird situations where the compiler can't automatically infer which files it needs only on the server, or only on the client. For these times, we provide an escape hatch: `*.client.js` and `*.server.js`.
  
  For example, on our own website we got into a situation where we were importing both `firebase` and `firebase-admin` in our `/login` route. We use the `firebase` package in the component code to create the user session, and we use the `firebase-admin` package in the `loader` (on the server) to verify and create the cookie. Our code looked something like this:
  
  ```js
  import admin from "../utils/firebaseAdmin.js";
  import firebase from "../utils/firebase.js";
  
  export function loader() {
    // use `admin` in here
  }
  
  export function LoginPage() {
    function loginFormHandler() {
      // use `firebase` in here
    }
  
    // ...
  }
  ```
  
  The `firebase` package isn't really meant to run on the server--it's client-only. But we can't easily infer that it's not needed in the server bundles because of the way it's used in an event handler. So instead, we use the `.client.js` file extension on our `utils/firebase.js` to exclude it from the server build!
  
  All we need to do is change our filename:
  
  ```js
  import firebase from "../utils/firebase.client.js";
  ```
  
  Now `utils/firebase.client.js` won't ever end up in the server bundles.
  
  So that's the feature in a nutshell: use `.server.js` (or `.server.tsx`) as your file extension when you know a file is only ever meant to be run server-side, or use `.client.js` when it's only ever meant to run in the browser. And remember, _most_ of the time the compiler should automatically be able to figure it out for you, so this is really just an escape hatch!
  
  ## CSS Imports
  
  You can now import CSS with the `css:` import assertion. It's just like `url:` except that the file will be processed with PostCSS (as long as you have a `postcss.config.js` file in the Remix app root).
  
  ```js
  // <app root>/postcss.config.js
  module.exports = {
    plugins: [require("autoprefixer"), require("cssnano")]
  };
  ```
  
  ```ts
  // <app root>/routes/some-route.js
  import style from "css:../styles/something.css";
  
  // usually used with links
  export let links = () => {
    return [{ rel: "stylesheet", href: style }];
  };
  ```
  
  You can find a few PostCSS setups in the [styling docs](https://remix.run/dashboard/docs/styling).
  
  **Note**: Using this plugin will slow down your builds. Remix won't rebuild a file that hasn't changed, even between restarts as long as you haven't deleted your browser build directory. It's usually not a big deal unless you're using tailwind where it's common for 5-20 seconds to build a file the first time depending on your tailwind config.
  
  ## `useMatches` hook and Route Module `handle` export
  
  Remix internally knows the all of the routes that match at the very top of the application hierachy even though routes down deeper fetched the data. It's how `<Meta />`, `<Links />`, and `<Scripts />` elements know what to render.
  
  This new hook allows you to create similar conventions, giving you access to all of the route matches and their data on the current page.
  
  This is useful for creating things like data-driven breadcrumbs or any other kind of app convention. Before you can do that, you need a way for your route to export an api, or a "handle". Check out how we can create breadcrumbs in `root.tsx`.
  
  First, your routes can put whatever they want on the `handle`, here we use `breadcrumb`, it's not a Remix thing, it's whatever you want.
  
  ```tsx
  // routes/some-route.tsx
  export let handle = {
    breadcrumb: () => <Link to="/some-route">Some Route</Link>
  };
  ```
  
  ```tsx
  // routes/some-route/some-child-route.tsx
  export let handle = {
    breadcrumb: () => <Link to="/some-route/some-child-route">Child Route</Link>
  };
  ```
  
  And then we can use this in our root route:
  
  ```tsx
  import { Links, Scripts, useRouteData, useMatches } from "remix";
  
  export default function Root() {
    let matches = useMatches();
  
    return (
      <html lang="en">
        <head>
          <meta charSet="utf-8" />
          <Links />
        </head>
        <body>
          <header>
            <ol>
              {matches
                // skip routes that don't have a breadcrumb
                .filter(match => match.handle && match.handle.breadcrumb)
                // render breadcrumbs!
                .map((match, index) => (
                  <li key={index}>{match.handle.breadcrumb(match)}</li>
                ))}
            </ol>
          </header>
  
          <Outlet />
        </body>
      </html>
    );
  }
  ```
  
  A match looks like:
  
  ```ts
  interface {
    // The amount of the URL this route matched
    pathname: string;
  
    // whatever your route's loader returned
    data: any;
  
    // the parsed params from the url
    params: { [name: string]: string };
  
    // the handle exported from your route module
    handle: any;
  }
  ```
  
  We're excited to see what conventions you come up with!
  
  ## Everything else
  
  - Added `action` to `usePendingFormSubmit()`
  - Fixed 404 pages
  - Fixed using non-HTML elements (e.g. `FormData`, `URLSearchParams`) with `useSubmit`
  - Fixed using Open Graph tags with route `meta` function
  
  Enjoy!
  