How to remove hash (#) from URL in Flutter web
Asked Answered
H

10

93

The default URL of a Flutter web project defines a URL containing a hashtag (#), as follows:

http://localhost:41521/#/peaple/...

I would like to remove this '#', looking like this:

http://localhost:41521/peaple/

How can I solve this problem?

Hawk answered 23/1, 2020 at 1:6 Comment(1)
Related issue Flutter_web navigation should provide a way to remove hash symbol(#) – Jocosity
G
128

You can now use a simple package and a single line of code to remove the leading hash (#) from your Flutter web app: url_strategy (full disclosure: I am the author)

Using url_strategy

You simply add the dependency as described here and then add the following function call to your main function:

import 'package:url_strategy/url_strategy.dart';

void main() {
  // Here we set the URL strategy for our web app.
  // It is safe to call this function when running on mobile or desktop as well.
  setPathUrlStrategy();
  runApp(MyApp());
}

Calling setPathUrlStrategy is all you need to do πŸŽ‰


The package also ensures that running the code will not crash on mobile (see below). Additionally, this will also run on stable if you build your mobile app on stable and only web on beta.

Notes

You need to make sure that you include <base href="/"> inside the <head> section of your web/index.html when using the path URL strategy.
This is added by default when creating a new Flutter app.

Furthermore, when deploying your production app, you need to make sure that every path points to your index.html. If you use tools like Firebase hosting, this is done automatically for you when configuring your app as a single page app.
Otherwise, you want to look up how to rewrite all paths to your index.html for the hosting you are using.

Essentially, you want to have a single page app, where the HTTP server serves the index.html for all paths.


The package implementation is based on the manual solution using flutter_web_plugins. The benefits of using the package are the following:

  • Only need to call a single function.
  • No need to use conditional imports (the package does it for you).
  • You will not get any missing implementation issues on stable (as the web feature is still on beta).
Gelb answered 13/1, 2021 at 20:24 Comment(8)
You can redirect all of your paths to index.html by adding thnis to the "hosting" field in your firebase.json: "rewrites": [ { "source": "**", "destination": "/index.html" } ] – Jozef
By default, Flutter uses the hash (/#/) location strategy. what is benefit of hash? – Chokecherry
@cretivecreatormaybenot I'm using url_strategy and when I type in a new url the app restarts instead of just parsing it and update the shown page. Is it normal ? To test it I used this Navigator 2.0 example: github.com/carloshwa/flutter-example/tree/navigator_2 Many thanks – Scherzando
Fantastic, thank you so much! For some reason, that '#' was really annoying me, and it was getting in the way of some specific routing I needed to do. – Tussock
Without /#/ every time you change address, the whole app restarts. With it, you just move within navigation system of the app, which is clearly faster and more efficient. It's probably not a good idea to change the default behavior. – Treblinka
@AshkanSarlak That is simply not true. If your whole app reloads, your app or server is not configured correctly. – Gelb
@Gelb It's a simple app served by a basic nginx. So I haven't introduced anything wrong in it. – Treblinka
All this package does is just export flutter_web_plugins setUrlStrategy(PathUrlStrategy()) with some conditional imports So you might as well just use the flutter_web_plugins package – Blond
R
35

The following answer is copied from Mouad Debbar's explanation on GitHub (see issue comment).


Here are the steps to use it once it's available:

Add <base href="/"> inside the <head> section of your web/index.html file. This will be added automatically for new projects created by flutter create. But for existing apps, the developer needs to add it manually. Add the flutter_web_plugins dependency in pubspec.yaml if it doesn't already exist:

dependencies:
  flutter_web_plugins:
    sdk: flutter

Add a lib/configure_nonweb.dart with the following content:

void configureApp() {
  // No-op.
}

Add a lib/configure_web.dart with the following content:

import 'package:flutter_web_plugins/flutter_web_plugins.dart';

void configureApp() {
  setUrlStrategy(PathUrlStrategy());
}

In lib/main.dart, do the following:

import 'package:flutter/material.dart';
import 'configure_nonweb.dart' if (dart.library.html) 'configure_web.dart';

void main() {
  configureApp();
  runApp(MyApp());
}
Requiescat answered 1/11, 2020 at 16:15 Comment(7)
Currently it's not available on either master or stable channels. But it's tested to be working on both dev and beta channels. – Imprudent
This should really be a community wiki because it is just a copied answer. – Gelb
I now wrote an answer with a simpler solution: https://mcmap.net/q/233898/-how-to-remove-hash-from-url-in-flutter-web – Gelb
Does this work if the base href is something else like /app/? – Cystotomy
flutter.dev/docs/development/ui/navigation/… – Fiver
I prefer this answer because it does not rely on a package, and it's really just a few very simple changes. Relying on url_strategy package for such simple edits is a bad idea for infrastructure and long-term support reasons. – Hygrometer
the if-statement in the import = amazing! – Hakon
I
8

For those coming in 2023, Flutter now explain how to do this in their official docs. One thing they don't mention though (at the time of writing) is how to update pubspec.yaml file.

Step 1: update pubspec.yaml as follows.

dependencies:
  flutter:
    sdk: flutter
  flutter_web_plugins: # add this line
    sdk: flutter       # and this line

Step 2: run flutter pub get.

Step 3: update main.dart as follows.

import 'package:flutter_web_plugins/url_strategy.dart'; // add this import

void main() {
  usePathUrlStrategy(); // and this line
  runApp(ExampleApp());
}

Step 4: note Flutter's recommendation for running local flutter web below.

The local dev server created by running flutter run -d chrome is configured to handle any path gracefully and fallback to your app’s index.html file.

I personally like to run it on a fixed port with flutter run -d chrome --web-port=3000.

Cheers!

This helped me resolve a redirect issue when implementing magic-link auth with flutter_supabase and go_router (I mention this for search-engine crawlers, in case it'll help someone else).

Imagine answered 13/9, 2023 at 22:23 Comment(0)
M
4

Only for Github pages hosting

This also applies to apps that aren't served from domain.com/ directly but from some path domain.com/path/.

You need to add your repo name to base href otherwise your website won't work.

<base href="/REPO_NAME/">
Mc answered 12/4, 2021 at 11:34 Comment(1)
what is REPO_NAME here? the domain name? I'm not hosting in github-pages – Batiste
S
3

add this in pubspec.yaml

dependencies:
  flutter_web_plugins:
    sdk: flutter

inside the main.dart file add the cofigureApp in to root of the app and also add this import

import 'package:flutter_web_plugins/flutter_web_plugins.dart';

void configureApp() {
  setUrlStrategy(PathUrlStrategy());
}

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  configureApp();
  runApp(MyApp());
}

restart the web app

out will be like this

http://localhost:52299/login_page
Southwestwardly answered 17/12, 2021 at 8:53 Comment(2)
by using this, I am unable to move any particular page from the URL. it automatically navigates me to the home page. – Morality
same here as well, why does this happen? and why don't I see anyone tackling this? – Emeritaemeritus
L
2

If your only concern is for routing, you can do something like this:

onGenerateRoute: (settings) {
    List segments = settings.name.split('/').where((x) => ! x.isEmpty).toList();
    String page = segments.length > 0 ? segments[0] : '';
    ...
  }
}
Lammond answered 22/7, 2020 at 20:36 Comment(2)
where to write this ? – Hying
@NehalJaisalmeria inside your MaterialApp() widget – Blackwood
A
2
  1. Install in pubspec.yaml url_strategy

  2. Write in main.dart:

import 'package:url_strategy/url_strategy.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  setPathUrlStrategy();
  runApp(MyApp());
}
  1. If you get an error when you refresh the page, then add file 404.html to the folder with index.html. Copy the entire contents of the index.html and paste it into the 404.html. For some hosts it's enough. But some host aslo requires the file ".htaccess".

  2. You shoud create in the same folder the file ".htaccess" and write into this file:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /index.html [L]

This solution was recieved from this video.

Ardent answered 8/7, 2022 at 17:34 Comment(1)
yet another beta projects, based on its semver. – Angloindian
B
2

After migration go Router to 5.0 UrlPathStrategy.path is removed


My current version goRouter 8.0.3

 dependencies:
 flutter_web_plugins:
 sdk: flutter 

Instead of:

GoRouter.setUrlPathStrategy(UrlPathStrategy.path);

Replace with:

 import 'package:flutter_web_plugins/url_strategy.dart';

 void main() {
 usePathUrlStrategy();
 runApp(ExampleApp());
 }
Bernina answered 14/6, 2023 at 18:35 Comment(0)
B
0

I found most of the answers above to be a bit confusing. What ended up working for my firebase-hosted website was following this short 4-minute YouTube tutorial by Johannes Milke.

The tutorial outlines a number of options for solving the "#" problem, basically explaining some of the answers above a bit better. My final solution was to

  1. Add url_strategy dependency as outlined in many of the answers above.
  2. Adding base href="/"> inside the section of my index.html file
  3. Making sure that all paths point to index.html by adding "rewrites": [ { "source": "**", "destination": "/index.html" } ] in my firebase.json.
Bobbitt answered 23/4, 2022 at 6:22 Comment(0)
B
-6

you can also do this

String main_url = url.split('#').join();

eg. http://localhost:31265/#apply?id=1

output: http://localhost:31265/apply?id=1

Boulevard answered 19/12, 2022 at 11:32 Comment(2)
what do you even mean man? provide more details – Angloindian
The post ask to remove # so u could just split the url around # and then again join it. – Boulevard

© 2022 - 2024 β€” McMap. All rights reserved.