From ee036044377b193128d74d385b0175faaa875282 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Thu, 9 Mar 2023 13:04:10 -0800 Subject: [PATCH] Add a flag to allow the default Client to be tree shaken away. (#868) --- .github/workflows/dart.yml | 76 ++++++++++++++++++- pkgs/http/CHANGELOG.md | 2 + pkgs/http/lib/src/browser_client.dart | 8 +- pkgs/http/lib/src/client.dart | 11 +++ pkgs/http/lib/src/io_client.dart | 8 +- pkgs/http/mono_pkg.yaml | 3 + .../test/no_default_http_client_test.dart | 18 +++++ tool/ci.sh | 4 + 8 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 pkgs/http/test/no_default_http_client_test.dart diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index b7d92fcd13..780b5715ef 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -157,6 +157,41 @@ jobs: if: "always() && steps.pkgs_http_client_conformance_tests_pub_upgrade.conclusion == 'success'" working-directory: pkgs/http_client_conformance_tests job_005: + name: "unit_test; Dart 2.19.0; PKG: pkgs/http; `dart run --define=no_default_http_client=true test/no_default_http_client_test.dart`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0;packages:pkgs/http;commands:command" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0;packages:pkgs/http + os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0 + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Dart SDK + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + with: + sdk: "2.19.0" + - id: checkout + name: Checkout repository + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - id: pkgs_http_pub_upgrade + name: pkgs/http; dart pub upgrade + run: dart pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: pkgs/http + - name: "pkgs/http; dart run --define=no_default_http_client=true test/no_default_http_client_test.dart" + run: "dart run --define=no_default_http_client=true test/no_default_http_client_test.dart" + if: "always() && steps.pkgs_http_pub_upgrade.conclusion == 'success'" + working-directory: pkgs/http + needs: + - job_001 + - job_002 + - job_003 + - job_004 + job_006: name: "unit_test; Dart 2.19.0; PKG: pkgs/http; `dart test --platform chrome`" runs-on: ubuntu-latest steps: @@ -191,7 +226,7 @@ jobs: - job_002 - job_003 - job_004 - job_006: + job_007: name: "unit_test; Dart 2.19.0; PKG: pkgs/http; `dart test --platform vm`" runs-on: ubuntu-latest steps: @@ -226,7 +261,42 @@ jobs: - job_002 - job_003 - job_004 - job_007: + job_008: + name: "unit_test; Dart dev; PKG: pkgs/http; `dart run --define=no_default_http_client=true test/no_default_http_client_test.dart`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/http;commands:command" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/http + os:ubuntu-latest;pub-cache-hosted;sdk:dev + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Dart SDK + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + with: + sdk: dev + - id: checkout + name: Checkout repository + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - id: pkgs_http_pub_upgrade + name: pkgs/http; dart pub upgrade + run: dart pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: pkgs/http + - name: "pkgs/http; dart run --define=no_default_http_client=true test/no_default_http_client_test.dart" + run: "dart run --define=no_default_http_client=true test/no_default_http_client_test.dart" + if: "always() && steps.pkgs_http_pub_upgrade.conclusion == 'success'" + working-directory: pkgs/http + needs: + - job_001 + - job_002 + - job_003 + - job_004 + job_009: name: "unit_test; Dart dev; PKG: pkgs/http; `dart test --platform chrome`" runs-on: ubuntu-latest steps: @@ -261,7 +331,7 @@ jobs: - job_002 - job_003 - job_004 - job_008: + job_010: name: "unit_test; Dart dev; PKG: pkgs/http; `dart test --platform vm`" runs-on: ubuntu-latest steps: diff --git a/pkgs/http/CHANGELOG.md b/pkgs/http/CHANGELOG.md index c11ad7afda..14adfa76ad 100644 --- a/pkgs/http/CHANGELOG.md +++ b/pkgs/http/CHANGELOG.md @@ -1,6 +1,8 @@ ## 0.13.6-dev * `BrowserClient` throws an exception if `send` is called after `close`. +* If `no_default_http_client=true` is set in the environment then disk usage + is reduced in some circumstances. * Require Dart 2.19 ## 0.13.5 diff --git a/pkgs/http/lib/src/browser_client.dart b/pkgs/http/lib/src/browser_client.dart index dff2da6bb0..ddaa43feae 100644 --- a/pkgs/http/lib/src/browser_client.dart +++ b/pkgs/http/lib/src/browser_client.dart @@ -15,7 +15,13 @@ import 'streamed_response.dart'; /// Create a [BrowserClient]. /// /// Used from conditional imports, matches the definition in `client_stub.dart`. -BaseClient createClient() => BrowserClient(); +BaseClient createClient() { + if (const bool.fromEnvironment('no_default_http_client')) { + throw StateError('no_default_http_client was defined but runWithClient ' + 'was not used to configure a Client implementation.'); + } + return BrowserClient(); +} /// A `dart:html`-based HTTP client that runs in the browser and is backed by /// XMLHttpRequests. diff --git a/pkgs/http/lib/src/client.dart b/pkgs/http/lib/src/client.dart index 2cc5f21505..11c266888c 100644 --- a/pkgs/http/lib/src/client.dart +++ b/pkgs/http/lib/src/client.dart @@ -210,6 +210,17 @@ Client? get zoneClient { /// runWithClient(() => runApp(const MyApp()), clientFactory); /// } /// ``` +/// +/// If [runWithClient] is used and the environment defines +/// `no_default_http_client=true` then generated binaries may be smaller e.g. +/// ```shell +/// $ flutter build appbundle --dart-define=no_default_http_client=true ... +/// $ dart compile exe --define=no_default_http_client=true ... +/// ``` +/// +/// If `no_default_http_client=true` is set then any call to the [Client] +/// factory (i.e. `Client()`) outside of the [Zone] created by [runWithClient] +/// will throw [StateError]. R runWithClient(R Function() body, Client Function() clientFactory, {ZoneSpecification? zoneSpecification}) => runZoned(body, diff --git a/pkgs/http/lib/src/io_client.dart b/pkgs/http/lib/src/io_client.dart index d5c79cddb9..4ebb434f9c 100644 --- a/pkgs/http/lib/src/io_client.dart +++ b/pkgs/http/lib/src/io_client.dart @@ -12,7 +12,13 @@ import 'io_streamed_response.dart'; /// Create an [IOClient]. /// /// Used from conditional imports, matches the definition in `client_stub.dart`. -BaseClient createClient() => IOClient(); +BaseClient createClient() { + if (const bool.fromEnvironment('no_default_http_client')) { + throw StateError('no_default_http_client was defined but runWithClient ' + 'was not used to configure a Client implementation.'); + } + return IOClient(); +} /// Exception thrown when the underlying [HttpClient] throws a /// [SocketException]. diff --git a/pkgs/http/mono_pkg.yaml b/pkgs/http/mono_pkg.yaml index 32c0a7e15f..0e2f9d8aa7 100644 --- a/pkgs/http/mono_pkg.yaml +++ b/pkgs/http/mono_pkg.yaml @@ -15,3 +15,6 @@ stages: - test: --platform chrome os: - linux + - command: dart run --define=no_default_http_client=true test/no_default_http_client_test.dart + os: + - linux diff --git a/pkgs/http/test/no_default_http_client_test.dart b/pkgs/http/test/no_default_http_client_test.dart new file mode 100644 index 0000000000..c51e98fa15 --- /dev/null +++ b/pkgs/http/test/no_default_http_client_test.dart @@ -0,0 +1,18 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:http/http.dart' as http; +import 'package:test/test.dart'; + +/// Tests that no [http.Client] is provided by default when run with +/// `--define=no_default_http_client=true`. +void main() { + test('Client()', () { + if (const bool.fromEnvironment('no_default_http_client')) { + expect(http.Client.new, throwsA(isA())); + } else { + expect(http.Client(), isA()); + } + }); +} diff --git a/tool/ci.sh b/tool/ci.sh index 74eeca90ec..2885a5827d 100755 --- a/tool/ci.sh +++ b/tool/ci.sh @@ -71,6 +71,10 @@ for PKG in ${PKGS}; do echo 'dart analyze --fatal-infos' dart analyze --fatal-infos || EXIT_CODE=$? ;; + command) + echo 'dart run --define=no_default_http_client=true test/no_default_http_client_test.dart' + dart run --define=no_default_http_client=true test/no_default_http_client_test.dart || EXIT_CODE=$? + ;; format) echo 'dart format --output=none --set-exit-if-changed .' dart format --output=none --set-exit-if-changed . || EXIT_CODE=$?