I'm building a Flutter Web app and I need to avoid loading fonts from any external CDN (company policy / privacy reasons).
Instead, I want to bundle all fonts locally and have Flutter use only those.
However, even after adding my own fonts to pubspec.yaml and updating my ThemeData, the app still tries to load fonts from a CDN (e.g.
https://fonts.gstatic.com/s/notocoloremoji/v32/Yq6P-KqIXTD0t4D9z1ESnKM3-HpFabsE4tq3luCC7p-aXxcn.3.woff2 or a similar font CDN). I either want to completely block this or configure Flutter so it does not attempt to use the CDN at all.
What I’m doing now:
I’m using Flutter (Web) with a custom font.
Here is my pubspec.yaml regarding fonts:
flutter:
generate: true
uses-material-design: false
assets:
- assets/logos/
- assets/icons/
- assets/fonts/
fonts:
- family: Roboto
fonts:
- asset: assets/fonts/Roboto-Light.ttf
- asset: assets/fonts/Roboto-Medium.ttf
- asset: assets/fonts/Roboto-Regular.ttf
- asset: assets/fonts/Roboto-Italic.ttf
- asset: assets/fonts/Roboto-Bold.ttf
- family: NotoSansSymbols
fonts:
- asset: assets/fonts/NotoSansSymbols-Regular.ttf
- family: NotoSansSymbols2
fonts:
- asset: assets/fonts/NotoSansSymbols2-Regular.ttf
- family: LocalNotoColorEmoji
fonts:
- asset: assets/fonts/NotoColorEmoji-Regular.ttf
- family: Font Awesome 7 Pro
fonts:
- asset: assets/icons/Font Awesome 7 Pro-Light-300.otf
weight: 300
In my theme.dart I set my fonts like this:
class AppTheme {
AppTheme._();
// light theme
static ThemeData lightTheme = ThemeData(
useMaterial3: true,
brightness: Brightness.light,
primaryColor: CustomColors.primary,
scaffoldBackgroundColor: CustomColors.primaryBackground,
canvasColor: CustomColors.primaryBackground,
fontFamily: 'Roboto',
textTheme: CustomTextTheme.lightTextTheme.apply(
fontFamily: 'Roboto',
fontFamilyFallback: [
'NotoSansSymbols',
'NotoSansSymbols2',
'LocalNotoColorEmoji',
'Apple Color Emoji', // macOS / iOS
'Segoe UI Emoji', // Windows
'Noto Color Emoji', // Linux / Android
'EmojiOne Color', // Linux / Firefox
],
),
I do not explicitly use the google_fonts package anywhere.
When I open the app in the browser, I still see network requests to a font CDN in the dev tools, for example:
If I block those requests (e.g. via the browser dev tools or a network filter), the app still works, but I want to ensure it never tries to load these external fonts in the first place.
2 Answers 2
It looks like the --no-web-resources-cdn flag doesn't handle fonts. Issue #163554 on the GitHub repo describes it in detail, a team member interested in fixing it. It looks like you mostly implemented the work-around from Johannes Mayer fro there:
Add this to your pubspec.yaml:
fonts: - family: Roboto fonts: - asset: assets/fonts/Roboto-Regular.ttf - asset: assets/fonts/Roboto-Medium.ttf weight: 500 - asset: assets/fonts/Roboto-Bold.ttf weight: 700I found those fonts in a gfonts.dart via those URLs:
- Roboto-Regular: fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf
- Roboto-Medium: fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmEU9vAx05IsDqlA.ttf
- Roboto-Bold: fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmWUlvAx05IsDqlA.ttf put them into assets/fonts folder
Call flutter pub get
Not sure if needed but in lib/main.dart I also added Roboto as explicit font family:
return MaterialApp( theme: ThemeData( fontFamily: 'Roboto', //required to stick with local Roboto ...And you are good to go... Check network tab of a private browser if roboto request is now getting it from your domain instead.
The biggest difference between that and your code that I can see is that you specify fontFamilyFallback, which the link does not do. If you do indeed have to specify a fallback, it makes sense that the load first tries to load the font from the URL, and only goes for the fallback once the URL is unreachable. So I'd remove the fallback URL, and check against te above and the GitHub link to make sure you follow the exact same process.
If you can't get it to work without the fallback, you could consider implementing the other workaround by GiovanniRaseraF (cetriolino).
2 Comments
Coincidentally I am referred in Frank van Puffelen's Post. I am revisiting this topic because on one screen my network tab still tried to fetch two fonts. NotoSansSymbols as well as NotoColorEmoji.
Turns out reason was we used an inline success emoji on that screen which triggered flutter to internally download fonts.
So for me the solution was to replace the celebration emoji with Icons.celebration. Also commonly you can choose cupertino_icons or font_awesome_flutter (you can also download SVGs from their website) packages.