Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to fix compilation errors when not building for web? #317

Open
gdurandrexel opened this issue Oct 16, 2024 · 10 comments
Open

How to fix compilation errors when not building for web? #317

gdurandrexel opened this issue Oct 16, 2024 · 10 comments
Labels
type-enhancement A request for a change that isn't a bug

Comments

@gdurandrexel
Copy link

gdurandrexel commented Oct 16, 2024

I have a flutter app that should support mobile and web, but compilation fails when building for mobile with errors such as "Dart library 'dart:js_interop' is not available on this platform.".

In my code I import dart:io and web/web and use kIsWeb to call IO methods or web methods.

When compiling for web, importing dart:io does not cause any problem.

I've read about creating a stub file and importing io or web implementations, but my code is sprinkled with kIsWeb checks with tiny bits of code.
Is it really the only way to make this work? How come importing dart:io is fine but web/web is not?
Could this package provide a stub so we can write something like this:

import 'package:web/web_stub.dart' as web
  if (dart.library.js_interop) 'package:web/web.dart';
@srujzs
Copy link
Contributor

srujzs commented Oct 22, 2024

kIsWeb separates code logic so that you only call web APIs when compiling to web and vice versa. In this case, a stub could work, but checking for kIsWeb everywhere is quite clunky. Instead, I'd stub out the platform-specific logic and then call those stubs.

When compiling for web, importing dart:io does not cause any problem.

Can you elaborate? Are you using a stub there to avoid the unsupported error?

@gdurandrexel
Copy link
Author

kIsWeb is convenient when only a tiny portion of your code is dependent of the platform. Without this I have to create 3 files (stub, io, web) and create a public function for just 3 lines of code in each platform, instead of writing if(kIsWeb) doWebStuff else doIOStuff. It's cumbersome to implement and maintain. So I wanted to know if there was another way.

If I import dart:io, to use Platform.isAndroid for instance, this compiles fine for web and I can call the io code conditionally at runtime. If I import web/web is does not compile for io, which prevents to use kIsWeb to branch platform-specific code as described above. Actually is seems to be more dart:js_interop that complains, but since web/web imports it, it is basically the same.
So if I ever need to import web/web, I have to go the stub way, which is overkill in my opinion in several instances in my code.

I'm not very familiar with all this: I've just stumbled upon this kind of problem recently. So if you tell me there's no way to import web/web without going the stub way, that's fine.

@tiprecpago
Copy link

@srujzs I am having the exact same issue.

Even though my code logic is wrapped around if (kIsWeb), just by having the import

import 'package:web/web.dart';

it causes my project to stop compiling to native platform targets.

Just like @gdurandrexel suggested, the solution in this case was to create a stub file and add a conditional import.

import 'package:web_stub.dart'
  if (dart.library.js_interop) 'package:web/web.dart';

I would be really nice to have this stub file created inside the package so it doesn't affect native platform targets or maybe just add this info to the package's home page, just in case someone else has the same problem.

@srujzs
Copy link
Contributor

srujzs commented Oct 29, 2024

Without this I have to create 3 files (stub, io, web) and create a public function for just 3 lines of code in each platform, instead of writing if(kIsWeb) doWebStuff else doIOStuff.

I may be wrong, but I think you only need two stubs - one for the VM and one for web and then just do a conditional like you were thinking of for package:web:

import 'vm_impl.dart' as impl
  if (dart.library.js_interop) 'web_impl.dart';

So if you tell me there's no way to import web/web without going the stub way, that's fine.

Ultimately if you want to avoid creating your own more general stubs and want to still use kIsWeb, a stub of all of web is the only remaining solution. The VM will indeed complain you're importing a platform-specific library, because that's what package:web is.

I would be really nice to have this stub file created inside the package so it doesn't affect native platform targets or maybe just add this info to the package's home page, just in case someone else has the same problem.

It's a good idea to put this in the README or an FAQ. I'm not completely opposed to a stub of web - it just feels like the wrong solution when you're comparing with the package ecosystem. I also recognize that that opinion adds some onus on users to implement their specific stubs I'm proposing above.

Similar issue: #55

@srujzs srujzs added the type-enhancement A request for a change that isn't a bug label Oct 29, 2024
@srujzs srujzs changed the title How to fix compilation errors when not building for web? Can a VM stub for package:web be provided? Oct 29, 2024
@srujzs srujzs changed the title Can a VM stub for package:web be provided? How to fix compilation errors when not building for web? Oct 29, 2024
@gdurandrexel
Copy link
Author

Yes, you're right, I need only 2 files as you explained. I had come across several examples with another stub file and at that time I was still in my copy/paste phase regarding this new kind of problem.

Yes, a full stub of web/web may work, and I proposed this solution because the code is generated, so it might not be too much work or need too much maintenance (though it may, I have no idea). There would still be the problem of dart:js_interop that surfaces in the API. If we cannot apply the same technique for this package also, then there is no point in creating a stub for web/web I suppose.

@srujzs
Copy link
Contributor

srujzs commented Oct 30, 2024

If we cannot apply the same technique for this package also, then there is no point in creating a stub for web/web I suppose.

Agreed. We may be able to get away with typedefs, but I'm not sure. We definitely do not want to either do a huge breaking change to web or stub dart:js_interop on the VM.

@ykmnkmi
Copy link

ykmnkmi commented Oct 31, 2024

Is there a way to override dart:* package paths? Similar to passing a path to an overridden package_config.json.

@kevmoo
Copy link
Member

kevmoo commented Nov 1, 2024

Is there a way to override dart:* package paths? Similar to passing a path to an overridden package_config.json.

Nope. dart: libraries are hard-wired. What do you want to override? (Also, this is a bit off-topic)

@ykmnkmi
Copy link

ykmnkmi commented Nov 1, 2024

@kevmoo I mean that we could use it to provide paths to the patched web and js_interop packages, if that’s possible.

@kevmoo
Copy link
Member

kevmoo commented Nov 1, 2024

you can override web, but js_interop is baked in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-enhancement A request for a change that isn't a bug
Projects
Status: No status
Development

No branches or pull requests

5 participants