schultek / jaspr

Modern web framework for building websites in Dart. Supports SPAs and SSR.
https://jasprpad.schultek.de
MIT License
996 stars 59 forks source link

fix: Hot reload always crashes on Static Mode after a syntax error is introduced at one point, even when it's fixed afterwards #216

Closed dhafinrayhan closed 2 months ago

dhafinrayhan commented 3 months ago

Description

When running development (jaspr serve) on Static Mode, hot reload always crashes and can't recover after at one point there's a syntax error in the code (even after the syntax error is fixed afterwards).

Steps To Reproduce

  1. Create a new project using jaspr create my_website.
  2. Choose static rendering mode (which should be the default).
  3. Let other setup options with their default selections.
  4. Run jaspr serve.
  5. Open the page in a browser.
  6. Introduce a syntax error. For example, you can add a component to the middle of a list without the mandatory separator comma:
    yield section([
      img(src: 'images/logo.png', width: 80),
      h1([text('Welcome')]),
      // Syntax error below (missing comma)
      Counter()
      p([text('You successfully create a new Jaspr site.')]),
      div(styles: Styles.box(height: 100.px), []),
      const Counter(),
    ]);
  7. Notice that hot reload crashes, which is expected.
    [BUILDER] [ERROR] This builder requires Dart inputs without syntax errors.
    [BUILDER] [ERROR] However, package:jas_static/pages/home.dart (or an existing part) contains the following errors.
    [BUILDER] [ERROR] home.dart:16:7: Expected to find ','.
    [BUILDER] [ERROR]
    [BUILDER] [ERROR] Try fixing the errors and re-running the build.
  8. Fix the syntax error (add comma after Counter()).
  9. Notice that hot reload still crashes, even when there are no more syntax errors.
    [SERVER] [ERROR] ERROR - 2024-04-08 13:11:15.623075
    [SERVER] [ERROR] GET /
    [SERVER] [ERROR] Error thrown by handler.
    [SERVER] [ERROR] ClientException: HTTP request failed. Client is already closed., uri=http://localhost:5567/
    [SERVER] [ERROR] package:http/src/io_client.dart 110:7            IOClient.send
    [SERVER] [ERROR] package:shelf_proxy/shelf_proxy.dart 59:48       proxyHandler.<fn>
    [SERVER] [ERROR] package:shelf_gzip/src/gzip_encoding.dart 51:44  createGzipMiddleware.<fn>.<fn>.<fn>
    [SERVER] [ERROR] dart:async                                       new Future.sync
    [SERVER] [ERROR] package:shelf_gzip/src/gzip_encoding.dart 51:21  createGzipMiddleware.<fn>.<fn>
    [SERVER] [ERROR] ERROR - 2024-04-08 13:11:15.644062
    [SERVER] [ERROR] GET /favicon.ico
  10. If you refresh the page on the browser, it will show you "Internal Server Error".

Doctor Output

[✓] Jaspr CLI (Version 0.11.1)
  • Dart Version 3.3.1 (stable) (Wed Mar 6 13:09:19 2024 +0000) on "windows_x64" at dart
  • Running on windows "Windows 10 Home Single Language" 10.0 (Build 22631) - Locale en-ID
  • Analytics: Enabled

[✓] Current Project
  • Dependencies on core packages:
    • jaspr: ^0.11.1
    • jaspr_builder: ^0.11.1 (dev)
    • jaspr_web_compilers: ^4.0.9 (dev)
    • jaspr_router: ^0.4.0
  • Rendering mode: static
  • Uses jaspr compilers: true
  • Uses flutter embedding: false

Expected Behavior

Hot reload should work normally after the syntax error is fixed.

Additional Context

This error does not happen when the project is running on Server Mode.

schultek commented 2 months ago

There really is no difference between server and static mode when running ' jaspr serve'. I also cannot reproduce this reliably.

Are you using any other dependencies than the ones from the starting project?

dhafinrayhan commented 2 months ago

No, there are no other dependencies, no other changes. The steps I did is exactly as mentioned above.

Yeah, I believe there should be no differences between the two, but apparently it always happens when I use Static Mode and does not happen in Server Mode somehow.

schultek commented 2 months ago

Ok super weird, I can only reproduce this error when

  1. I'm starting from a clean project (delete .dart_tool and run dart pub get)
  2. I'm navigating to a different tab between step 5 and 6

Still no idea where the error comes from

schultek commented 2 months ago

Ok I think I know now. A very subtle race-condition inside the reloading logic

schultek commented 2 months ago

@dhafinrayhan Can you test if this is fixed with the following dependency override:

dependency_overrides:
  jaspr:
    git:
      url: https://github.com/schultek/jaspr
      path: packages/jaspr
      ref: fix/reload-racecondition
dhafinrayhan commented 2 months ago

Looking great! Seems like that fixes the issue.