środa, 1 sierpnia 2018

Polymer 2 to Polymer 3

Introduction
I decided to upgrade from Polymer 2 to Polymer 3. According to

"we've made a smooth upgrade path our top priority for Polymer 3.0. Polymer's API remains almost unchanged, and we're providing an upgrade tool (polymer-modulizer) that will automatically handle most of the work in converting your 2.x-based elements and apps to 3.0.".

Encouraged by this advertisement, I run "modulizer --out ." and ... It depends on what one means by "most of the work" and "smooth".

I understand the rationale behind that but Chrome browser I'm using obviously does not. It still insists that @polymer is a directory name and demands the path name to resolve it. Adding the path names manually is challenging because not only custom elements should be touched but also all internal Polymer elements. So it looks that some kind of "build" process is necessary after every upgrade. After some trials, errors and research I ended up using:

polymer build --module-resolution node

which does the job. Then I replace current "node_modules" directory with "build/default/node_modules". In the case of the Polymer upgrade, "yarn install" should be launched beforehand. Previously, no build process was required. It was enough to run "bower install".

ReferenceError: IntlMessageFormat is not defined

Uncaught (in promise) ReferenceError: IntlMessageFormat is not defined
at HTMLElement. (app-localize-behavior.js:285)
at runMethodEffect (property-effects.js:905)
at Function._evaluateBinding (property-effects.js:3079)
at Object.runBindingEffect [as fn] (property-effects.js:648)
at runEffectsForProperty (property-effects.js:169)
at runEffects (property-effects.js:131)
at HTMLElement._propagatePropertyChanges (property-effects.js:1933)
at HTMLElement._propertiesChanged (property-effects.js:1891)
at HTMLElement._flushProperties (properties-changed.js:370)
at HTMLElement._flushProperties (property-effects.js:1731)

Unfortunately, "polymer build" does not catch "node_modules/intl-messageformat" package and it is absent after build. So we have to reinstall the package again.

npm install intl-messageformat

ReferenceError: IntlMessageFormat is not defined
Although "intl-messageformat" is downloaded, it should be also imported somewhere to make "IntMessageFormat" class visible.
I ended up patching manually "node_modules/@polymer/app-localize-behavior/app-localize-behavior.js" file.

Uncaught TypeError: Cannot set property 'IntlMessageFormat' of undefined
at main.js:7
at main.js:7

It was a stab in the back because Chrome does not tell where this disaster happens. After some time I found a hint here.
The solution is to patch manually "node_modules/intl-messageformat/dist/intl-messageformat.js".
At the end of the file replace:

Uncaught ReferenceError: KeyframeEffect is not defined
This exception was thrown from paper-dropdown-menu element. Instead of spending time trying to resolve it, I decided to remove this dependency and replaced it with something different.
Replace namespace with imports
In Polymer 2 I was using Polymer namespace for custom classes.

"modulizer" utility has nothing to do with that, it should be done manually.Conclusion
"Smooth upgrade" ended up in several sleepless nights. But in the end, I made it. On the whole, I really like this ES6 module, it provides a good encapsulation and isolation which is very important in every programming language including JavaScript.