Why GoRouter for Flutter Web?
GoRouter, developed by the Flutter team, is designed to handle navigation with a URL-based approach, making it ideal for web apps. Here’s why GoRouter shines for Flutter web development:
-
URL-Based Navigation: GoRouter supports clean URLs (e.g.,
/about
,/product/123
), which align with how users expect web navigation to work. - Browser Integration: It handles browser back/forward buttons and URL changes seamlessly.
-
Deep Linking: Users can share or bookmark specific pages (e.g.,
/product/42
) and land directly on them. - Declarative Routing: Define routes in a straightforward, scalable way, reducing navigation complexity.
In this guide, we’ll build a simple Flutter web app with GoRouter, featuring a Home page, an About page, and a Product page with dynamic URLs. We’ll ensure the app supports browser navigation and deep linking, all while keeping the code beginner-friendly.
Setting Up the Project
Let’s create a Flutter web app with GoRouter step by step.
Step 1: Create a New Flutter Project
If you don’t already have a Flutter project, create one by running:
flutter create go_router_web_app
cd go_router_web_app
Ensure your Flutter SDK is set up for web development. Test it with:
flutter run -d chrome
Step 2: Add GoRouter Dependency
Add the go_router
package to your project. Open pubspec.yaml
and include:
dependencies:
go_router: ^16.2.1
Run flutter pub get
to install it. (Check pub.dev for the latest version.)
Step 3: Create the App Screens
Let’s create three simple screens: HomeScreen
, AboutScreen
, and ProductScreen
. Create a lib/screens
folder and add the following files.
lib/screens/home_screen.dart:
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Welcome to the Home Page!'),
ElevatedButton(
onPressed: () => context.go('/about'),
child: const Text('Go to About'),
),
ElevatedButton(
onPressed: () => context.go('/product/123'),
child: const Text('View Product #123'),
),
],
),
),
);
}
}
lib/screens/about_screen.dart:
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class AboutScreen extends StatelessWidget {
const AboutScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('About')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('About Our App'),
ElevatedButton(
onPressed: () => context.go('/'),
child: const Text('Back to Home'),
),
],
),
),
);
}
}
lib/screens/product_screen.dart:
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class ProductScreen extends StatelessWidget {
final String productId;
const ProductScreen({super.key, required this.productId});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Product #$productId')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Details for Product #$productId'),
ElevatedButton(
onPressed: () => context.go('/'),
child: const Text('Back to Home'),
),
],
),
),
);
}
}
Step 4: Set Up GoRouter
Now, configure GoRouter to handle navigation. Replace the contents of lib/main.dart
with the following:
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'screens/home_screen.dart';
import 'screens/about_screen.dart';
import 'screens/product_screen.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// Define the GoRouter configuration
final GoRouter _router = GoRouter(
initialLocation: '/', // Start at the home page
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
),
GoRoute(
path: '/about',
builder: (context, state) => const AboutScreen(),
),
GoRoute(
path: '/product/:productId',
builder: (context, state) {
final productId = state.pathParameters['productId']!;
return ProductScreen(productId: productId);
},
),
],
// Optional: Handle 404-like errors
errorBuilder: (context, state) => Scaffold(
appBar: AppBar(title: const Text('Page Not Found')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Error: ${state.error}'),
ElevatedButton(
onPressed: () => context.go('/'),
child: const Text('Go to Home'),
),
],
),
),
),
);
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Flutter GoRouter Web Demo',
routerConfig: _router,
theme: ThemeData(primarySwatch: Colors.blue),
);
}
}
Explanation of the Code
-
GoRouter Setup: We define three routes:
-
/
: Maps toHomeScreen
. -
/about
: Maps toAboutScreen
. -
/product/:productId
: Maps toProductScreen
, with a dynamicproductId
parameter.
-
- MaterialApp.router: This integrates GoRouter with Flutter’s navigation system.
-
Error Handling: The
errorBuilder
displays a custom 404 page if the user navigates to an invalid route (e.g.,/invalid
). -
Navigation: We use
context.go()
for navigation, which updates the browser’s URL and supports back/forward buttons.
Step 5: Run the App for Web
Run the app in a browser with:
flutter run -d chrome
You should see:
- The Home page with buttons to navigate to the About page or Product page.
- URLs in the browser change to
/
,/about
, or/product/123
as you navigate. - Browser back/forward buttons work seamlessly.
- Typing a URL like
http://localhost:port/product/456
directly in the browser takes you to the Product page with ID 456.
Key GoRouter Features for Web Apps
1. URL-Based Navigation
GoRouter makes URLs the core of navigation. For example, navigating to /product/123
with context.go('/product/123')
updates the browser’s address bar, making the URL shareable.
2. Deep Linking
GoRouter supports deep linking out of the box. If a user visits http://yourapp.com/product/123
, GoRouter parses the productId
and loads the correct screen. This is great for sharing links or integrating with external systems like notifications.
3. Browser History Integration
GoRouter syncs with the browser’s history. Clicking the back button returns to the previous route (e.g., from /about
to /
), and forward navigates back. This happens automatically, no extra code needed.
4. Dynamic Routes
The :productId
syntax allows dynamic routes. You can access the parameter in the builder
with state.pathParameters['productId']
. For example:
GoRoute(
path: '/product/:productId',
builder: (context, state) => ProductScreen(productId: state.pathParameters['productId']!),
)
5. Query Parameters
GoRouter also supports query parameters (e.g., /search?query=flutter
). Access them with state.uri.queryParameters['query']
. For example:
GoRoute(
path: '/search',
builder: (context, state) {
final query = state.uri.queryParameters['query'] ?? 'No query';
return SearchScreen(query: query);
},
)
6. Redirects for Authentication
For web apps, you might want to redirect users to a login page if they’re not authenticated. Add a redirect to the GoRouter config:
final GoRouter _router = GoRouter(
routes: [/* ... */],
redirect: (context, state) {
bool isLoggedIn = false; // Replace with your auth logic
if (!isLoggedIn && state.uri.path != '/login') {
return '/login';
}
return null; // No redirect
},
);
Tips for Building URL-Friendly Flutter Web Apps
-
Test URLs Directly: Try typing URLs like
/product/999
in the browser to ensure deep linking works. -
Use Descriptive Paths: Keep routes like
/about
or/product
intuitive for users. -
Handle Errors Gracefully: Use
errorBuilder
to show user-friendly 404 pages. -
Optimize for SEO: Clean URLs like
/product/123
are better for search engines and sharing. - Test Browser Navigation: Ensure back/forward buttons work as expected.
Deploying the Web App
To deploy your Flutter web app:
- Build it with:
flutter build web
- Host the contents of the
build/web
folder on a web server (e.g., Firebase Hosting, Netlify, or GitHub Pages). - Ensure your server supports single-page app routing, redirecting all routes to
index.html
for GoRouter to handle.
Top comments (0)