Skip to content

Conversation

@ulisseshen
Copy link
Contributor

@ulisseshen ulisseshen commented Sep 22, 2025

Add --web-define option for runtime variable injection in Flutter web templates

This PR adds support for injecting environment-specific variables into Flutter web templates during development and build processes through a new --web-define command-line option.

What this changes

Before: Developers had to manually edit HTML templates or use build-time workarounds to inject environment-specific values (API URLs, feature flags, etc.) into Flutter web applications.

After: Developers can now use --web-define KEY=VALUE to inject variables directly into web templates using {{VARIABLE_NAME}} placeholders.

Key features

  • Template variable substitution: Support for {{VARIABLE_NAME}} placeholders in index.html and flutter_bootstrap.js
  • Runtime validation: Throws clear errors when required variables are missing with helpful suggestions
  • Command-line integration: Works with both flutter run and flutter build web commands
  • Multiple variable support: Can define multiple variables in a single command
  • Built-in variable protection: Ignores Flutter's built-in template variables during validation

Usage examples

# Development with API configuration
flutter run -d chrome --web-define=API_URL=https://dev-api.example.com --web-define=DEBUG_MODE=true

# Production build with environment variables
flutter build web --web-define=API_URL=https://api.example.com --web-define=ANALYTICS_ID=GA-123456 --web-define=DEBUG_MODE=false

# Multiple environments
flutter run -d chrome --web-define=ENV=staging --web-define=FEATURE_X=enabled

Template usage

In your web/index.html:

<script>
  window.config = {
    apiUrl: '{{API_URL}}',
    environment: '{{ENV}}',
    debugMode: {{DEBUG_MODE}}
  };
</script>

Error handling

If a variable is missing, the tool provides clear feedback:

Missing web-define variable: API_URL

Please provide the missing variable using:
flutter run --web-define=API_URL=VALUE
or
flutter build web --web-define=API_URL=VALUE

Issues fixed

Fixes #127853

Additional Usage Examples

Environment-Specific Configurations (Flavors)

# Development
flutter run -d chrome --web-define=ENV=dev --web-define=API_URL=http://localhost:3000 --web-define=DEBUG=true

# Production
flutter build web --web-define=ENV=prod --web-define=API_URL=https://api.example.com --web-define=DEBUG=false

Template:

<script>
  window.config = {
    environment: '{{ENV}}',
    apiUrl: '{{API_URL}}',
    debugMode: {{DEBUG}}
  };
</script>

Dynamic Asset Loading

flutter build web --web-define=CDN_URL=https://cdn.example.com --web-define=LOGO_PATH=/assets/logo.png

Template:

<link rel="icon" href="{{CDN_URL}}{{LOGO_PATH}}">
<link rel="stylesheet" href="{{CDN_URL}}/styles/theme.css">

Analytics Integration

flutter build web --web-define=GA_ID=G-XXXXXXXXXX --web-define=SENTRY_DSN=https://xxx@sentry.io/123

Template:

<script async src="https://www.googletagmanager.com/gtag/js?id={{GA_ID}}"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', '{{GA_ID}}');
</script>

Feature Flags

flutter run -d chrome --web-define=FEATURE_X=true --web-define=FEATURE_Y=false

Template:

<script>
  window.features = { featureX: {{FEATURE_X}}, featureY: {{FEATURE_Y}} };
</script>

Multi-Tenant/White-Label Apps

flutter build web --web-define=TENANT=acme --web-define=PRIMARY_COLOR=#FF5733 --web-define=LOGO_URL=https://cdn.acme.com/logo.png

Template:

<head>
  <title>{{TENANT}} Portal</title>
  <link rel="icon" href="{{LOGO_URL}}">
  <style>:root { --primary: {{PRIMARY_COLOR}}; }</style>
</head>

Backend Service URLs

flutter build web \
  --web-define=API_URL=https://api.example.com \
  --web-define=WS_URL=wss://ws.example.com \
  --web-define=AUTH_DOMAIN=auth.example.com

Template:

<script>
  window.services = {
    api: '{{API_URL}}',
    websocket: '{{WS_URL}}',
    auth: '{{AUTH_DOMAIN}}'
  };
</script>

SEO & Meta Tags

flutter build web --web-define=APP_TITLE="My App" --web-define=APP_DESC="Description" --web-define=OG_IMAGE=https://example.com/og.png

Template:

<head>
  <title>{{APP_TITLE}}</title>
  <meta name="description" content="{{APP_DESC}}">
  <meta property="og:title" content="{{APP_TITLE}}">
  <meta property="og:image" content="{{OG_IMAGE}}">
</head>

Build Automation

{
  "scripts": {
    "dev": "flutter run -d chrome --web-define=ENV=dev --web-define=API_URL=http://localhost:3000",
    "prod": "flutter build web --web-define=ENV=prod --web-define=API_URL=https://api.example.com"
  }
}

Important Notes

  • Security: Never expose secrets via --web-define (client-side only)

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

- Add test for web-define variable substitution in HTML templates
- Add test for missing web-define variable validation and error handling
- Add test for multiple missing variables error handling
- Add test to verify built-in Flutter variables are ignored during validation
- Add test for empty web-define variables support
- Add test for serving index.html with web-define variables
- Add test for error handling when web-define variables are missing
- Add test for serving flutter_bootstrap.js with web-define variables
- Update existing tests to support new web-define parameter
- Add support for {{VARIABLE_NAME}} pattern matching in web templates
- Add validation to throw ToolExit when required variables are missing
- Add comprehensive error messages with usage suggestions
- Support built-in Flutter variables alongside user-defined variables
- Allow empty string values for web-define variables
- Add usesWebDefineOption() method for commands to enable web-define support
- Add extractWebDefines() method to parse and validate KEY=VALUE format
- Add FlutterOptions.kWebDefinesOption constant for consistent option naming
- Provide comprehensive help text and examples for web-define usage
- Add webDefines parameter to WebAssetServer constructor
- Update template substitution calls to include web-define variables
- Pass web-define variables through the entire web serving pipeline
- Update WebRunnerFactory interface to support webDefines parameter
- Add web-define option support to flutter run command
- Add web-define option support to flutter build web command
- Pass extracted web-define variables to web runner creation
@github-actions github-actions bot added the tool Affects the "flutter" command-line tool. See also t: labels. label Sep 22, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a --web-define option to inject environment-specific variables into Flutter web templates (index.html and flutter_bootstrap.js). The implementation adds the command-line option to flutter run and flutter build web, parses the key-value pairs, and performs substitution in the web templates. The changes include validation for missing variables, providing helpful error messages. The core logic for substitution is in WebTemplate, and new tests have been added to verify the functionality. My review focuses on improving the efficiency and correctness of the substitution logic.

Comment on lines 193 to 199
// Apply substitutions
String result = content;
webDefines.forEach((String key, String value) {
result = result.replaceAll('{{$key}}', value);
});

return result;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation for substitution iterates through all webDefines and calls replaceAll for each. This can be inefficient for a large number of defines and may lead to incorrect substitutions if a define's value contains another placeholder (e.g., --web-define=A={{B}}). A more efficient and safer approach is to use replaceAllMapped to perform all substitutions in a single pass.

    // Apply substitutions
    return content.replaceAllMapped(variablePattern, (Match match) {
      final String variableName = match.group(1)!;
      if (webDefines.containsKey(variableName)) {
        return webDefines[variableName]!;
      }
      // Return the original match for built-in variables, which are handled elsewhere.
      return match.group(0)!;
    });

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with this suggestion.

The implementation of _applyWebDefineSubstitutions could look something like:

String _applyWebDefineSubstitutions(String content, Map<String, String> webDefines) {
  final RegExp variablePattern = RegExp(r'\{\{([A-Za-z_][A-Za-z0-9_]*)\}\}');

  final Set<String> missingVariables = <String>{};
  final String result = content.replaceAllMapped(variablePattern, (Match match) {
    final String variableName = match.group(1)!;
    if (webDefines.containsKey(variableName)) {
      return webDefines[variableName]!;
    }
    missingVariables.add(variableName);
    // Return the original match for missing variables.
    return match.group(0)!;
  });

  if (missingVariables.isNotEmpty) {
    // ...
  }

  return result;
}

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@cedvdb
Copy link
Contributor

cedvdb commented Sep 27, 2025

Why web-define instead of dart-define ? Using dart define seems more consistent.

Also does this support only index.html or other files too (manifest etc) ?

@ulisseshen
Copy link
Contributor Author

Why web-define instead of dart-define ? Using dart define seems more consistent.

Also does this support only index.html or other files too (manifest etc) ?

Is dart define possible to use in index.html as template? Where I can found this usage? I search a lot and dont found any information like that.


My propose is to use it to dynamically provide resources to web flutter app in build and devlop time.

@ulisseshen ulisseshen changed the title Add --web-define option for runtime variable injection in Flutter web templates Add --web-define option for runtime placeholder injection in Flutter web index.html file Sep 29, 2025
@ulisseshen ulisseshen changed the title Add --web-define option for runtime placeholder injection in Flutter web index.html file Add --web-define flag for template variable injection in Flutter web builds Sep 29, 2025
@Pszione
Copy link

Pszione commented Sep 30, 2025

Why don't you call it:
Add --web-define for flavors injection in Flutter web builds?

@ulisseshen
Copy link
Contributor Author

Why don't you call it: Add --web-define for flavors injection in Flutter web builds?

Why it will help not only in flavor, althogh it will be the more blessed fro this feature.

Maybe the mix of template variable and flavors injection should emerge a goot title for this PR.

@flutter-dashboard
Copy link

This pull request executed golden file tests, but it has not been updated in a while (20+ days). Test results from Gold expire after as many days, so this pull request will need to be updated with a fresh commit in order to get results from Gold.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@cedvdb
Copy link
Contributor

cedvdb commented Oct 20, 2025

you should request a review

@ulisseshen ulisseshen changed the base branch from master to beta October 20, 2025 18:50
@ulisseshen ulisseshen requested review from a team and jtmcdole as code owners October 20, 2025 18:50
@flutter-dashboard flutter-dashboard bot changed the base branch from beta to master October 20, 2025 18:50
@flutter-dashboard
Copy link

This pull request was opened against a branch other than master. Since Flutter pull requests should not normally be opened against branches other than master, I have changed the base to master. If this was intended, you may modify the base back to beta. See the Release Process for information about how other branches get updated.

Reviewers: Use caution before merging pull requests to branches other than master, unless this is an intentional hotfix/cherrypick.

@fluttergithubbot
Copy link
Contributor

An existing Git SHA, dca7a559fba71ed29693561ad7c09e7229a6934a, was detected, and no actions were taken.

To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with --force) that already was pushed before, push a blank commit (git commit --allow-empty -m "Trigger Build") or rebase to continue.

1 similar comment
@fluttergithubbot
Copy link
Contributor

An existing Git SHA, dca7a559fba71ed29693561ad7c09e7229a6934a, was detected, and no actions were taken.

To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with --force) that already was pushed before, push a blank commit (git commit --allow-empty -m "Trigger Build") or rebase to continue.

@bkonyi bkonyi removed the request for review from a team November 3, 2025 14:39
Copy link
Contributor

@mdebbar mdebbar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing all the concerns, and sorry for the review delay!

@mdebbar mdebbar added the autosubmit Merge PR when tree becomes green via auto submit App label Dec 3, 2025
@auto-submit auto-submit bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Dec 3, 2025
@auto-submit
Copy link
Contributor

auto-submit bot commented Dec 3, 2025

autosubmit label was removed for flutter/flutter/175805, because - The status or check suite Windows tool_tests_commands has failed. Please fix the issues identified (or deflake) before re-applying this label.

@bkonyi bkonyi added the autosubmit Merge PR when tree becomes green via auto submit App label Dec 11, 2025
@auto-submit auto-submit bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Dec 11, 2025
@auto-submit
Copy link
Contributor

auto-submit bot commented Dec 11, 2025

autosubmit label was removed for flutter/flutter/175805, because - The status or check suite Linux android_java17_tool_integration_tests has failed. Please fix the issues identified (or deflake) before re-applying this label.

@bkonyi bkonyi added the autosubmit Merge PR when tree becomes green via auto submit App label Dec 11, 2025
@auto-submit auto-submit bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Dec 11, 2025
@auto-submit
Copy link
Contributor

auto-submit bot commented Dec 11, 2025

autosubmit label was removed for flutter/flutter/175805, because - The status or check suite Linux android_java17_tool_integration_tests has failed. Please fix the issues identified (or deflake) before re-applying this label.

@bkonyi bkonyi added the autosubmit Merge PR when tree becomes green via auto submit App label Jan 6, 2026
@auto-submit auto-submit bot added this pull request to the merge queue Jan 7, 2026
Merged via the queue into flutter:master with commit 9766a97 Jan 7, 2026
141 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jan 7, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 7, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 7, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 7, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 7, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 7, 2026
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Jan 7, 2026
Roll Flutter from 13b2b91 to 01d37bc (74 revisions)

flutter/flutter@13b2b91...01d37bc

2026-01-07 stuartmorgan@google.com Replace Hybrid Composition wiki page with dev-facing content (flutter/flutter#180642)
2026-01-07 116356835+AbdeMohlbi@users.noreply.github.com Improve code quality in `FlutterActivityTest.java` (flutter/flutter#180585)
2026-01-07 iinozemtsev@google.com Roll Dart SDK to 3.11.0-296.1.beta (flutter/flutter#180633)
2026-01-07 vegorov@google.com Bump target Windows version to 10 (flutter/flutter#180624)
2026-01-07 goderbauer@google.com Run hook_user_defines and link_hook integration tests on CI (flutter/flutter#180622)
2026-01-07 iliyazelenkog@gmail.com Fix division by zero in RenderTable intrinsic size methods (flutter/flutter#178217)
2026-01-07 116356835+AbdeMohlbi@users.noreply.github.com Remove more  `requires 24` anotations (flutter/flutter#180116)
2026-01-07 engine-flutter-autoroll@skia.org Roll Skia from 3971dbb85d45 to c5359a4d720e (1 revision) (flutter/flutter#180631)
2026-01-07 huy@nevercode.io Fix TabBar.image does not render at initialIndex for the first time (flutter/flutter#179616)
2026-01-07 engine-flutter-autoroll@skia.org Roll Skia from 1e7ad625f6f7 to 3971dbb85d45 (3 revisions) (flutter/flutter#180627)
2026-01-07 goderbauer@google.com Unpin DDS (flutter/flutter#180571)
2026-01-07 bruno.leroux@gmail.com Fix DropdownMenuEntry.style not resolved when entry is highlighted (flutter/flutter#178873)
2026-01-07 116356835+AbdeMohlbi@users.noreply.github.com Remove unnecessary `@RequiresApi24` annotations from FlutterFragment methods (flutter/flutter#180117)
2026-01-07 engine-flutter-autoroll@skia.org Roll Skia from 7fc63228056b to 1e7ad625f6f7 (1 revision) (flutter/flutter#180616)
2026-01-07 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from QfR2ZFZ5kGTD3raO3... to dTvN_JVSCfGFRasvH... (flutter/flutter#180612)
2026-01-07 bkonyi@google.com [ Widget Preview ] Add support for `dart:ffi` imports (flutter/flutter#180586)
2026-01-07 engine-flutter-autoroll@skia.org Roll Skia from eec90000a899 to 7fc63228056b (2 revisions) (flutter/flutter#180608)
2026-01-07 ulisses.hen@hotmail.com Add --web-define flag for template variable injection in Flutter web builds (flutter/flutter#175805)
2026-01-07 codefu@google.com docs(engine): update rbe notes (flutter/flutter#180599)
2026-01-06 engine-flutter-autoroll@skia.org Roll Skia from b6249496c230 to eec90000a899 (3 revisions) (flutter/flutter#180602)
2026-01-06 146823759+brahim-guaali@users.noreply.github.com Forward proxy 404 responses to client (flutter/flutter#179858)
2026-01-06 engine-flutter-autoroll@skia.org Roll Dart SDK from 40a8c6188f7f to d2e3ce177270 (1 revision) (flutter/flutter#180598)
2026-01-06 104009581+Saqib198@users.noreply.github.com Restore CLI precedence for web headers and HTTPS over web_dev_config.yaml (flutter/flutter#179639)
2026-01-06 engine-flutter-autoroll@skia.org Roll Skia from f5d9da13d56d to b6249496c230 (1 revision) (flutter/flutter#180596)
2026-01-06 dkwingsmt@users.noreply.github.com Enable misc leak tracking (flutter/flutter#176992)
2026-01-06 dacoharkes@google.com [hooks] Don't require NDK for Android targets (flutter/flutter#180594)
2026-01-06 kjlubick@users.noreply.github.com [skia] Disable legacy non-const SkData APIs (flutter/flutter#179684)
2026-01-06 48625061+muradhossin@users.noreply.github.com Fix/ios share context menu (flutter/flutter#176199)
2026-01-06 engine-flutter-autoroll@skia.org Roll Skia from b970aeffa66f to f5d9da13d56d (5 revisions) (flutter/flutter#180588)
2026-01-06 goderbauer@google.com Manually bump dependencies (flutter/flutter#180509)
2026-01-06 engine-flutter-autoroll@skia.org Roll Dart SDK from 8150be8a0e48 to 40a8c6188f7f (2 revisions) (flutter/flutter#180582)
2026-01-06 engine-flutter-autoroll@skia.org Roll Packages from 12eb764 to d3f860d (2 revisions) (flutter/flutter#180581)
2026-01-06 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from MHF-UAfO6sVKqSEYk... to nR2ESa1Gd8yPcWo06... (flutter/flutter#180578)
2026-01-06 sokolovskyi.konstantin@gmail.com Add tooltip support to PlatformMenuItem and PlatformMenu. (flutter/flutter#180069)
2026-01-06 bruno.leroux@gmail.com Add DropdownMenuFormField.errorBuilder (flutter/flutter#179345)
2026-01-06 engine-flutter-autoroll@skia.org Roll Skia from 1845397e11ba to b970aeffa66f (2 revisions) (flutter/flutter#180566)
2026-01-06 oss@simonbinder.eu Don't embed unreferenced assets (flutter/flutter#179251)
2026-01-06 116356835+AbdeMohlbi@users.noreply.github.com Improve documentation about ValueNotifier's behavior (flutter/flutter#179870)
2026-01-06 engine-flutter-autoroll@skia.org Roll Skia from 904ba00331ca to 1845397e11ba (5 revisions) (flutter/flutter#180558)
2026-01-06 engine-flutter-autoroll@skia.org Roll Dart SDK from 2fb9ad834c4d to 8150be8a0e48 (1 revision) (flutter/flutter#180557)
2026-01-06 engine-flutter-autoroll@skia.org Roll Skia from 98c042dde68c to 904ba00331ca (3 revisions) (flutter/flutter#180550)
2026-01-06 engine-flutter-autoroll@skia.org Roll Dart SDK from ba9f7f790966 to 2fb9ad834c4d (2 revisions) (flutter/flutter#180548)
2026-01-06 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from ubBGcRaAKWKihQ4ac... to QfR2ZFZ5kGTD3raO3... (flutter/flutter#180547)
2026-01-06 ahmedsameha1@gmail.com Make sure that a DraggableScrollableSheet doesn't crash in 0x0 enviro… (flutter/flutter#180433)
2026-01-06 ahmedsameha1@gmail.com Make sure that a ColorFiltered doesn't crash 0x0 environment (flutter/flutter#180307)
2026-01-06 ahmedsameha1@gmail.com Make sure that a FadeInImage doesn't crash in 0x0 environment (flutter/flutter#180495)
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fyi-web For the attention of Web platform team tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support dart defines in index.html

6 participants