Ask Questions and Find Answers
Important:
Ask is now read-only. You can review any existing questions and answers, but not add anything new.
But - don't panic! While ask is no more, we've replaced it with discuss - the new Liferay Discussion Forum! Read more here here or just visit the site here:
discuss.liferay.com
RE: Debugging React portlet loading
My company is relatively new to our Liferay implementation, and I am working specifically on developing React portlets for inclusion within our portal. I have come across several issues when trying to take running standalone applications and use them within a widget page (admittedly, self-induced problems - more on that in a minute), and unfortunately have yet to figure out an efficient way to debug why a given portlet won't load.
Examples:
* I had an issue where an errant unescaped character (the literal @ symbol, such as me@mycompany.com, in a block of text on a page) worked just fine when running the application in standalone fashion...but threw an error like "Path [my-project@1.0.0.js] does not start with a "/" character" in both the browser console and the log files for my local Liferay instance when attempting to load the application as a portlet. Once I finally tracked down the character, and used the ASCII code instead, my portlet loaded just fine.
* I had another issue where a build had failed for a dependent NPM module (a shared library of common functionality, including things like form fields/validation). Attempting to load the application into Liferay as a portlet on a widget page produced the same error as the previous example. Once I stepped back, and tried to run the application in standalone fashion, I immediately noticed an error related to the shared module not being able to load (because the published artifact was empty, save for a package.json and README.md).
* Far more common lately has been to take a running standalone React application (built upon the Liferay yeoman template, using the Liferay NPM bundler - run in standalone fashion using Webpack), and attempt to load it into a widget page. Even after extending the Javascript loader timeout (eventually, as much as 10 minute), loading of the portlet eventually times out - without any messaging whatsoever (just an empty portlet on the screen, with the title visible).
Questions:
* Is there additional linting or other checks I could be doing in my application before attempting to build it that could help me catch potential gotchas? (for instance, I saw another thread mentioning that importing css files is not supported yet - things like that, as well as the errant @ character example above, would be nice to catch before attempting to deploy)
* Is there additional logging I could be turning on/turning up on the Liferay side to see more information about the loading process as a portlet is deployed? Using the second example above, it would have been helpful to be able to see what specific modules the loader was attempting to load - and if a given module was successful.
* I am working through trying to find the happy middle ground between something simple (like the Tic Tac Toe example from the Front End Developer Training) and a more complex standalone app (like my multi-step form example, which in turn loads an internal NPM package...which in turn loads a form library and other shared packages) to try and determine when/where/why things break. Beyond additional debugging/logging, are there best practices around things like complexity/levels of nesting and/or packaging to "help" the Liferay loader more efficiently work through my dependencies?
Examples:
* I had an issue where an errant unescaped character (the literal @ symbol, such as me@mycompany.com, in a block of text on a page) worked just fine when running the application in standalone fashion...but threw an error like "Path [my-project@1.0.0.js] does not start with a "/" character" in both the browser console and the log files for my local Liferay instance when attempting to load the application as a portlet. Once I finally tracked down the character, and used the ASCII code instead, my portlet loaded just fine.
* I had another issue where a build had failed for a dependent NPM module (a shared library of common functionality, including things like form fields/validation). Attempting to load the application into Liferay as a portlet on a widget page produced the same error as the previous example. Once I stepped back, and tried to run the application in standalone fashion, I immediately noticed an error related to the shared module not being able to load (because the published artifact was empty, save for a package.json and README.md).
* Far more common lately has been to take a running standalone React application (built upon the Liferay yeoman template, using the Liferay NPM bundler - run in standalone fashion using Webpack), and attempt to load it into a widget page. Even after extending the Javascript loader timeout (eventually, as much as 10 minute), loading of the portlet eventually times out - without any messaging whatsoever (just an empty portlet on the screen, with the title visible).
Questions:
* Is there additional linting or other checks I could be doing in my application before attempting to build it that could help me catch potential gotchas? (for instance, I saw another thread mentioning that importing css files is not supported yet - things like that, as well as the errant @ character example above, would be nice to catch before attempting to deploy)
* Is there additional logging I could be turning on/turning up on the Liferay side to see more information about the loading process as a portlet is deployed? Using the second example above, it would have been helpful to be able to see what specific modules the loader was attempting to load - and if a given module was successful.
* I am working through trying to find the happy middle ground between something simple (like the Tic Tac Toe example from the Front End Developer Training) and a more complex standalone app (like my multi-step form example, which in turn loads an internal NPM package...which in turn loads a form library and other shared packages) to try and determine when/where/why things break. Beyond additional debugging/logging, are there best practices around things like complexity/levels of nesting and/or packaging to "help" the Liferay loader more efficiently work through my dependencies?
Additional information/example:I went back into the JavaScript Loader settings (Control Panel > Configuration > System Settings > Platform > Infrastructure), and turned on "Explain Module Resolutions" in an attempt to get more information. For one of my example React applications, I get the below message back in the browser console (after attempting to load it into a Widget page). How do I go about making sense of this, to the point where I have some actionable to look into further?
Liferay AMD Loader: Require call 4 resolved modules ["my-testing-project-too@1.0.25"] to ...
Liferay AMD Loader: Invoking failure handler for require call 4
-------------------------------------------------------------
Liferay AMD Loader: Unhandled require failure:
...
A detailed report of what happened follows:
· Require call id: 4
· Required modules: ["my-testing-project-too@1.0.25"]
· Error cause: Error: The following problems where detected while resolving modules:
· Missing required module 'my-testing-project-too@1.0.25'
at e.value (combo?browserId=other&minifierType=js&languageId=en_US&b=7210&t=1559659421456&/o/frontend-js-web/clay/popper.js&/o/frontend-js-web/clay/bootstrap.js&/o/frontend-js-web/loader/config.js&/o/frontend-js-web/loader/loader.js&/o/frontend-js-web/aui/aui/aui.js&/o/frontend-js-web/aui/aui-base-html5-shiv/aui-base-html5-shiv.js&/o/frontend-js-web/liferay/browser_selectors.js&/o/frontend-js-web/liferay/modules.js&/o/frontend-js-web/liferay/aui_sandbox.js&/o/frontend-js-web/clay/collapsible-search.js&/o/frontend-js-web/clay/side-navigation.js&/o/frontend-js-web/misc/svg4everybody.js&/o/frontend-js-web/aui/arraylist-add/arraylist-add.js&/o/frontend-js-web/aui/arraylist-filter/arraylist-filter.js&/o/frontend-js-web/aui/arraylist/arraylist.js&/o/frontend-js-web/aui/array-extras/array-extras.js&/o/frontend-js-web/aui/array-invoke/array-invoke.js&/o/frontend-js-web/aui/attribute-base/attribute-base.js&/o/frontend-js-web/aui/attribute-complex/attribute-complex.js&/o/frontend-js-web/aui/attribute-core/attribute-core.js&/o/frontend-js-web/aui/attribute-observable/attribute-observable.js&/o/frontend-js-web/aui/attribute-extras/attribute-extras.js&/o/frontend-js-web/aui/base-base/base-base.js&/o/frontend-js-web/aui/base-pluginhost/base-pluginhost.js&/o/frontend-js-web/aui/classnamemanager/classnamemanager.js&/o/frontend-js-web/aui/datatype-xml-format/datatype-xml-format.js&/o/frontend-js-web/aui/datatype-xml-parse/datatype-xml-parse.js&/o/frontend-js-web/aui/dom-base/dom-base.js&/o/frontend-js-web/aui/dom-core/dom-core.js&/o/frontend-js-web/aui/dom-screen/dom-screen.js&/o/frontend-js-web/aui/dom-style/dom-style.js&/o/frontend-js-web/aui/event-base/event-base.js&/o/frontend-js-web/aui/event-custom-base/event-custom-base.js&/o/frontend-js-web/aui/event-custom-complex/event-custom-complex.js&/o/frontend-js-web/aui/event-delegate/event-delegate.js&/o/frontend-js-web/aui/event-focus/event-focus.js&/o/frontend-js-web/aui/event-hover/event-hover.js&/o/frontend-js-web/aui/event-key/event-key.js:287)
at combo?browserId=other&minifierType=js&languageId=en_US&b=7210&t=1559659421456&/o/frontend-js-web/clay/popper.js&/o/frontend-js-web/clay/bootstrap.js&/o/frontend-js-web/loader/config.js&/o/frontend-js-web/loader/loader.js&/o/frontend-js-web/aui/aui/aui.js&/o/frontend-js-web/aui/aui-base-html5-shiv/aui-base-html5-shiv.js&/o/frontend-js-web/liferay/browser_selectors.js&/o/frontend-js-web/liferay/modules.js&/o/frontend-js-web/liferay/aui_sandbox.js&/o/frontend-js-web/clay/collapsible-search.js&/o/frontend-js-web/clay/side-navigation.js&/o/frontend-js-web/misc/svg4everybody.js&/o/frontend-js-web/aui/arraylist-add/arraylist-add.js&/o/frontend-js-web/aui/arraylist-filter/arraylist-filter.js&/o/frontend-js-web/aui/arraylist/arraylist.js&/o/frontend-js-web/aui/array-extras/array-extras.js&/o/frontend-js-web/aui/array-invoke/array-invoke.js&/o/frontend-js-web/aui/attribute-base/attribute-base.js&/o/frontend-js-web/aui/attribute-complex/attribute-complex.js&/o/frontend-js-web/aui/attribute-core/attribute-core.js&/o/frontend-js-web/aui/attribute-observable/attribute-observable.js&/o/frontend-js-web/aui/attribute-extras/attribute-extras.js&/o/frontend-js-web/aui/base-base/base-base.js&/o/frontend-js-web/aui/base-pluginhost/base-pluginhost.js&/o/frontend-js-web/aui/classnamemanager/classnamemanager.js&/o/frontend-js-web/aui/datatype-xml-format/datatype-xml-format.js&/o/frontend-js-web/aui/datatype-xml-parse/datatype-xml-parse.js&/o/frontend-js-web/aui/dom-base/dom-base.js&/o/frontend-js-web/aui/dom-core/dom-core.js&/o/frontend-js-web/aui/dom-screen/dom-screen.js&/o/frontend-js-web/aui/dom-style/dom-style.js&/o/frontend-js-web/aui/event-base/event-base.js&/o/frontend-js-web/aui/event-custom-base/event-custom-base.js&/o/frontend-js-web/aui/event-custom-complex/event-custom-complex.js&/o/frontend-js-web/aui/event-delegate/event-delegate.js&/o/frontend-js-web/aui/event-focus/event-focus.js&/o/frontend-js-web/aui/event-hover/event-hover.js&/o/frontend-js-web/aui/event-key/event-key.js:284
Liferay AMD Loader: Require call 4 resolved modules ["my-testing-project-too@1.0.25"] to ...
Liferay AMD Loader: Invoking failure handler for require call 4
-------------------------------------------------------------
Liferay AMD Loader: Unhandled require failure:
...
A detailed report of what happened follows:
· Require call id: 4
· Required modules: ["my-testing-project-too@1.0.25"]
· Error cause: Error: The following problems where detected while resolving modules:
· Missing required module 'my-testing-project-too@1.0.25'
at e.value (combo?browserId=other&minifierType=js&languageId=en_US&b=7210&t=1559659421456&/o/frontend-js-web/clay/popper.js&/o/frontend-js-web/clay/bootstrap.js&/o/frontend-js-web/loader/config.js&/o/frontend-js-web/loader/loader.js&/o/frontend-js-web/aui/aui/aui.js&/o/frontend-js-web/aui/aui-base-html5-shiv/aui-base-html5-shiv.js&/o/frontend-js-web/liferay/browser_selectors.js&/o/frontend-js-web/liferay/modules.js&/o/frontend-js-web/liferay/aui_sandbox.js&/o/frontend-js-web/clay/collapsible-search.js&/o/frontend-js-web/clay/side-navigation.js&/o/frontend-js-web/misc/svg4everybody.js&/o/frontend-js-web/aui/arraylist-add/arraylist-add.js&/o/frontend-js-web/aui/arraylist-filter/arraylist-filter.js&/o/frontend-js-web/aui/arraylist/arraylist.js&/o/frontend-js-web/aui/array-extras/array-extras.js&/o/frontend-js-web/aui/array-invoke/array-invoke.js&/o/frontend-js-web/aui/attribute-base/attribute-base.js&/o/frontend-js-web/aui/attribute-complex/attribute-complex.js&/o/frontend-js-web/aui/attribute-core/attribute-core.js&/o/frontend-js-web/aui/attribute-observable/attribute-observable.js&/o/frontend-js-web/aui/attribute-extras/attribute-extras.js&/o/frontend-js-web/aui/base-base/base-base.js&/o/frontend-js-web/aui/base-pluginhost/base-pluginhost.js&/o/frontend-js-web/aui/classnamemanager/classnamemanager.js&/o/frontend-js-web/aui/datatype-xml-format/datatype-xml-format.js&/o/frontend-js-web/aui/datatype-xml-parse/datatype-xml-parse.js&/o/frontend-js-web/aui/dom-base/dom-base.js&/o/frontend-js-web/aui/dom-core/dom-core.js&/o/frontend-js-web/aui/dom-screen/dom-screen.js&/o/frontend-js-web/aui/dom-style/dom-style.js&/o/frontend-js-web/aui/event-base/event-base.js&/o/frontend-js-web/aui/event-custom-base/event-custom-base.js&/o/frontend-js-web/aui/event-custom-complex/event-custom-complex.js&/o/frontend-js-web/aui/event-delegate/event-delegate.js&/o/frontend-js-web/aui/event-focus/event-focus.js&/o/frontend-js-web/aui/event-hover/event-hover.js&/o/frontend-js-web/aui/event-key/event-key.js:287)
at combo?browserId=other&minifierType=js&languageId=en_US&b=7210&t=1559659421456&/o/frontend-js-web/clay/popper.js&/o/frontend-js-web/clay/bootstrap.js&/o/frontend-js-web/loader/config.js&/o/frontend-js-web/loader/loader.js&/o/frontend-js-web/aui/aui/aui.js&/o/frontend-js-web/aui/aui-base-html5-shiv/aui-base-html5-shiv.js&/o/frontend-js-web/liferay/browser_selectors.js&/o/frontend-js-web/liferay/modules.js&/o/frontend-js-web/liferay/aui_sandbox.js&/o/frontend-js-web/clay/collapsible-search.js&/o/frontend-js-web/clay/side-navigation.js&/o/frontend-js-web/misc/svg4everybody.js&/o/frontend-js-web/aui/arraylist-add/arraylist-add.js&/o/frontend-js-web/aui/arraylist-filter/arraylist-filter.js&/o/frontend-js-web/aui/arraylist/arraylist.js&/o/frontend-js-web/aui/array-extras/array-extras.js&/o/frontend-js-web/aui/array-invoke/array-invoke.js&/o/frontend-js-web/aui/attribute-base/attribute-base.js&/o/frontend-js-web/aui/attribute-complex/attribute-complex.js&/o/frontend-js-web/aui/attribute-core/attribute-core.js&/o/frontend-js-web/aui/attribute-observable/attribute-observable.js&/o/frontend-js-web/aui/attribute-extras/attribute-extras.js&/o/frontend-js-web/aui/base-base/base-base.js&/o/frontend-js-web/aui/base-pluginhost/base-pluginhost.js&/o/frontend-js-web/aui/classnamemanager/classnamemanager.js&/o/frontend-js-web/aui/datatype-xml-format/datatype-xml-format.js&/o/frontend-js-web/aui/datatype-xml-parse/datatype-xml-parse.js&/o/frontend-js-web/aui/dom-base/dom-base.js&/o/frontend-js-web/aui/dom-core/dom-core.js&/o/frontend-js-web/aui/dom-screen/dom-screen.js&/o/frontend-js-web/aui/dom-style/dom-style.js&/o/frontend-js-web/aui/event-base/event-base.js&/o/frontend-js-web/aui/event-custom-base/event-custom-base.js&/o/frontend-js-web/aui/event-custom-complex/event-custom-complex.js&/o/frontend-js-web/aui/event-delegate/event-delegate.js&/o/frontend-js-web/aui/event-focus/event-focus.js&/o/frontend-js-web/aui/event-hover/event-hover.js&/o/frontend-js-web/aui/event-key/event-key.js:284
For reference (and maybe it will help someone else out), I did manage to get past the error in the last example (although mostly by dumb luck and following vague references in other threads, so I would still love some help with more efficient debugging/troubleshooting).
My project structure looked like the following (only the relevant portions represented):
/src
/src/components
/src/components/form
/src/components/form/myfirstcomponent.js
/src/components/form/mysecondcomponent.js
/src/components/form/index.js (this would expose the contents of this directory by importing each of them, and then directly exporting them)
...
/src/mypagecomponent.js (a page render, included in index.js - this would import the form components with a line like import { myfirstcomponent } from './components/form';)
/src/index.js (my application entrypoint)
After some playing around, it seems like my superfluous use of the /src/components/[...]/index.js pattern above was the culprit. This worked just fine when running in standalone mode (using Webpack), but the Liferay NPM Bundler didn't quite seem to know what to do with it (although no errors were shown until I actually tried to import the bundle into my portal instance).
My final structure looks more like the following:/src
/src/components
/src/components/form (index.js removed from here)
/src/components/form/myfirstcomponent.js
/src/components/form/mysecondcomponent.js
...
/src/mypagecomponent.js (a page render, included in index.js - this would import the form components with a line like import myfirstcomponent from './components/form/myfirstcomponent';, going after each component directly)
/src/index.js (my application entrypoint)
My project structure looked like the following (only the relevant portions represented):
/src
/src/components
/src/components/form
/src/components/form/myfirstcomponent.js
/src/components/form/mysecondcomponent.js
/src/components/form/index.js (this would expose the contents of this directory by importing each of them, and then directly exporting them)
...
/src/mypagecomponent.js (a page render, included in index.js - this would import the form components with a line like import { myfirstcomponent } from './components/form';)
/src/index.js (my application entrypoint)
After some playing around, it seems like my superfluous use of the /src/components/[...]/index.js pattern above was the culprit. This worked just fine when running in standalone mode (using Webpack), but the Liferay NPM Bundler didn't quite seem to know what to do with it (although no errors were shown until I actually tried to import the bundle into my portal instance).
My final structure looks more like the following:/src
/src/components
/src/components/form (index.js removed from here)
/src/components/form/myfirstcomponent.js
/src/components/form/mysecondcomponent.js
...
/src/mypagecomponent.js (a page render, included in index.js - this would import the form components with a line like import myfirstcomponent from './components/form/myfirstcomponent';, going after each component directly)
/src/index.js (my application entrypoint)
Hi Rich:
First of all, thanks a lot for your feedback. We need more like this to know how you developers, use the tools :-).
1.
Regarding the @ I would say it is an error. Where was the @ exactly and why did it make the setup fail?
2.
The import css thing is something we want to address. The problem with this kind of features is that there's no official guide on what should and shouldn't work in the frontend world.
So, for example, import css is apparently a webpack feature (or that's what they say in the create-react-app docs, for example) but people usually take it for granted for any other setup. In our case, we want to support it too, because we see its value, but it's impossible to know about all these features in advance.
I mean, we could decide to support this or warn about it, but if we don't know that it exists, the bundler will just see it and continue. That is because the bundler is at a syntactic level, but doesn't know the semantics of your app (the same happens with babel, typescript, or any other compiler, of course).
If someone invents some other idiom today that doesn't break the javascript syntax, but does some magic when the app is bundled, we cannot support or warn you until we analyze it and code the decided behaviour in the bundler.
3.
I see that you found the Explain Resolutions flag. That's good. It's the only way to get info about what the loader is doing. I would advise to disable the combo servlet (a.k.a. javascript fast load) while in development. That way, each JS module is loaded in a single HTTP request and things get much more easier. To do that edit your portal.properties file and set "javascript.fast.load=false".
Some other settings that aid in development are:
com.liferay.portal.servlet.filters.cache.CacheFilter=false
com.liferay.portal.servlet.filters.etag.ETagFilter=false
com.liferay.portal.servlet.filters.header.HeaderFilter=false
minifier.enabled=false
Once you do this, you will find that the loader resolution traces make more sense.
4.
Another good way to see what's happening with a specific module is to invoke the loader directly in the JS console. For example, in your case, you may run:
Liferay.Loader.get("my-testing-project-too@1.0.25", console.log);
And you would get the resolution trace you pasted or a console.log message with the correct result. Sometimes it's hard to know what is happening because several require calls are issued in parallel and the logs get intertwined. That's why each require call has an ID (a number) to be able to match deferred messages. But it's even easier if you can call require alone in a controlled way so that you only get one execution trace
Hope this helps. Feel free to ask about any other doubt.
Happy coding :-)
First of all, thanks a lot for your feedback. We need more like this to know how you developers, use the tools :-).
1.
Regarding the @ I would say it is an error. Where was the @ exactly and why did it make the setup fail?
2.
The import css thing is something we want to address. The problem with this kind of features is that there's no official guide on what should and shouldn't work in the frontend world.
So, for example, import css is apparently a webpack feature (or that's what they say in the create-react-app docs, for example) but people usually take it for granted for any other setup. In our case, we want to support it too, because we see its value, but it's impossible to know about all these features in advance.
I mean, we could decide to support this or warn about it, but if we don't know that it exists, the bundler will just see it and continue. That is because the bundler is at a syntactic level, but doesn't know the semantics of your app (the same happens with babel, typescript, or any other compiler, of course).
If someone invents some other idiom today that doesn't break the javascript syntax, but does some magic when the app is bundled, we cannot support or warn you until we analyze it and code the decided behaviour in the bundler.
3.
I see that you found the Explain Resolutions flag. That's good. It's the only way to get info about what the loader is doing. I would advise to disable the combo servlet (a.k.a. javascript fast load) while in development. That way, each JS module is loaded in a single HTTP request and things get much more easier. To do that edit your portal.properties file and set "javascript.fast.load=false".
Some other settings that aid in development are:
com.liferay.portal.servlet.filters.cache.CacheFilter=false
com.liferay.portal.servlet.filters.etag.ETagFilter=false
com.liferay.portal.servlet.filters.header.HeaderFilter=false
minifier.enabled=false
Once you do this, you will find that the loader resolution traces make more sense.
4.
Another good way to see what's happening with a specific module is to invoke the loader directly in the JS console. For example, in your case, you may run:
Liferay.Loader.get("my-testing-project-too@1.0.25", console.log);
And you would get the resolution trace you pasted or a console.log message with the correct result. Sometimes it's hard to know what is happening because several require calls are issued in parallel and the logs get intertwined. That's why each require call has an ID (a number) to be able to match deferred messages. But it's even easier if you can call require alone in a controlled way so that you only get one execution trace
Hope this helps. Feel free to ask about any other doubt.
Happy coding :-)
Ivan - Thanks for the reply! I will do my best to stick to your numbering scheme above to help the comments line up :-)
1) The @ symbol was within some text - something like index.js loads MyComponent.js, MyComponent.js including something like render() { return(...<div>Having trouble? Email us at contactus@mycompany.com!</div>...); }. Once I updated that portion to render() { return(...<div>Having trouble? Email us at contactus@mycompany.com!</div>...); }, my portlet was able to render. It caught me off guard, as there were no problems rendering this in standalone fashion (from Webpack), no compile/build errors...my portlet just didn't render. It was honestly a shot in the dark, as I basically broke everything done and started putting it in piece by piece until the portlet stopped loading.
2) I think that the bigger thing for me will be figuring out a more efficient development workflow. I was coming from built standalone apps to integrating them into the portal. My thinking is to have all CSS within the theme for the portal...but I also want to find a way to use that same CSS when developing a standalone app, before attempting to bundle it for inclusion into the portal (e.g., so that the developer has it available for development of pages/screens without having to go through the motions of bundling and loading into a local Liferay instance as they are working on a given task). This is still on my to do list, but I am imagining something like an in-house build process which both builds the theme WAR artifact, as well as some CSS files for loading directly into local development projects. Does that make sense/seem reasonable?
3 & 4) Perfect, thank you - that helps. I will keep those items in mind as development continues, and revisit as needed if anything else comes up!
1) The @ symbol was within some text - something like index.js loads MyComponent.js, MyComponent.js including something like render() { return(...<div>Having trouble? Email us at contactus@mycompany.com!</div>...); }. Once I updated that portion to render() { return(...<div>Having trouble? Email us at contactus@mycompany.com!</div>...); }, my portlet was able to render. It caught me off guard, as there were no problems rendering this in standalone fashion (from Webpack), no compile/build errors...my portlet just didn't render. It was honestly a shot in the dark, as I basically broke everything done and started putting it in piece by piece until the portlet stopped loading.
2) I think that the bigger thing for me will be figuring out a more efficient development workflow. I was coming from built standalone apps to integrating them into the portal. My thinking is to have all CSS within the theme for the portal...but I also want to find a way to use that same CSS when developing a standalone app, before attempting to bundle it for inclusion into the portal (e.g., so that the developer has it available for development of pages/screens without having to go through the motions of bundling and loading into a local Liferay instance as they are working on a given task). This is still on my to do list, but I am imagining something like an in-house build process which both builds the theme WAR artifact, as well as some CSS files for loading directly into local development projects. Does that make sense/seem reasonable?
3 & 4) Perfect, thank you - that helps. I will keep those items in mind as development continues, and revisit as needed if anything else comes up!
4) I tried using the browser console method that you mentioned, and was unsuccessful. I get "Uncaught TypeError: Liferay.Loader.get is not a function at <anonymous>:1:16". Do I need to turn anything else on settings-wise, and/or enter other commands in first?
For what it's worth, I was trying to use this method to get more information about a portlet that doesn't seem to want to render in 7.1 - although it bundles without error, is deployed without error, and even shows up in the console looking like a successful load - e.g., "Resolved modules: (...list of modules...)" when I turned on the Explain Resolutions flag - but nothing is rendered on the page, beyond the placeholder/title of the portlet. Interestingly enough, this is a portlet which also happens to render as expected in 7.2 - so not a critical issue for me to resolve now, more so treating it as a learning opportunity to further enhance my debugging skills...
For what it's worth, I was trying to use this method to get more information about a portlet that doesn't seem to want to render in 7.1 - although it bundles without error, is deployed without error, and even shows up in the console looking like a successful load - e.g., "Resolved modules: (...list of modules...)" when I turned on the Explain Resolutions flag - but nothing is rendered on the page, beyond the placeholder/title of the portlet. Interestingly enough, this is a portlet which also happens to render as expected in 7.2 - so not a critical issue for me to resolve now, more so treating it as a learning opportunity to further enhance my debugging skills...
Oops. That's because it is not Liferay.Loader.get but Liferay.Loader.require :-S.
Sorry.
Sorry.
Copyright © 2025 Liferay, Inc
• Privacy Policy
Powered by Liferay™