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

Static binding generator fails when using Webpack + Workers #778

Closed
sis0k0 opened this issue Jun 8, 2017 · 45 comments
Closed

Static binding generator fails when using Webpack + Workers #778

sis0k0 opened this issue Jun 8, 2017 · 45 comments
Assignees
Labels
Milestone

Comments

@sis0k0
Copy link
Contributor

sis0k0 commented Jun 8, 2017

Example case:
Setup - project with web worker file where the worker imports 'globals'.
If you webpack the project, a bundle named [hash].worker.js will be generated and it will contain the whole tns-core-modules package.
Since tns-core-modules is also contained in the vendor chunk, the static binding generator will fail:

Warning: there already is an extend called com.tns.FragmentClass.
Warning: The static binding generator will generate extend from:b8fc197268e0dd59663c.worker.js implementation
:asbg:generateBindings
Exception in thread "main" java.io.IOException: File already exists. This may lead to undesired behavior. Building 55% > :asbg:generateBindings
Please change the name of one of the extended classes.
/home/svlaeva@bedford.progress.com/nativescript-webpack-workers-issue/platforms/android/src/main/java/com/tns/FragmentClass.java
        at org.nativescript.staticbindinggenerator.Generator.writeBindings(Generator.java:59)
        at org.nativescript.staticbindinggenerator.Main.main(Main.java:15)
:asbg:generateBindings FAILED
@petekanev
Copy link
Contributor

petekanev commented Jun 8, 2017

Starting off I'd like to point something out - that behavior IS expected.

The build-time exception is often a sign that something isn't quite right with the files - you have dupes, or you extend the same class, with the same name, meaning if the build was uninterrupted - only one of the two extended classes will pass, which may result in unexpected behavior/bugs runtime.

I think we can make it so the sbg will spit out a warning message when two of the same classes have the same content, and not throw, while still throwing an exception with that particular error message if contents of the two files differs.

@danielgek
Copy link

danielgek commented Jun 8, 2017

@Pip3r4o i saw your branch about this issue, do you have a build i can test/use ?
i have a release pending on this :P
thanks in advance

@petekanev
Copy link
Contributor

petekanev commented Jun 8, 2017

@danielgek you can fetch the branch, and build the .jar locally, then simply replace it in build-tools/android-static-binding-generator. (navigate to android-static-binding-generator/project/staticbindinggenerator && ./gradlew build - the output jar will be in build/libs)

However these changes will not fix or work around the problem that @sis0k0 has described with webpacked workers. While the two files whose contents are being compared may look the same, there is a very important bit (JavaScriptImplementation annotation) that will fail the check.

@danielgek
Copy link

@Pip3r4o i was already doing that xD, but yeah i got the same error, thanks for the help !!

@PeterStaev
Copy link

I'm hitting this same issue when developing plugins that have @Interfaces() decorated classes. So I make changes to the local TS files for the plugin. Then go to the demo project and do a tns run android and very often I get this error because the static binding generated decides to create a new file. I guess happens because it detects that the plugin files have changed (i.e. installed a new version of the plugin) and decides to generate again the Java classes but does not clear the old ones. Also tns run android --clean does not seem to fix the problem and you have to do tns platform clean android to fix the problem.

In case of plugins the CLI/Runtime should detect that a new version of the plugin is used and should automatically remove the old java classes that have been generated by this plugin so the new ones can be generated successfully. Or it should just override the existing classes with the new ones.

@petekanev
Copy link
Contributor

@PeterStaev I recently pushed a change to the sbg logic to make it less aggressive during a build. That is achieved by always invalidating the list of to-be-generated classes.

@PeterStaev
Copy link

Thanks @Pip3r4o ! I've just tried the @next of the android runtime and it is working really nice 👍 Will speed up plugin dev tremendously! 😄

@mcrvaz
Copy link

mcrvaz commented Jun 20, 2017

I was having an issue with a duplicated DropDownAdapter class from nativescript-drop-down and @next solved it.

@abhayastudios
Copy link

I am still experiencing this issue when running npm run start-android-bundle with NS 3.1.1:

$ tns info
All NativeScript components versions information
┌──────────────────┬─────────────────┬────────────────┬─────────────┐
│ Component        │ Current version │ Latest version │ Information │
│ nativescript     │ 3.1.1           │ 3.1.1          │ Up to date  │
│ tns-core-modules │ 3.1.0           │ 3.1.0          │ Up to date  │
│ tns-android      │ 3.1.1           │ 3.1.1          │ Up to date  │
│ tns-ios          │ 3.1.0           │ 3.1.0          │ Up to date  │
└──────────────────┴─────────────────┴────────────────┴─────────────┘

Did I understand wrong that this was supposed to be fixed in this version?

@petekanev
Copy link
Contributor

Having duplicate classes with the same name will fail your build, and that is expectrd, yes. Read the error carefully and see where the conflicts are.

@abhayastudios
Copy link

@Pip3r4o thanks for the reply. As far as I understand, I encounter this issue due to a web worker that I am using in my plugin as is explained in this issue. Shouldn't web workers be supported out of the box?

I see that @sis0k0 explains that "you don't really need to import globals in your worker" so I tried not to include the globals in the worker, but even then I am getting the same error:

Running full build
finished with reading lines with js files
Warning: there already is an extend called com.tns.FragmentClass.
Warning: The static binding generator will generate extend from:vendor.js implementation
:asbg:generateBindings
Exception in thread "main" java.io.IOException: File already exists. This may lead to undesired behavior.
Please change the name of one of the extended classes.
File:/Users/joni/projects/nativescript-webpack-error-app/platforms/android/src/main/java/com/tns/FragmentClass.java Class: com.tns.FragmentClass
        at org.nativescript.staticbindinggenerator.Generator.writeBindings(Generator.java:68)
        at org.nativescript.staticbindinggenerator.Main.main(Main.java:15)
:asbg:generateBindings FAILED

@quentinor
Copy link

Hi,

I believe I am having the same problem as @sis0k0 , trying to webpack an {N} app with a web worker:

Exception in thread "main" java.io.IOException: File already exists. This may lead to undesired behavior.
Please change the name of one of the extended classes.
File:/home/quentin/Projects/hubup-nativescript-clover/platforms/android/src/main/java/com/tns/FragmentClass.java Class: com.tns.FragmentClass
        at org.nativescript.staticbindinggenerator.Generator.writeBindings(Generator.java:68)
        at org.nativescript.staticbindinggenerator.Main.main(Main.java:15)
:asbg:generateBindings FAILED

I waited a few weeks before migrating to {N} V3, but now, it is becoming more and more pressing that I keep my app up to date :)

So is there a workaround for workers, or is there a release where this prob is fixed ?

Thanks

@petekanev
Copy link
Contributor

@quentinor we have not put any specific effort towards resolving this particular issue. We are still deliberating how to best handle the case with webpack, since it essentially pours the scripts you already use in the main bundle into the worker script bundle. The static binding generator does not, at this point, differentiate between a regular script, and one that will be used on a worker thread.

For the time being, avoid importing the tns-core-modules into a worker script, when webpacking. That should be sufficient to let the android build complete.

@petekanev petekanev added this to the 3.2.0 milestone Aug 3, 2017
@leocrawf
Copy link

leocrawf commented Aug 8, 2017

Hello Pip3r4o. You said:" For the time being, avoid importing the tns-core-modules into a worker script, when webpacking. That should be sufficient to let the android build complete."

How do you do that?

@danielgek
Copy link

@leocrawf don't import 'globals' as it is used by console

@petekanev petekanev changed the title Static binding generator fails if the same extended class exists more than once Static binding generator fails when using Webpack + Workers Aug 10, 2017
@KristianDD KristianDD added the bug label Aug 29, 2017
@bfv
Copy link

bfv commented Sep 11, 2017

I updated my project to 3.2.0. I'm still experiencing issues as described above when using var http = require("http"); in my worker.

@abhayastudios
Copy link

@bfv for me it is working fine. Make sure you are using nativescript-dev-webpack v0.8.0.

@bfv
Copy link

bfv commented Sep 11, 2017

I am using nativescript-dev-webpack v0.8.0. Strange.

@abhayastudios
Copy link

@bfv yeah I had some issues as well, until I just created a new project and then copied my app dir and relevant files to the new project and did the installation of nativescript-dev-webpack from scratch. There are so many dev deps there that I wasn't sure everything was updated to the latest. Anyway eventually it started working.

@sis0k0
Copy link
Contributor Author

sis0k0 commented Sep 11, 2017

@bfv @abhayastudios
You need these loader and plugin - https://github.com/nativescript/worker-loader.

@erjdriver
Copy link

Is this the official and permanent solution for worker threads and web-pack - or is this a temporary fix.

btw I commented out my global imports and I was still getting the FragmentClass refined error.

@danielgek
Copy link

@erjdriver https://github.com/nativescript/worker-loader is the official way of getting workers working with AOT/Webpack

@n4lexeev
Copy link

n4lexeev commented Oct 3, 2017

same problem, how to solve it ?

@petekanev
Copy link
Contributor

@Nurgunkalol please have a look at the README at https://github.com/nativescript/worker-loader explaining how to configure the worker loader for webpack.

@erjdriver
Copy link

erjdriver commented Oct 3, 2017

I followed the instructions - developing in typescript.

I installed nativescript-worker-loader.

The webpack.config.js file was auto generated

Then I tried to include the worker file as:

import * as WorkerScript from "nativescript-worker-loader!./worker-script";

with worker-script replaced with my filename.

I'm getting a module not found error in vscode.

but if I ignore it and build/run it, I get the same redefinition FragmentClass error.

This is in android with 3.2

@abhayastudios
Copy link

@erjdriver I'm pretty sure you need to feed a .js file as the worker. I use something like this:

if (global.TNS_WEBPACK) {
  let Worker = require("nativescript-worker-loader!./assets/js/phonebook-worker.js");
  worker = new Worker;
} else {
  worker = new Worker('./assets/js/phonebook-worker.js');
}

@erjdriver
Copy link

@abhayastudios the README page says support for typescript files.

@petekanev
Copy link
Contributor

@erjdriver TypeScript files are transpiled down to JavaScript, so you should have javascripts at runtime.

@erjdriver
Copy link

I'm using the syntax in the README file for ts worker files

import * as WorkerScript from "nativescript-worker-loader!./worker-script";

I understand TS compiles down to JS.

But in the app folder there's no .js files - even for my other files. I assume that's something webpack is doing - storing it somewhere else.

Issue #1 is that above import statement results in module-not-found error. Even though I've got the correct ts file in the app folder.

Issue #2 is at startup time, I get the FragmentClass redefinition error that the OP wrote about.

@erjdriver
Copy link

Here's the error that gets displayed when i try to webpack on the android

Note the error "not cacheable"

`[224] ../node_modules/nativescript-worker-loader!./worker-check-version.ts 119 bytes {0} [not cacheable] [built]
+ 320 hidden modules

ERROR in [at-loader] ./app/utils.ts:19:37
TS2307: Cannot find module 'nativescript-worker-loader!./worker-check-version'.`

When I try to include the file from /app/utils.ts file -I get the cannot-find-module error

@abhayastudios
Copy link

@erjdriver as far as I know you need to explicitly reference the .js file (not the .ts file) since the .js file is what needs to be executed runtime. I don't know whether webpack transpiles typescript sources for workers as I wrote my worker in plain ES6. However, as a debug step, I would try to manually transpile your .ts file to .js and reference that one just to check whether it works.

Regarding the FragmentClass exception: are you sure you are using nativescript-dev-webpack ^0.8.0 in your package.json? If so, then try removing the android platform and adding it back again.

@erjdriver
Copy link

@abhayastudios thank you for your suggestions.

  1. dumb question - how do i force a transcompile. In my apps folder there are NO js files - even for the other files. I assume that's because webpack is doing something.

  2. i'm pretty sure - but i'll do your suggestion once I get past resolved issue #40 #1.

@abhayastudios
Copy link

You can run tsc worker-name.ts which should produce the JavaScript version. You can also copy/paste the TypeScript code into their playground for an online transpilation.

@petekanev
Copy link
Contributor

@erjdriver since your worker is done in TypeScript, did you follow the README steps strictly? Did you make a typings file? -> https://github.com/nativescript/worker-loader#integrating-with-typescript

@erjdriver
Copy link

ok making some progress.

I added the typings folder in the root and am not getting the module-not-found error any more.

The build succeeds.

But when the app tries to run in the emulator.

I removed and added the android platform before the build.

`finished with reading lines with js files
Warning: there already is an extend called com.tns.FragmentClass.
Warning: The static binding generator will generate extend from:vendor.js implementation
Exception in thread "main" java.io.IOException: File already exists. This may lead to undesired behavior.
Please change the name of one of the extended classes.
File:C:\Users\MyPC\nativescript\test4b\platforms\android\src\main\java\com\tns\FragmentClass.java Class: com.tns.FragmentClass
at org.nativescript.staticbindinggenerator.Generator.writeBindings(Generator.java:68)
at org.nativescript.staticbindinggenerator.Main.main(Main.java:15)

FAILURE: Build failed with an exception.`

@erjdriver
Copy link

This issue is still not fixed - not sure why it was closed.

Still getting the duplicate FragmentClass error.

I've commented out all the Worker references and still getting the error.

@petekanev
Copy link
Contributor

@erjdriver please provide a minimalistic sample repository to help us debug the problem, as I am unable to reproduce it on my end.

@legioner0
Copy link

@erjdriver did you try tns platform clean android, as @PeterStaev say? This command fixed FragmentClass error in my project.

@PeterStaev
Copy link

Seems there is some problem with @next (3.3) version. I just got a PR for the Drop Down plugin to support Angular 4.4 (PeterStaev/NativeScript-Drop-Down#138) and this failed the the CI build with the Fragment class error: https://travis-ci.org/PeterStaev/NativeScript-Drop-Down/jobs/286806719#L3749 .

@petekanev
Copy link
Contributor

@PeterStaev I am not sure it is a problem with the @next of the android runtime. I tested master branch of your plugin's demo (tns build android) with the latest versions of angular and the nativescript-angular plugin. The project built fine without exceptions.

@PeterStaev
Copy link

@Pip3r4o seems you are correct. It could have been something specific to the specific version that was used in the PR. With the resubmited PR with @next there is no error 👍

@petekanev
Copy link
Contributor

@erjdriver I created a minimalistic sample of loading a worker in typescript, following the nativescript-worker-loader README. You can find the sample in the pete/workertsbranch of the demo-worker repo -> https://github.com/NativeScript/demo-workers/tree/pete/workerts

@erjdriver
Copy link

erjdriver commented Oct 12, 2017

@Pip3r4o - thanks for getting back to me and taking the time to create the test project.

I solved the problem.

The problem was that in my bundle-config.ts file, I had

global.registerModule("nativescript-telerik-ui/sidedrawer", function () { return require("nativescript-telerik-ui/sidedrawer"); });

global.registerModule("nativescript-telerik-ui/sidedrawer/drawerpage", () => require("nativescript-telerik-ui/sidedrawer/drawerpage"));

I was getting the multiple definition of FragmentClass.

If I comment out the second line - then it works.

Weird because I got those two lines from some sample projects on github.

Hopefully this will help someone else...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests