srawlins / timezone

Time zone database and time zone aware DateTime object for Dart.
BSD 2-Clause "Simplified" License
102 stars 54 forks source link

Flutter web not including .tzf #68

Open pblinux opened 4 years ago

pblinux commented 4 years ago

Hello.

I'm having a trouble with tzf files, I think the database is not included into generated assets for web. Everything works fine in debug but when I run flutter build web and then run the generated static site, a 404 error is showing for: packages/timezone/data/latest.tzf that comes from the flutter_service_worker.js.

Maybe Am I skipping a configuration step or something?

Thanks.

srawlins commented 4 years ago

I've not had the chance to try this package with flutter web. But I'd recommend using the initializeTimeZones API which doesn't rely on loading assets like the tzf files.

pblinux commented 4 years ago

Hi @srawlins

With initializeTimeZone occurs the same. At the moment the solution I have found is to include the .tzf file in the assets and then load it with initializeDatabase.

Maybe this need a specific process to include it in assets when building a Flutter web app for production.

srawlins commented 4 years ago

With initializeTimeZone occurs the same.

I'd recommend using the initializeTimeZones API, not initializeTimeZone.

pblinux commented 4 years ago

@srawlins sorry, I meant initializeTimeZones, not initializeTimeZone. With initializeTimeZones it's the same problem.

pointshd commented 3 years ago

Same here, the web bundle built with flutter build web doesn't include the packages/timezone/data folder.

But using initializeTimeZones does work since it doesn't load network resources.


The problem with initializeTimeZone is that the data urls are different for production web build, there's a /assets prefix before every resource path, i.e. /assets/packages/timezone/data/latest.tzf.

For this to work, we need to in include the tzf file in the pubspec.yaml file, like this:

assets:
    - packages/timezone/data/latest.tzf

This file will end up in build/web/assets/packages/timezone/data/latest.tzf.

And in our code, we need to check if we are in production mode and add the /assets prefix;

raphael-bmec-co commented 2 years ago

See https://github.com/flutter/flutter/issues/67655

You can add the /assets prefix in production and development and then you don't need to change anything:

initializeTimeZone('assets/packages/timezone/data/latest_10y.tzf')

srawlins commented 1 year ago

At this point, everything should be loaded from the .dart data files, which do not require the tzf files at runtime.

raphael-bmec-co commented 1 year ago

@srawlins can you explain how this would change the code? Or point us to some updated documentation?

Bungeefan commented 1 year ago

@srawlins Could we request an update for the following sentence from the README? As, after your statement, this doesn't seem to be the case anymore.

I am specifically talking about the for non-browser environments part.

https://github.com/srawlins/timezone/blob/5ea548f6da991b354e735a484d9192430f46a4fa/README.md?plain=1#L35-L38

srawlins commented 1 year ago

Ah sorry, I misremembered and/or misread.

Maybe something does need to be done, either documentation or implementation, for Flutter web.

@srawlins sorry, I meant initializeTimeZones, not initializeTimeZone. With initializeTimeZones it's the same problem.

@pblinux can you show the error, and the import statement which provides initializeTimeZones? No .tzf files should be requested. Maybe the 404 can be ignored.

Bungeefan commented 1 year ago

Thanks for coming back to me/us!


Maybe I can provide some information here:

This only happens in the release build, as the request for latest.tzf works in the debug build!

Error (Doesn't show much as it's in release):

js_helper.dart:1123 Uncaught Invalid argument(s): Invalid typed array length: 1008813135
    at Object.c (http://localhost:42173/main.dart.js:4783:3)
    at biT.$1 (http://localhost:42173/main.dart.js:139898:15)
    at alr.pU (http://localhost:42173/main.dart.js:55864:32)
    at pT.aQU (http://localhost:42173/main.dart.js:54805:10)
    at b6K.$0 (http://localhost:42173/main.dart.js:54962:37)
    at Object.Hb (http://localhost:42173/main.dart.js:6112:78)
    at am.ql (http://localhost:42173/main.dart.js:54872:3)
    at b6D.$0 (http://localhost:42173/main.dart.js:54919:13)
    at Object.bPN (http://localhost:42173/main.dart.js:6144:5)
    at adC.bQo (http://localhost:42173/main.dart.js:6146:7)

I was only able to pinpoint it to this library as the latest.tzf request was the only one that failed, and without the init call it worked again.

Import used for dart.library.html: import 'package:timezone/browser.dart' as tz; with tz.initializeTimeZone();

Import used for dart.library.io: import 'package:timezone/data/latest.dart' as tz; with tz.initializeTimeZones();

This reproduced the error above, if I use the same import for io and html (Browser and Mobile) it works flawlessly, and no request is made, despite the documentation.

Sidenote:

If you use flutter run --release the request doesn't fail as the web server just returns the index.html (which probably triggers the js array error) instead of an 404 error, but if you use an un-configured web server as for example python3 -m http.server a proper HTTP 404 is returned.

Error with un-configured web server and failed request:

main.dart.js:4783 Uncaught Instance of 'minified:lC'
    at Object.c (http://0.0.0.0:8000/main.dart.js:4783:3)
    at biT.$1 (http://0.0.0.0:8000/main.dart.js:139898:15)
    at alr.pU (http://0.0.0.0:8000/main.dart.js:55864:32)
    at pT.aQU (http://0.0.0.0:8000/main.dart.js:54805:10)
    at b6K.$0 (http://0.0.0.0:8000/main.dart.js:54962:37)
    at Object.Hb (http://0.0.0.0:8000/main.dart.js:6112:78)
    at am.hu (http://0.0.0.0:8000/main.dart.js:54875:3)
    at b6C.$0 (http://0.0.0.0:8000/main.dart.js:54925:13)
    at Object.bPN (http://0.0.0.0:8000/main.dart.js:6144:5)
    at adC.bQo (http://0.0.0.0:8000/main.dart.js:6146:7)

Therefore, I requested to update the documentation because the paragraph about "non-browser environments" was confusing, as the same import for both environments works now.

However, maybe there is more to do than to fix the docs.

maxlapides commented 1 year ago

I think I found a workaround for this issue.

First, add the asset to your pubspec.yaml:

  assets:
    - packages/timezone/data/latest.tzf

(Got this idea from this open PR: https://github.com/srawlins/timezone/pull/122/files)

Then, update your web code to specify the path for the latest.tzf file:

tz.initializeTimeZone('assets/packages/timezone/data/latest.tzf');

Note that we are prefixing the path with assets/ -- this is the fix needed to dynamically load the timezone data correctly.

To import the asset on mobile, you can use this:

const path = 'packages/timezone/data/latest.tzf';
tz.initializeDatabase(
  Uint8List.sublistView(await rootBundle.load(path)),
);

I think this probably means that there should be an update to browser.dart in this package to correctly fetch the asset, what do you think @srawlins?

MarcBritton commented 8 months ago

We have an application running on Mobile and Web and we ran into the same problem with .tzf files not loading on web.

Per this comment just initialising from the Dart files, not browser.dart, seems to work on web as well.

Can the README.md be updated so that instead of recommending different methods of initialisation for browser vs web, the "Initialization from Dart library" approach is recommended as the default for all platforms?

raphael-bmec-co commented 4 months ago

I'd like to +1 the proposal by @MarcBritton. We've been misled a few times by this point in the documentation.