Upgrading Plugins for NativeScript 7 and following
In my previous blogpost, I wrote about updating an app from NativeScript 6.5 to 8, taking 7 as the necessary step in between. The app is basically working but major functionality is missing as it crashes as soon it tries to execute functions from an internally maintained plugin.
Must read when upgrading plugins: https://blog.nativescript.org/nativescript-7-for-plugin-authors/
That post offers a 6-step procedure to convert a plugin which I will follow.
Basic steps for migration are the same as for the app: Remove deep imports from core
, fix references.d.ts
file, etc
Step 3 about @NativeClass
decorator needs some more attention as we have implemented quite a lot of the iOS part of the plugin directly in TypeScript.
As with the move to Angular 10, some Angular specific consideration have to be made for plugins as described in that blogpost. But as we did not choose to implement such in our plugin, I´m fine here and do not need to take care of specifics.
To migrate the sample apps, I need to take basically the same steps as I did for the main application.
After I have the demo-apps migrated and get to the point to test the plugin using these, I run into a problem on iOS:
Our iOS specific code (TypeScript using ObjC interfaces) contains static methods and calls to them, e.g. a class
@NativeClass()
export ViewControllerWrapper extends UIViewController {
(...)
public static initWithOptionsAndStrategy(options: LogicOptions, logicStrategy: LogicStrategy): ViewControllerWrapper {
(...)
return wrapper;
}
(...)
}
and a call to that initializer method:
const view = ViewControllerWrapper.initWithOptionsAndStrategy(...);
The error I get during runtime (build is fine) is CONSOLE LOG: Error: rejected Cannot read property 'initWithOptionsAndStrategy' of undefined
. That means that the javascript resulting from the transpilation does not have a valid referenece to my static method.
Also, I get this warning during build
WARNING in /Users/markus/src/plugin/src/ios/ViewControllerWrapper.ts 269:55-91
"export 'ViewControllerWrapper' was not found in './ViewControllerWrapper'
@ /Users/markus/src/plugin/src/SomeAction.ts
@ ./app.ts
The solution to this is described in the best-practices articles for @NativeClass in the NativeScript docs. I need to seperate the export
from the class declaration as the @NativeClass
decorator changes the JS syntax and thus breaks the export.
So, instead of
@NativeClass()
export class CustomClass extends NSObject {}
we need to do
@NativeClass()
class CustomClass extends NSObject {}
export { CustomClass }
On testing my plugin in the app (build & package a tgz locally and reference it from the app´s package.json
with file:/path/to/plugin.tgz
instead of the version number), I got errors sayint Uncaught ReferenceError: NativeClass is not defined
.
Which appeared like an packaging error to me, so I had to revise the webpack.config and ths tsconfig
.
It turned out that my tsconfig.json
was actually missing the following that takes care for the NativeClass items:
"plugins": [
{
"transform": "@nativescript/webpack/transformers/ns-transform-native-classes",
"type": "raw"
}
],
Finally, I stumbled over a "declaration: false"
setting in the plugin´s tsconfig.json
– with this set, the generated code in the packaged plugin will not be useable to the app as typescript will not find the expected code to import classes. It has to be set to true
.
And with this, the migration of the custom plugins is complete and we have our app migrated to NS 7. 🎉