Skip to content

Commit d585d02

Browse files
committed
wire up custom hotreload handling
1 parent f56e2f9 commit d585d02

8 files changed

Lines changed: 71 additions & 29 deletions

File tree

packages/jaspr/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## Unreleased breaking
2+
3+
- Added hot-reload support.
4+
15
## 0.23.1
26

37
- Fixed expression compilation when debugging a client-side application with an AOT installed CLI.

packages/jaspr/lib/src/server/server_handler.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,11 @@ Handler createProxyHandler(http.Client? client) {
127127
final handler = proxyHandler('http://localhost:$jasprProxyPort/', client: c);
128128
return (req) async {
129129
try {
130-
// Determine and pass the base path to the proxy handler so it can rewrite DWDS handler paths correctly.
131-
return await handler(req.change(headers: {'jaspr_base_path': req.handlerPath}));
130+
return await handler(req);
132131
} on http.ClientException {
133132
return Response(503, headers: {'Retry-After': '1'});
133+
} on SocketException {
134+
return Response(503, headers: {'Retry-After': '1'});
134135
}
135136
};
136137
}

packages/jaspr_builder/lib/src/options/client_options_builder.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ class ClientOptionsBuilder implements Builder {
120120
}
121121
}
122122

123+
bool _triedRunningFlutter = false;
124+
123125
Future<List<Plugin>> loadWebPlugins(BuildStep buildStep) async {
124126
final pluginsDependenciesId = AssetId(buildStep.inputId.package, '.flutter-plugins-dependencies');
125127

@@ -136,7 +138,8 @@ Future<List<Plugin>> loadWebPlugins(BuildStep buildStep) async {
136138

137139
var content = await readPluginsDependencies();
138140

139-
if (content == null) {
141+
if (content == null && !_triedRunningFlutter) {
142+
_triedRunningFlutter = true;
140143
try {
141144
final result = await Process.run('flutter', ['packages', 'get']);
142145
if (result.exitCode != 0) {

packages/jaspr_cli/lib/src/commands/dev_command.dart

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,6 @@ abstract class DevCommand extends BaseCommand with ProxyHelper, FlutterHelper {
287287

288288
logger.write('Starting web compiler...', tag: Tag.cli, progress: ProgressState.running);
289289

290-
final webHotReload = argResults!.flag('web-hot-reload');
291-
final moduleFormat = webHotReload ? 'ddc' : (argResults!.option('module-format') ?? 'ddc');
292-
293-
logger.write('Starting web compilers...', tag: Tag.cli, progress: ProgressState.running);
294-
295290
final compiler = useWasm
296291
? 'dart2wasm'
297292
: release
@@ -325,7 +320,8 @@ abstract class DevCommand extends BaseCommand with ProxyHelper, FlutterHelper {
325320
'refresh' => ReloadConfiguration.liveReload,
326321
'restart' || _ => ReloadConfiguration.hotRestart,
327322
};
328-
final moduleFormat = this.moduleFormat ?? (reloadConfig == ReloadConfiguration.hotReload ? 'ddc' : 'amd');
323+
324+
final moduleFormat = reloadConfig == ReloadConfiguration.hotReload ? 'ddc' : this.moduleFormat ?? 'ddc';
329325
final usesDdcLibraryBundles = moduleFormat == 'ddc';
330326

331327
List<String> additionalFlutterBuildArgs() {

packages/jaspr_cli/lib/src/dev/dev_proxy.dart

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class DevProxy {
2020
final http.Client client;
2121
final Handler handler;
2222
final Stream<BuildResult> buildResults;
23+
final ReloadConfiguration reload;
2324

2425
final Dwds dwds;
2526
final ExpressionCompilerService? ddcService;
@@ -28,14 +29,16 @@ class DevProxy {
2829
final _clientEvents = StreamController<Map<String, dynamic>>();
2930
Stream<Map<String, dynamic>> get clientEvents => _clientEvents.stream;
3031

31-
DevProxy._(
32-
this.client,
33-
this.handler,
34-
this.buildResults, {
32+
DevProxy._({
33+
required this.client,
34+
required this.handler,
35+
required this.buildResults,
36+
required this.reload,
3537
required this.dwds,
3638
this.ddcService,
3739
}) {
3840
_listenToClientConnections();
41+
_listenToBuildResults();
3942
}
4043

4144
Future<void> _listenToClientConnections() async {
@@ -51,6 +54,18 @@ class DevProxy {
5154
}
5255
}
5356

57+
void _listenToBuildResults() async {
58+
if (reload == ReloadConfiguration.hotReload) {
59+
await for (final buildResult in buildResults) {
60+
if (buildResult.status == BuildStatus.succeeded) {
61+
for (final clientConnection in _clientConnections.values) {
62+
await clientConnection.performHotReload();
63+
}
64+
}
65+
}
66+
}
67+
}
68+
5469
ClientConnection? getClientConnection(String? appId) {
5570
if (appId == null) return null;
5671
return _clientConnections[appId];
@@ -120,16 +135,19 @@ class DevProxy {
120135

121136
final reloadedSourcesUri = Uri.parse('/reloaded_sources.json');
122137

138+
// We handle hot-reload ourselves, so we don't need the DDC service to do it.
139+
final reloadStrategy = reload == ReloadConfiguration.hotReload ? ReloadConfiguration.none : reload;
140+
123141
final loadStrategy = moduleFormat == 'ddc'
124142
? BuildRunnerDdcLibraryBundleStrategyProvider(
125-
reload,
143+
reloadStrategy,
126144
assetReader,
127145
buildSettings,
128146
packageConfigPath: findPackageConfigFilePath(),
129147
reloadedSourcesUri: reloadedSourcesUri,
130148
).strategy
131149
: BuildRunnerRequireStrategyProvider(
132-
reload,
150+
reloadStrategy,
133151
assetReader,
134152
buildSettings,
135153
packageConfigPath: findPackageConfigFilePath(),
@@ -174,7 +192,6 @@ class DevProxy {
174192

175193
if (moduleFormat == 'ddc') {
176194
cascade = cascade.add((Request req) {
177-
print("middleware reloaded sources: ${req.url.path}");
178195
if (req.url.path == 'reloaded_sources.json') {
179196
return Response.ok(jsonEncode(reloadedSources), headers: {'content-type': 'application/json'});
180197
}
@@ -188,9 +205,10 @@ class DevProxy {
188205
cascade = cascade.add(assetHandler);
189206

190207
return DevProxy._(
191-
client,
192-
pipeline.addHandler(cascade.handler),
193-
filteredBuildResults,
208+
client: client,
209+
handler: pipeline.addHandler(cascade.handler),
210+
buildResults: filteredBuildResults,
211+
reload: reload,
194212
dwds: dwds,
195213
ddcService: ddcService,
196214
);
@@ -287,6 +305,7 @@ class ClientConnection {
287305

288306
void start() async {
289307
final appId = appConnection.request.appId;
308+
290309
try {
291310
final debugConnection = _debugConnection = await dwds.debugConnection(appConnection);
292311
final debugUri = debugConnection.ddsUri ?? debugConnection.uri;
@@ -343,15 +362,13 @@ class ClientConnection {
343362
}
344363

345364
void sendEvent(String method, Map<String, dynamic> params) {
346-
print('event: $method $params');
347365
devProxy._clientEvents.add({'method': method, 'params': params});
348366
}
349367

350368
// Mapping from service name to service method.
351369
final Map<String, String> _registeredMethodsForService = <String, String>{};
352370

353371
void _onServiceEvent(vm.Event e) {
354-
print('service event: ${e.kind} ${e.service} ${e.method}');
355372
if (e.kind == vm.EventKind.kServiceRegistered) {
356373
final serviceName = e.service!;
357374
_registeredMethodsForService[serviceName] = e.method!;
@@ -369,6 +386,20 @@ class ClientConnection {
369386
return response;
370387
}
371388

389+
Future<void> performHotReload() async {
390+
final isolateId = (await vmService?.getVM())?.isolates?.first.id;
391+
vm.ReloadReport? response;
392+
for (var i = 0; i < 5; i++) {
393+
response = await vmService?.reloadSources(isolateId!);
394+
if (response?.success ?? false) {
395+
break;
396+
}
397+
}
398+
if (response?.success ?? false) {
399+
await reassemble();
400+
}
401+
}
402+
372403
Future<vm.Response?> reassemble() async {
373404
final reassembleMethod = _registeredMethodsForService['ext.jaspr.reassemble'] ?? 'ext.jaspr.reassemble';
374405
try {

packages/jaspr_cli/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,4 @@ dependencies:
5353

5454
dev_dependencies:
5555
mocktail: ^1.0.4
56-
test: ^1.22.0
56+
test: ^1.22.0

pubspec.lock

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,14 @@ packages:
194194
source: hosted
195195
version: "3.5.10"
196196
build_web_compilers:
197-
dependency: transitive
197+
dependency: "direct overridden"
198198
description:
199-
name: build_web_compilers
200-
sha256: f7020628ddf67db7619025ff64b1d3e890419410c4356a28757907db6e61a1f8
201-
url: "https://pub.dev"
202-
source: hosted
203-
version: "4.4.15"
199+
path: "builder_pkgs/build_web_compilers"
200+
ref: HEAD
201+
resolved-ref: f4cabecdb834819022dd845c600978b8e4ecdc38
202+
url: "https://github.com/dart-lang/build"
203+
source: git
204+
version: "4.4.20-wip"
204205
built_collection:
205206
dependency: transitive
206207
description:

pubspec.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@ dev_dependencies:
3333
melos: ^7.1.0
3434

3535
dependency_overrides:
36-
cli_util: 0.5.0 # Until melos upgrades to this version
36+
# Until melos upgrades to this version
37+
cli_util: 0.5.0
38+
# Until 4.4.20 is released
39+
build_web_compilers:
40+
git:
41+
url: https://github.com/dart-lang/build
42+
path: builder_pkgs/build_web_compilers
3743

3844
melos:
3945
command:

0 commit comments

Comments
 (0)