Closed marc0olo closed 7 years ago
This has actually nothing to do with this loader. How are you building and developing your portlet (-web) bundle?
You are definitely right! ... I made to many and different attempts to get this working. After cleaning up my project I got it finally working - almost! :(
The only thing that is still failing, is when I try to render a "normal" output in react. This is the console-output of the browser:
Uncaught (in promise) Error: (SystemJS) SyntaxError: Unexpected token <
at eval (<anonymous>)
at Object.eval (http://localhost:8080/o/pkg/react-module/1.0.0/~/index.js:7:17)
at eval (http://localhost:8080/o/pkg/react-module/1.0.0/~/index.js:25:4)
at eval (http://localhost:8080/o/pkg/react-module/1.0.0/~/index.js:26:3)
Evaluating http://localhost:8080/o/pkg/react-module/1.0.0/~/component.js
Evaluating http://localhost:8080/o/pkg/react-module/1.0.0/~/index.js
Error loading http://localhost:8080/o/pkg/react-module/1.0.0/~/index.js
If there is function in the js-file declared which returns the character "<", then I get the error above:
// component.js
var React = require('react');
var ReactDOM = require('react-dom');
class Component extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
};
module.exports = Component;
// index.js
var React = require('react');
var ReactDOM = require('react-dom');
var Component = require('./component');
function render(config, wrapper) {
return ReactDOM.render(
React.createElement(Component, config),
document.getElementById(wrapper));
}
module.exports = {render: render};
// view.jsp
<%@ include file="/init.jsp" %>
<div id="<portlet:namespace />wrapper"> </div>
<script>
window.process = { env: {} };
System
.import('react-module/1.0.0')
.then(function (MyModule) {
MyModule.render({name: 'react-portlet'},'<portlet:namespace />wrapper');
});
</script>
When I create an element with React which only includes a String with 'Hello, World' and without a special character the output in the portlet works es expected:
// index.js
var React = require('react');
var ReactDOM = require('react-dom');
function render(wrapper) {
return ReactDOM.render(
React.createElement('div', null, 'Hello, World!'),
document.getElementById(wrapper)
);
}
module.exports = {render: render};
// view.jsp
<%@ include file="/init.jsp" %>
<div id="<portlet:namespace />wrapper"> </div>
<script>
window.process = { env: {} };
System
.import('react-module/1.0.0')
.then(function (MyModule) {
MyModule.render('<portlet:namespace />wrapper');
});
</script>
Can you help me to get this thing working? Maybe I'm just doing something wrong ...
You are doing great! The only problem is with JSX syntax which is not supported by browsers. You'll need to use the React.createElement
currently, mostly because I had no time to build an alternative transpilation process that doesn't builds AMD modules (which is what Liferay does).
You also need to know that using JSX (that xml-like stuff) is completely optional for React development, even if it's very useful.
In the final form of this experiment this will not be an issue at all.
Well ok, my problem is a bit that I'm new to this javascript-stuff (npm., systemjs, loader x,y,z, ...)
Where am I using JSX in my above failure-example? I adapted this example 1:1 as described in #1 and it crashes. As you can see above I also use React.createElement
in the failure-example.
So when this is actually the expected behaviour as you said, is it in general possible to create React-Components right now? I don't see any chance to do this when my failure-example doesn't work.
Well ok, my problem is a bit that I'm new to this javascript-stuff (npm., systemjs, loader x,y,z, ...)
This is great, and the perfect audience for this project.
Where am I using JSX in my above failure-example? I adapted this example 1:1 as described in #1 and it crashes. As you can see above I also use React.createElement in the failure-example.
When you develop with React you’ll need to manually define the HTML of you components inside your JS code. To do so React exposes a React.createElement
function that you can use to do so.
Since you’ll have hundreds of those in your code they provided from the start an easier (and more readable) way to do so, namely JSX where “X” stands for “eXtended” and “XML”.
When you write <div>Hi</div>
it is rewritten by a compile-time script in React.createElement('div', null, 'Hi')
. You don’t have that compile-time process in place, therefore your JSX is outputted in the final code and served to the browser. JSX is not supported by the browser.
In your example the file component.js had one occurrence of JSX. That was the only problem in your code.
So when this is actually the expected behaviour as you said, is it in general possible to create React-Components right now? I don't see any chance to do this when my failure-example doesn't work.
As I said before everything works, except from not having compile time processes in place. We still have to flesh it out correctly.
Really great project, keep up this work! ;-)
Thank you!!!
Is or will it be also possible to create angular apps using the frontend-packages-bundle-config-extender? (I didn't try yet but I think you can answer this pretty quick :)
The only problem is that you wont be able to use TypeScript because that requires a compile-time process as well. For the rest it should work perfectly. If it doesn’t it’s a bug and please file it as such here!
you can mark this issue as 'question' since it isn't an issue
Good idea. Done.
thanks for the fast response to my questions!
Glad to be helpful!
@marc0o- how are your experiments going? any update to share? :)
Yes, it is indeed working fine if I use plain javascript. Thanks for the explanation! Sadly I didn't have much time to invest in this topic up to now.
But I have a few other questions about this topic:
Liferay Javascript API
in this concrete scenario? it would be a pity if not :-( https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/liferay-javascript-apisfrontend-packages-bundle-config-extender
compared to the possibilities Liferay provides?
liferay-amd-loader
I have to define my modules and its dependencies by "hand", right?frontend-packages-bundle-config-extender
I can use package.json to install the necessary dependencies needed by my module, correct?liferay-amd-loader
?liferay-amd-loader
?I'm curious about your answers! :-)
is it possible to use the
Liferay Javascript API
in this concrete scenario? it would be a pity if not :-( https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/liferay-javascript-apis
Most “vanilla” APIs work out of the box, they are simply available on the global scope.
In short, yes you can access themeDisplay
.
Sometimes APIs need to be “loaded” on the page. If you need Liferay.PortletURL
for example you’ll need to call AUI().use('liferay-portlet-url', …)
.
For modules that are in the AUI format I’ll attach here an example code that provides them as Promises. For Liferay AMD Loader modules there a little more to be done—but this project doesn’t expect to be working side-by-side with the AMD Loader.
function loadAUI() {
var args = Array.prototype.slice.call(arguments);
return new Promise(function (resolve, reject) {
AUI().use(args, function (A, status) {
if (status && status.success) {
resolve(A);
}
else {
reject(status);
}
});
});
}
what is the intention of the
frontend-packages-bundle-config-extender
compared to the possibilities Liferay provides?
This project is a Proof of Concept of a new Loader implemented in Liferay. Potentially this would replace the original implementation.
In Liferay there are few missing features that we believe are critical for front-end developers:
By using SystemJS (or a loader with similar features) and by integrating it with the whole front-end architecture (SCSS file resolution, FTL import resolution…) we get a very solid infrastructure which
supports npm packages and transient dependencies (!!) right away
deduplicates aggressively based on package.json dependency ranges
doesn‘t break intra-bundle execution by providing the same cached execution of modules when possible
let every bundle to use their own version of packages without interfering one each other (Marketplace oriented)
when do you think you will be able to provide an alternative transpilation process that will make it possible to write compile-time scripts?
Well you could already do it as they do it at step 4 here. The issue is to have a super simple way to do it (a Gradle plugin for example).
is it possible to use compile-time scripts with
liferay-amd-loader
?
Could you elaborate a little bit more?
what do you think about this approach to use Angular in Liferay? https://gist.github.com/mjbradford89/e0d2175e1742173530966827184f5a21
This is very interesting and exactly in the direction of this project.
When they say…
Multiple instances/portlets using angular will break. I think this can be resolve by importing angular outside of the portlet, and bootstrapping Angular applications as they become available […]
they are referring to the fact that in the JSP they have to place a <script …>
.
This project solves also that.
Thanks again for the detailed answer! And forget about my questions about the "compile-time"-stuff since I am still a beginner in the js-world :-D
The process described above still requires "manual" work. As you already mentioned there should be a "super simple" way to get this work done fully automatic :-)
frontend-packages-bundle-config-extender
will be published Thank you so much for your time. Can we consider you in if we need some testers later in the development of this?
Sure, assuming I have the time to test it!
Again 3 questions:
Well the README-Guide seems not really be up to date.
When I followed the steps descripted in issue #1 I was really happy to see ANY output in Liferay and for just one moment my example seemed to work.
Sadly the portlet didn't show the output I wanted to see. The browser console doesn't output any errors, but when I look in the system.out of Liferay I see the following lines:
Do you have any ideas what is happening here?