• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / fx-private-relay / 8da7c3b7-a519-4539-918c-b416afc03320

15 Jan 2026 11:20AM UTC coverage: 91.39% (+0.04%) from 91.349%
8da7c3b7-a519-4539-918c-b416afc03320

Pull #6193

circleci

Vinnl
fix MPP-5435: chore(frontend) Webpack to Turbopack

This is the default in Next.js now, so it's probably safest to align
with that.

Some changes I had to do:
- Set up Turbopack to load FTL files as raw strings.
- Add the raw-loader dependency to do so.
- Compensate for Turbopack (at the moment) loading those strings on
  the `default` export property for FTL modules, rather than having
  the complete module be a string.
- Remove the MSW workaround — I no longer received build errors, so that
  no longer appears to be necessary. This seems to align with the
  current package.json of msw, which indeed now no longer sets any
  exports explicitly to `null`.
- Switch to the function-style syntax for :global, since Turbopack
  always uses LightningCSS, which only supports that.
- Hardcode the breakpoints we use, since Turbopack/LightningCSS won't
  support exporting variables from CSS:
  https://github.com/vercel/next.js/issues/88544
- Next.js itself updated next-env.d.ts
Pull Request #6193: Switch from Webpack to Turbopack

3005 of 3871 branches covered (77.63%)

Branch coverage included in aggregate %.

2 of 6 new or added lines in 2 files covered. (33.33%)

2 existing lines in 1 file now uncovered.

18490 of 19649 relevant lines covered (94.1%)

13.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

33.33
/frontend/src/hooks/mediaQuery.ts
1
import { useEffect, useState } from "react";
2✔
2

3
// We used to import these directly from the source of truth (the SCSS),
4
// but Next.js does not support that with Turbopack:
5
// https://github.com/vercel/next.js/issues/88544
6
// Hence, we manually inline the breakpoints from Protocol.
7
// Since we're not matching Protocol updates, that should be safe enough:
8
const breakpoints = {
2✔
9
  xs: "(min-width: 320px)",
10
  sm: "(min-width: 480px)",
11
  md: "(min-width: 768px)",
12
  lg: "(min-width: 1024px)",
13
  xl: "(min-width: 1312px)",
14
} as const;
15

16
function useMediaQueryImp(mediaQuery: string): boolean {
17
  const [mediaQueryList, setMediaQueryList] = useState(
×
18
    window.matchMedia(mediaQuery),
19
  );
20
  useEffect(() => {
×
21
    setMediaQueryList(window.matchMedia(mediaQuery));
×
22
  }, [mediaQuery]);
23

24
  const [matches, setMatches] = useState(mediaQueryList.matches);
×
25
  useEffect(() => {
×
26
    const changeListener: Parameters<MediaQueryList["addEventListener"]>[1] = (
×
27
      _changedList,
28
    ) => {
29
      setMatches(mediaQueryList.matches);
×
30
    };
31
    mediaQueryList.addEventListener("change", changeListener);
×
32
    return () => {
×
33
      mediaQueryList.removeEventListener("change", changeListener);
×
34
    };
35
  }, [mediaQueryList]);
36

37
  return matches;
×
38
}
39

40
export const useMediaQuery =
2✔
41
  typeof window === "undefined" || typeof window.matchMedia !== "function"
2!
42
    ? () => false
×
43
    : useMediaQueryImp;
44

45
/**
46
 * Get whether the current viewport width matches a Protocol media query.
47
 *
48
 * @param width Matches the `$mq-xs` to `$mq-xl` media queries from Protocol.
49
 * @returns Whether the current viewport width matches that media query.
50
 */
51
export function useMinViewportWidth(width: keyof typeof breakpoints): boolean {
2✔
NEW
52
  return useMediaQuery(breakpoints[width] ?? "all");
×
53
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc