7

Is there any way to access Environment Variables defined by the --dart-define command inside the index.html file of Flutter Web?

I currently can access them inside iOS and Android native files but have not found a way to do so inside the html file

tapizquent
  • 668
  • 11
  • 24

1 Answers1

9

Access to the environment declarations (this is the most correct name, also used in the doc of the String.fromEnvironment() method; see also dart-sdk issue #42136 - Clarify usage of -D/environment variables/environment declarations), is also possible from the javascript code.

There are two details to keep in mind:

  • String.fromEnvironment() can only be invoked with const (also implicit, in const context) and never with "new".
  • In Flutter/web, the main() method is not executed immediately upon loading the main.dart.js script, so it is not sufficient to place the js script (which reads the variable declared in dart) immediately after main.dart.js. It is therefore necessary to signal in some way to the js code when the dart code has been executed. To solve this problem, I resort to a custom DOM event. If there are better solutions, I invite you to report them.

Example:

main.dart

import 'package:flutter/material.dart';

import 'dart:js' as js;
import 'dart:html' as html;

void main() {
  //To expone the dart variable to global js code
  js.context["my_dart_var"] = const String.fromEnvironment("my_dart_var");
  //Custom DOM event to signal to js the execution of the dart code
  html.document.dispatchEvent(html.CustomEvent("dart_loaded"));

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
   //...
}

In index.html:

  <script src="main.dart.js" type="application/javascript"></script>

  <script>

    //Here my_dart_var is undefined
    console.log(`my_dart_var: ${window.my_dart_var}`);

    document.addEventListener("dart_loaded", function (){
      //Here my_dart_var is defined
      console.log("dart_loaded event");
      console.log(`my_dart_var: ${window.my_dart_var}`);
    });
  </script>
Mabsten
  • 1,570
  • 11
  • 16
  • This doesn't work: `TypeError: Cannot read property 'app' of undefined` – Rebar Jun 25 '21 at 15:06
  • @rebar I have tested again the snippet with the new Flutter Sdk 2.2.0 (that has introduced a new mechanism in index.html to load dart.main.js) and it works as expected. What is the `app` property? `--dart-define` allows you to define only 'environment declarations' of primitive type (string, int, bool) so I guess it is not a property of the value you have assigned to an environment declaration. – Mabsten Jun 25 '21 at 23:03
  • It‘s Firebase! You can‘t use this solution for firebase apps! Because Firebase wants these variables before Dart has loaded! Therefore: It may work for non-firebase projects but as of today Firebase Projects have a lack of security due to this…. – Rebar Jun 27 '21 at 02:00
  • @rebar I think I guessed what you were trying to do, though: 1) Firebase is safe without you taking this step; the tokens to initialize it in index.html are meant to be public, in the sense that it is not a risk even if others see them, because they are usable only in your domain (your site), which you set in the firebase console. 2) if you still want to pass tokens via dart-define, you can delay the loading of the firebase libraries using javascript – Mabsten Jun 27 '21 at 05:42
  • Also note that the env declarations passed via dartdefine are `const` **inlined in the sources**, so after compiling the final release they are visible in the .js files. Therefore ***should not be used for tokens to be kept secret*** (as mentioned above, the tokens to init Fb in index.html are not to be kept secret; you can verify this by deepening the subject with a google search). For secret tokens, web hosting services usually offer a special mechanism (very easy to use; I used Netlify), and maybe Firebase also offers a similar service (perhaps with Firebase Config, but I don't remember). – Mabsten Jun 27 '21 at 06:03
  • This is the only way I got it to work!!!! – Jose Georges Oct 22 '21 at 20:17
  • What if the variable is part of the source of the script, like so ? – user3808307 Mar 03 '22 at 23:04
  • @Mabsten for me, using the window variable without dollar & brackets worked i.e. `window.my_dart_var`. This didn't work for me `${window.my_dart_var}` – Ashutosh Chamoli Jun 20 '22 at 14:44
  • Btw firebase now allow to make the initialization right in the dart code. So there's no need to do it in index.html anymore. https://stackoverflow.com/questions/70232931/firebaseoptions-cannot-be-null-when-creating-the-default-app – Bonco May 01 '23 at 11:50