Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

App crashes when using builder within custom component after bundle-build with webpack #867

Closed
felixkrautschuk opened this issue Apr 17, 2019 · 9 comments
Assignees
Labels
docs migration-to-bundle The issue is describing a breaking change in the Bundle workflow compared to the Legacy one.

Comments

@felixkrautschuk
Copy link

Environment
Provide version numbers for the following components (information can be retrieved by running tns info in your project folder or by inspecting the package.json of the project):

  • CLI: 5.3.2
  • Cross-platform modules: 5.3.1
  • Android Runtime: 5.3.1
  • iOS Runtime: -
  • Plugin(s): nativescript-ui-listview
  • Node.js: -

Just the config files package.json, webpack.config.js, bundle-config.js:
config_file.zip

Describe the bug
I have two custom components (code-only) in my app: DropdownList.js and Pagination.js.
In the Pagination.js component, I try to add the DropdownList component within the Pagination component like this:

//app/shared/pagination/Pagination.js

var Pagination = (function (_super) {
    global.__extends(Pagination, _super);

    function Pagination() {
        var _this = _super.call(this);

        var dropdown = builder.load({
            path: 'shared/dropdown/DropdownList',
            name: 'DropdownList'
        });

        _this.addChild(dropdown);

        ...
    }

...
})(gridLayoutModule.GridLayout);
<!-- main-page.xml -->
<Page xmlns:pagination="shared/pagination/Pagination">
    ...
    <StackLayout class="p-20">
        <pagination:Pagination countPages="{{ countPages }}" page="{{ page }}" selectedPageChanged="onSelectedPageChanged"/>
    </StackLayout>
</Page>

But when navigating to page that uses the pagination component, the app crashes.

Please note that everything works as expected when building the app without the --bundle flage.

I have no idea where to start searching the cause of this issue.

I tried to register the components in bundle-config.js

if (global.TNS_WEBPACK) {
    // Register custom modules
    global.registerModule("nativescript-ui-listview",
        () => require("../node_modules/nativescript-ui-listview"));

    global.registerModule("DropdownList",
        () => require("./shared/dropdown/DropdownList"));

    global.registerModule("Pagination",
        () => require("./shared/pagination/Pagination"));
}

I also added the shared folder here within webpack.config.js:

new CopyWebpackPlugin([
                { from: { glob: "fonts/**" } },
                { from: { glob: "shared/**" } },
                { from: { glob: "**/*.jpg" } },
                { from: { glob: "**/*.png" } },
]

The crashlog can be found here:

System.err: java.lang.RuntimeException: Unable to start activity ComponentInfo{org.nativescript.NSWebPackCustomComponent/com.tns.NativeScriptActivity}: com.tns.NativeScriptException:
System.err: Calling js method onCreate failed
System.err:
System.err: Error: Parsing XML at 1:1
System.err: > Parsing XML at 28:9
System.err: > Module 'shared/pagination/Pagination' not found for element 'shared/pagination/Pagination:Pagination'.
System.err: > Module '/data/data/org.nativescript.NSWebPackCustomComponent/files/app/shared/dropdown/DropdownList' not found for element 'shared/dropdown/DropdownList:DropdownList'.
System.err: > com.tns.NativeScriptException: Failed to find module: "tns-core-modules/ui/layouts/grid-layout", relative to: app/tns_modules/
System.err: com.tns.Module.resolvePathHelper(Module.java:146)
System.err: com.tns.Module.resolvePath(Module.java:55)
System.err: com.tns.Runtime.callJSMethodNative(Native Method)
System.err: com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1203)
System.err: com.tns.Runtime.callJSMethodImpl(Runtime.java:1083)
System.err: com.tns.Runtime.callJSMethod(Runtime.java:1070)
System.err: com.tns.Runtime.callJSMethod(Runtime.java:1050)
System.err: com.tns.Runtime.callJSMethod(Runtime.java:1042)
System.err: com.tns.NativeScriptActivity.onCreate(NativeScriptActivity.java:19)
System.err: android.app.Activity.performCreate(Activity.java:7136)
System.err: android.app.Activity.performCreate(Activity.java:7127)
System.err: android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
System.err: android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2926)
System.err: android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081)
System.err: android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
System.err: android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
System.err: android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
System.err: android.app.ActivityThread$H.handleMessage(ActivityThread.java:1838)
System.err: android.os.Handler.dispatchMessage(Handler.java:106)
System.err: android.os.Looper.loop(Looper.java:193)
System.err: android.app.ActivityThread.main(ActivityThread.java:6715)
System.err: java.lang.reflect.Method.invoke(Native Method)
System.err: com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
System.err: com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)
System.err: File: "file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js, line: 15786, column: 20
System.err:
System.err: StackTrace:
System.err: Frame: function:'ScopeError', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 36010, column: 24
System.err: Frame: function:'PositionErrorFormat', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15799, column: 16
System.err: Frame: function:'', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15786, column: 33
System.err: Frame: function:'', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 37128, column: 13
System.err: Frame: function:'push.../node_modules/tns-core-modules/js-libs/easysax/easysax.js.EasySAXParser.parse', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 10436, column: 23
System.err: Frame: function:'push.../node_modules/tns-core-modules/xml/xml.js.XmlParser.parse', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 37175, column: 22
System.err: Frame: function:'push.../node_modules/tns-core-modules/ui/builder/builder.js.XmlStringParser.parse', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15792, column: 27
System.err: Frame: function:'parseInternal', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15754, column: 11
System.err: Frame: function:'loadInternal', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15654, column: 27
System.err: Frame: function:'loadPage', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15588, column: 27
System.err: Frame: function:'', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15609, column: 12
System.err: Frame: function:'', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15623, column: 20
System.err: Frame: function:'push.../node_modules/tns-core-modules/ui/frame/frame.js.ActivityCallbacksImplementation.setActivityContent', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 24669, column: 42
System.err: Frame: function:'push.../node_modules/tns-core-modules/ui/frame/frame.js.ActivityCallbacksImplementation.onCreate', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 24502, column: 14
System.err: Frame: function:'push.../node_modules/tns-core-modules/ui/frame/activity.js.NativeScriptActivity.onCreate', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 22415, column: 25
System.err:
System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2946)
System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081)
System.err: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
System.err: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
System.err: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1838)
System.err: at android.os.Handler.dispatchMessage(Handler.java:106)
System.err: at android.os.Looper.loop(Looper.java:193)
System.err: at android.app.ActivityThread.main(ActivityThread.java:6715)
System.err: at java.lang.reflect.Method.invoke(Native Method)
System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)
System.err: Caused by: com.tns.NativeScriptException:
System.err: Calling js method onCreate failed
System.err:
System.err: Error: Parsing XML at 1:1
System.err: > Parsing XML at 28:9
System.err: > Module 'shared/pagination/Pagination' not found for element 'shared/pagination/Pagination:Pagination'.
System.err: > Module '/data/data/org.nativescript.NSWebPackCustomComponent/files/app/shared/dropdown/DropdownList' not found for element 'shared/dropdown/DropdownList:DropdownList'.
System.err: > com.tns.NativeScriptException: Failed to find module: "tns-core-modules/ui/layouts/grid-layout", relative to: app/tns_modules/
System.err: com.tns.Module.resolvePathHelper(Module.java:146)
System.err: com.tns.Module.resolvePath(Module.java:55)
System.err: com.tns.Runtime.callJSMethodNative(Native Method)
System.err: com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1203)
System.err: com.tns.Runtime.callJSMethodImpl(Runtime.java:1083)
System.err: com.tns.Runtime.callJSMethod(Runtime.java:1070)
System.err: com.tns.Runtime.callJSMethod(Runtime.java:1050)
System.err: com.tns.Runtime.callJSMethod(Runtime.java:1042)
System.err: com.tns.NativeScriptActivity.onCreate(NativeScriptActivity.java:19)
System.err: android.app.Activity.performCreate(Activity.java:7136)
System.err: android.app.Activity.performCreate(Activity.java:7127)
System.err: android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
System.err: android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2926)
System.err: android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081)
System.err: android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
System.err: android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
System.err: android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
System.err: android.app.ActivityThread$H.handleMessage(ActivityThread.java:1838)
System.err: android.os.Handler.dispatchMessage(Handler.java:106)
System.err: android.os.Looper.loop(Looper.java:193)
System.err: android.app.ActivityThread.main(ActivityThread.java:6715)
System.err: java.lang.reflect.Method.invoke(Native Method)
System.err: com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
System.err: com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)
System.err: File: "file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js, line: 15786, column: 20
System.err:
System.err: StackTrace:
System.err: Frame: function:'ScopeError', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 36010, column: 24
System.err: Frame: function:'PositionErrorFormat', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15799, column: 16
System.err: Frame: function:'', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15786, column: 33
System.err: Frame: function:'', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 37128, column: 13
System.err: Frame: function:'push.../node_modules/tns-core-modules/js-libs/easysax/easysax.js.EasySAXParser.parse', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 10436, column: 23
System.err: Frame: function:'push.../node_modules/tns-core-modules/xml/xml.js.XmlParser.parse', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 37175, column: 22
System.err: Frame: function:'push.../node_modules/tns-core-modules/ui/builder/builder.js.XmlStringParser.parse', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15792, column: 27
System.err: Frame: function:'parseInternal', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15754, column: 11
System.err: Frame: function:'loadInternal', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15654, column: 27
System.err: Frame: function:'loadPage', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15588, column: 27
System.err: Frame: function:'', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15609, column: 12
System.err: Frame: function:'', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 15623, column: 20
System.err: Frame: function:'push.../node_modules/tns-core-modules/ui/frame/frame.js.ActivityCallbacksImplementation.setActivityContent', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 24669, column: 42
System.err: Frame: function:'push.../node_modules/tns-core-modules/ui/frame/frame.js.ActivityCallbacksImplementation.onCreate', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 24502, column: 14
System.err: Frame: function:'push.../node_modules/tns-core-modules/ui/frame/activity.js.NativeScriptActivity.onCreate', file:'file:///data/data/org.nativescript.NSWebPackCustomComponent/files/app/vendor.js', line: 22415, column: 25
System.err:
System.err: at com.tns.Runtime.callJSMethodNative(Native Method)
System.err: at com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1203)
System.err: at com.tns.Runtime.callJSMethodImpl(Runtime.java:1083)
System.err: at com.tns.Runtime.callJSMethod(Runtime.java:1070)
System.err: at com.tns.Runtime.callJSMethod(Runtime.java:1050)
System.err: at com.tns.Runtime.callJSMethod(Runtime.java:1042)
System.err: at com.tns.NativeScriptActivity.onCreate(NativeScriptActivity.java:19)
System.err: at android.app.Activity.performCreate(Activity.java:7136)
System.err: at android.app.Activity.performCreate(Activity.java:7127)
System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2926)
System.err: ... 11 more

The strange thing is this part of the crashlog:

Failed to find module: "tns-core-modules/ui/layouts/grid-layout", relative to: app/tns_modules/

To Reproduce
Just start the sample project, it will crash immediately, as I try to include the Pagination component in the main-page.xml.

Expected behavior

Sample project
Full sample project:
NSWebPackCustomComponent.zip

I appreciate any hint to figure out what causes this issue.
Again I want to mention one more time, that everything works when not using webpack (tns run android)

@DimitarTachev
Copy link
Contributor

Hi @felix-idf,

Thanks for the detailed explanation and the sample project.

When you run an app with Webpack (--bundle), all pages and custom components have to be registered by calling the global.registerModule method.

In order to make this process easier, each xml, css and js file ending with page or root (e.g. main-page.js) is automatically registered by our bundle-config-loader.

There is also xml-namespace-loader which is analyzing the XML of your pages and registers the custom components defined with xmlns like your xmlns:pagination="shared/pagination/Pagination" component from your main-page.xml.

In other words, you are getting this exception because the DropDownList component is dynamically loaded by builder.load (not with XML namespace + tag) and it's name is not ending with page or root.

You've been really close by calling

global.registerModule("DropdownList",
    () => require("./shared/dropdown/DropdownList"));

in your bundle-config.js, but the key should match the path used in the builder.load method and you need:

global.registerModule("shared/dropdown/DropdownList",
    () => require("./shared/dropdown/DropdownList"));

In order to get your app working, you currently have the following options:

  1. Manually register the dynamically loaded components by their path (as shown in the example above).
  2. Use the drop-down component directly in your pagination XML (like you use the pagination in your main-page).
  3. Make your custom component files end with page (this will be strange).
  4. Edit your webpack.config.js and pass an additional convention to the registerModules property of the bundle config loader. For example, initialize the loader as shown below and rename your DropdownList.js to DropdownList-fragment.js:
...
loader: "nativescript-dev-webpack/bundle-config-loader",
options: {
    loadCss: !snapshot, // load the application css if in debug mode
    unitTesting,
    appFullPath,
    projectRoot,
    registerModules: /(root|page|fragment)\.(xml|css|js|ts|scss)$/ // <-- fragment is added here
}
...

then you just need to load the component with the new name:

var dropdown = builder.load({
    path: 'shared/dropdown/DropdownList-fragment',
    name: 'DropdownList'
});

I hope this clarifies the issue. We are also thinking about exposing an easier API for more page/component conventions in addition to page and root or directly adding a few more conventions in the loader (e.g. fragment and component). In this way, we will avoid overriding the whole regex as shown in point (4). What do you think about these ideas and the best solution applicable to your application?

@felixkrautschuk
Copy link
Author

Hi @DimitarTachev ,

thank you for the detailed explanation. This really helps.

I fixed the issue with the Pagination component by editing the global.registerModule call and using the correct path there.

So for now, a mix of your sugesstions 1 and 4 seem to be applicable for us.

Besides those javascript components (like DropdownBase and Pagination and some other ones) we have multiple xml-snippets in our project, that we want to share between several places in our app. But the code-behind of the elements within the snippet is defined for each page, where the snippet is used.
While working without WebPack, this creates a new issue for us when using --bundle, that is described here: #865

So if there is nothing that can be done from the NativeScript side to bring us the old behaviour when not using WebPack, then we will have to put those snippets to fragments and register them like it is done in suggestion 4. We will see...

So from here, thank you very much for your detailed help and for investigating this issue.

@NickIliev
Copy link
Contributor

extend documentation section here

@markusmauch
Copy link

Where is the bundle-config.js located? I don't find it in my project.

@DimitarTachev
Copy link
Contributor

Hi @markusmauch,

That's just a file from the sample project attached in the issue. There's nothing special about it.

The requirement is that the component should be registered before the application.run call in your app entry (e.g. app.js).

In the attached project, there is a require("./bundle-config") call in app.js and that's the reason I was referring to this file.

In other words, you can register the custom component directly in your app.js (before the application.run call) or extract this logic in <another-file>.js and require it in your app entry.

@markusmauch
Copy link

@DimitarTachev Thanks for the clarification. Is it also possible to use this in order to register XML files?

global.registerModule("shared/dropdown/DropdownList.xml", () => require("./shared/dropdown/DropdownList.xml"));

@NathanaelA
Copy link

@DimitarTachev - Is there a way we can do this global.registerModule to register its CSS/XML inside our plugins. I have a couple plugins that have attached xml/css. One of the things you mentioned above is that it should be done before application.run but most plugins are actually loaded as screens are loaded...

(Also isn't bundle-config.js depreciated, I don't recall seeing it in any of the modern template sets.)

@DimitarTachev
Copy link
Contributor

@markusmauch, yes, it's possible and currently required :) If you are using the builder.load API in order to programmatically include a component inside your page, you have to manually register the component along with its xml and css files.

@NathanaelA, the app developers using the builder.load API should handle some manual components registration. However, this should be a rare and corner case and in most of the cases, the components are directly used in the xml files (example). In such cases, the xml-namespace-loader is automatically registering the required UI components from the plugins along with their corresponding xml and css files.

We do not recommend a manual registration from the plugin authors because registering all of the plugin components inside the plugin will break the UI components tree shaking as these UI components will be forcefully included in the app bundle.

@DimitarTachev
Copy link
Contributor

I'm closing this issue as starting from this PR and NativeScript 6.0, we are automatically including all app files instead of requiring the old -page or -root convention.

You could also take a look at this issue comment for a way of excluding files from the Webpack compilation.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
docs migration-to-bundle The issue is describing a breaking change in the Bundle workflow compared to the Legacy one.
Projects
None yet
Development

No branches or pull requests

6 participants