NativeScript / nativescript-dev-webpack

A package to help with webpacking NativeScript apps.
Apache License 2.0
97 stars 49 forks source link

XML Compatibility issue between NS-Angular and NS-Core #1121

Open NathanaelA opened 4 years ago

NathanaelA commented 4 years ago

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):

Callstack

 Error: Parsing XML at 3:5
JS:  > Module 'null' not found for element '@nstudio/nativescript-camera-plus:CameraPlus'.
JS:    > require's first parameter should be string Error: Parsing XML at 3:5
JS:  > Module 'null' not found for element '@nstudio/nativescript-camera-plus:CameraPlus'.
JS:    > require's first parameter should be string
JS:  > require's first parameter should be string
JS:     at require (<anonymous>:1:266)
JS:     at _loop_1 (file:///node_modules/@nativescript/core/globals/register-module-helpers.js:83:0)
JS:     at loadModule (file:///node_modules/@nativescript/core/globals/register-module-helpers.js:91:0)
JS:     at file:///node_modules/@nativescript/core/ui/builder/component-builder/component-builder.js:30:0
JS:     at Object.getComponentModule (file:///node_modules/@nativescript/core/ui/builder/component-builder/component-builder.js:116:0)
JS:     at loadCustomComponent (file:///node_modules/@nativescript/core/ui/builder/builder.js:138:0)
JS:     at ComponentParser.push.../node_modules/@nativescript/core/ui/builder/builder.js.ComponentParser.buildComponent (file:///data/data/org.nativescript.demong...
JS: Failed Error: Parsing XML at 3:5
JS:  > Module 'null' not found for element '@nstudio/nativescript-camera-plus:CameraPlus'.
JS:    > require's first parameter should be string Error: Parsing XML at 3:5
JS:  > Module 'null' not found for element '@nstudio/nativescript-camera-plus:CameraPlus'.
JS:    > require's first parameter should be string
JS:  > require's first parameter should be string
JS:     at require (<anonymous>:1:266)
JS:     at _loop_1 (file:///node_modules/@nativescript/core/globals/register-module-helpers.js:83:0)
JS:     at loadModule (file:///node_modules/@nativescript/core/globals/register-module-helpers.js:91:0)
JS:     at file:///node_modules/@nativescript/core/ui/builder/component-builder/component-builder.js:30:0
JS:     at Object.getComponentModule (file:///node_modules/@nativescript/core/ui/builder/component-builder/component-builder.js:116:0)
JS:     at loadCustomComponent (file:///node_modules/@nativescript/core/ui/builder/builder.js:138:0)
JS:     at ComponentParser.push.../node_modules/@nativescript/core/ui/builder/builder.js.ComponentParser.buildComponent (file:///data/data/org.nativescript...

Describe the bug I have a plugin that has its own custom XML/JS that it uses when it loads a model (using showmodal) the plugin works great on NS-Core. Unfortunately on Angular the webpack config breaks loading and the parse of NS-Core xml files.

The issue is that XML is treated differently between Angular webpack config and the NS-Core; when I manually changed my angular webpack.config.js file to be:

                { test: /\.xml$/, use: "nativescript-dev-webpack/xml-namespace-loader" },
                { test: /\.html$/, use: "raw-loader" },

Instead of both XML and HTML being raw-loader; my plugin will then work properly on Angular.

To Reproduce

  1. Have a XML file that is written as a NS-Core XML file with a namespaced component -- In my case this is it:
    <Page xmlns:Cam="@nstudio/nativescript-camera-plus" shownModally="shownModally" unloaded="unloaded">
    <GridLayout backgroundColor="#00000000" rows="*,auto,auto" columns="*">
    <Cam:CameraPlus id="camPlus"
                    loaded="camLoaded"
                   ... more props ...
                    debug="false">
    </Cam:CameraPlus>
        <Button row="1" id="recordButton" text="Record" tap="handleRecording" visibility="collapsed"/>
        <Button row="2" id="cancelButton" text="Cancel" tap="cancel" visibility="collapsed"/>
    </GridLayout>
    </Page>
  2. Use builder.Builder.parse(require("./camera.xml"),... So the xml is pulled into the bundle/vendor
  3. See error above...

Expected behavior The plugin to work on all platforms equally well. :grinning:

Sample project Need to check with client if I can share....

Workarounds

DimitarTachev commented 4 years ago

@NathanaelA,

As far as I understand, the plugin is trying to use the NativeScript Core Builder.parse API in order to load a NativeScript Core view (an XML file) in an Angular app and this leads to an XML parsing exception runtime.

I won't recommend you using the above-mentioned workarounds as they add some partial NativeScript Core support in the Angular apps of the end-users.

I believe that the proper solution would be making the UI plugin itself Angular compatible, instead of trying to add a NativeScript Core view in Angular apps.

I suggest you take a look at the Support Angular in UI Plugins and Integrating UI Components With Angular articles.

NathanaelA commented 4 years ago

@DimitarTachev - Go grab a cup of coffee; not sure you are all the way awake... :grinning: (This is meant to be a joke! :grinning: )


The page you linked to: https://docs.nativescript.org/angular/plugins/angular-third-party literally tells me to do exactly what my workaround is. :grinning: Which is why I tried that workaround, because I've done enough plugins to have ideas what might be a potential cause/solution. :grinning:

Angular components are almost always just wrapped NS-Core components; sometimes they have extra pieces, but very frequently; it is just a simple registerModule call. global.registerModule("plugin-namespace", () => require('plugin-name')); so that it is registered in the app as a valid namespace extension.

There are no issues using NS-Core components in Angular, Vue, Svelte, or even creating and disposing of them dynamically.


Now honestly, I don't know if this is something worth fixing, but it is a regression as it was something that used to work in NS < 6. But it is a corner case, and probably only a corner case a plugin would run into as if you are doing a Angular app; you won't normally be using the NS-Core builder to do things. But plugins might; and this is where the question of compatibility needs to be decided.

DimitarTachev commented 4 years ago

@NathanaelA , I didn't get that you are doing the first workaround in the plugin itself. 😄

In the legacy workflow (before NativeScript 6.0 and without --bundle), we were copying all of the app files allowing any dynamic executions.

Once we've migrated to the Webpack workflow, we had issues with the NativeScript Core applications because the dependencies between the different views/components were not easily analyzable - you are able to navigate, build a dynamic view or reference UI from plugins by using simple strings (without importing/requiring any modules). In order to keep the Webpack workflow as close as possible to the legacy one for NativeScript Core apps, we've included all XML, CSS and JS files from the app folder and we've implemented the above-mentioned xml-namespace-loader which is analyzing the XML namespace strings and automatically registering their dependencies (in this case the plugin files).

The reasons why we've not implemented a similar approach for the Angular apps are: 1) We are using the AngularCompilerPlugin plugin which is automatically analyzing these dependencies and even creating additional files for the lazy routes. This plugin also has some strict restrictions for the loaders that should be used for the Angular files. 2) Some of the users were using .xml instead of .html for their Angular view. 3) Its a corner case that could be handled in the plugins by a manual registration.

I will mark the issue as a feature request but bear in mind that it would be a risky change.