All Things JavaScriptSu Liferay DXP 7.x e Liferay Portal CE 7.x
Carlo CervellinFront-End Engineer
Pier Paolo RamonHead of Digital
Liferay DXP è una pia;aforma
per realizzare Composite Applica.ons
Liferay DXP è una pia;aforma
per realizzare Composite Applica.ons
Liferay DXP è una pia;aforma
per realizzare Composite Applica.ons
!!
La cara1eris3ca principale delle Composite Applica3ons
è non avere un Single Point of Build
Sfide da tenerein considerazione
Minificazionee peso della pagina
Concatenazione e Bundling
Caricamentoe Lazy Loading
Ordine di esecuzionee dipendenze
Coordinazionetra componen9
Scriptse Moduli
Concatenazione Combo Loader
Caching Sta9c Resource URLs + CDN Configura9on
Minificazione Minificatore automa9co(Google Closure Compiler)
Turbolinks SPA Framework(Senna.js)
Bundling Liferay AMD Loader+ Combo Loader
Registrazione come dipendenza di Portlet
Registrazione come dipendenza di Portlet
@Component( service = Portlet.class, properties = { "com.liferay.portlet.header-portlet-css=/css/main.css", "com.liferay.portlet.header-portlet-javascript=/js/main.js"
} ) public class AwesomePortlet extends MVCPortlet { … }
Registrazione come dipendenza di Portlet
<head> header-portlet-javascript
!</head>
<body> Contenuto della pagina footer-portlet-javascript
!</body>
Registrazione come dipendenza di Portlet
Vengono concatenate in Combo Load?
Quando viene caricata?
Quando viene eseguita?
Viene eseguita ogni navigazione?
Sì
Solo una volta e solo quando la portlet è in pagina
Subito prima / dopo del corpo
Sì — è uno “script”
Caricamento manuale via <script>
Caricamento manuale via <script>
<script src="/o/awesome-portlet-web/js/utility.js">!</script>
Nei frammen9 JSPdei Dynamic Include
Web Content Templates Applica9on Display Templates
Fragments
Nei frammen9 JSPdelle Portlet
FTL del tema
Caricamento manuale via <script>
<script src="<%= request.getContextPath() + "/js/utility.js"
%>">!</script>
Questo ci perme\e di evitare di dover conoscere
il Web Context Path del bundle OSGi
Caricamento manuale via <script>
<script src="<%= PortalUtil.getPathContext(request) + "/js/utility.js"
%>">!</script>
ATTENZIONE! L’ordine di «Path» e «Context»è al contrario rispe\o a prima!
Questo ci perme\e di supportare casi in cui il portale non è nella
root del server. Il 9pico /portal
Caricamento manuale via <script>
<script src="<%= PortalUtil.getStaticResourceURL(
request, PortalUtil.getPathContext(request) + "/js/utility.js", ""...
) %>">!</script>
Aggiunge i parametri in query string necessari ad abvare il minificatore
automa9co
Ci sono alcuneconfigurazioni
possibili. Per scoprirle…
…leggete il sorgentedi PortalImpl :)
Caricamento manuale via <script>
<script src="<%= PortalUtil.getStaticResourceURL(
request, themeDisplay.getCDNDynamicResourcesHost() + PortalUtil.getPathContext(request) + "/js/utility.js", !!...
) %>">!</script> Se configurata una CDN
dinamica (capace di fare cache on-demand delle
risorse) questo ci perme\e di sfru\arla.
<head> header-portlet-javascript
!</head>
<body> Contenuto della pagina
Script manuali footer-portlet-javascript
!</body>
Caricamento manuale via <script>
Vengono concatenate in Combo Load?
Quando viene caricata?
Quando viene eseguita?
Viene eseguita ogni navigazione?
No
N volte, nel corpo della pagina
N volte, ad ogni presenza nella pagina
Sì — è uno “script”
Caricamento manuale via <script>
Caricamento manuale via <script> e a1ributo data-senna-track
<script data-senna-track="permanent" src="<%= PortalUtil.getStaticResourceURL(
request, themeDisplay.getCDNDynamicResourcesHost() + PortalUtil.getPathContext(request) + "/js/utility.js", !!...
) %>">!</script>
Caricamento manuale via <script> e a1ributo data-senna-track
Vengono concatenate in Combo Load?
Quando viene caricata?
Quando viene eseguita?
Viene eseguita ogni navigazione?
No
N volte, nel corpo della pagina
N volte, ad ogni presenza nella pagina
No! Viene tra;ato come modulo!
Caricamento manuale via <script> e a1ributo data-senna-track
Caricamento manuale via <script> e <liferay-util:html-top/bottom>
Caricamento manuale via <script> e <liferay-util:html-top/bottom>
<liferay-util:html-top> <script src="!!.../js/utility.js">!</script>
"</liferay-util:html-top>
<liferay-util:html-bottom> <script src="!!.../js/utility.js">!</script>
"</liferay-util:html-bottom>
Questo porta nella <head>
Questo porta a fondo <body>
<head> header-portlet-javascriptliferay-util:html-top
!</head>
<body> Contenuto della pagina
Script manuali footer-portlet-javascriptliferay-util:html-bottom
!</body>
Caricamento manuale via <script> e <liferay-util:html-top/bottom>
Vengono concatenate in Combo Load?
Quando viene caricata?
Quando viene eseguita?
Viene eseguita ogni navigazione?
No
N volte, inizio o fine pagina
N volte, inizio o fine pagina
Sì — è uno “script”
Caricamento manuale via <script> e <liferay-util:html-top/bottom>
Caricamento manuale via <script> e <liferay-util:html-top/bottom>
e a1ributo outputKey="..."
Caricamento manuale via <script> e <liferay-util:html-top/bottom>
e a1ributo outputKey="..."
<liferay-util:html-top> <script src="!!.../js/utility.js">!</script>
!</liferay-util:html-top>
Caricamento manuale via <script> e <liferay-util:html-top/bottom>
e a1ributo outputKey="..."
<liferay-util:html-top outputKey="awesome-key"> <script src="!!.../js/utility.js">!</script>
!</liferay-util:html-top>
Assicura che il frammento incluso nel tag <liferay-u2l:html-top>venga riportato nella pagina finale una sola volta
Vengono concatenate in Combo Load?
Quando viene caricata?
Quando viene eseguita?
Viene eseguita ogni navigazione?
No
1 volta, inizio o fine pagina
1 volta, inizio o fine pagina
Sì — è uno “script”
Caricamento manuale via <script> e <liferay-util:html-top/bottom>
e a1ributo outputKey="..."
Caricamento via Theme Contributor
Caricamento via Theme Contributor
bnd.bnd Liferay-Theme-Contributor-Type: some-unique-name
Nessuna relazione con i temi! Da non confondere con i Template Context Contributor!
TuG i file staIci (.js e .css) del modulovengono carica9 in tu;e le pagine.
<head> header-portlet-javascriptliferay-util:html-top Theme Contributor resources
!</head>
<body> Contenuto della pagina
Script manuali footer-portlet-javascriptliferay-util:html-bottom
!</body>
Caricamento via Theme Contributor
Vengono concatenate in Combo Load?
Quando viene caricata?
Quando viene eseguita?
Viene eseguita ogni navigazione?
Sì
1 volta, ad inizio pagina
1 volta, alla prima navigazione
No! Vengono tra;aI come moduli!
Caricamento via Theme Contributor
Caricamento via Liferay AMD Loader
Caricamento via Liferay AMD Loader
Liferay.Loader.require( 'some-module', function (someModule) { !// :) } );
Liferay.Loader.define( 'some-module', function () { return { … } } );
1 2
Asynchronous Module Defini9on
Prima deve essere eseguito questo… …poi questo. Non molto asincrono :(
Caricamento via Liferay AMD Loader
Liferay.Loader.require( 'some-module', function (someModule) { !// :) } );
Liferay.Loader.define( 'some-module', function () { return { … } } );
1 2
Asynchronous Module Defini9on
Prima deve essere eseguito questo… …poi questo. Non molto asincrono :(
Caricamento via Liferay AMD Loader
Liferay.Loader.require( 'some-module', function (someModule) { !// :) } );
Liferay.Loader.define( 'some-module', function () { return { … } } );
Liferay.Loader.addModule({ name: 'some-module', path: '/o/blahblah/some-module.js' });
1
2
Caricamento via Liferay AMD Loader
Liferay.Loader.require( 'some-module', function (someModule) { !// :) } );
Liferay.Loader.define( 'some-module', function () { return { … } } );
Liferay.Loader.addModule({ name: 'some-module', path: '/o/blahblah/some-module.js' });
1
2
Caricamento via Liferay AMD Loader
Liferay.Loader.require( 'some-module', function (someModule) { !// :) } );
Liferay.Loader.define( 'some-module', function () { return { … } } );
Liferay.Loader.addModule({ name: 'some-module', path: '/o/blahblah/some-module.js' });
LAZY LOADED
1
2
ASYNC!
bnd.bnd (Liferay Modules) Liferay-JS-Config: /js/config.js
liferay-plugin-package.properties (Themes) Liferay-JS-Config=/js/config.js
/src/main/resources/META-INF/resources/js/config.js Liferay.Loader.addModule({ …… }); Liferay.Loader.addModule({ …… });
Caricamento via Liferay AMD Loader
<head> Liferay-JS-Config
header-portlet-javascriptliferay-util:html-top Theme Contributor resources
!</head>
<body> Contenuto della pagina
Script manuali footer-portlet-javascriptliferay-util:html-bottom
!</body>
Caricamento via Liferay AMD Loader
Caricamento via Liferay AMD Loader
Liferay.Loader.addModule({ name: 'named-module', path: '/o/!!.../named-module.js', anonymous: false, });
Liferay.Loader.define( 'named-module', function () { return { … } } );
Liferay.Loader.addModule({ name: 'named-module', path: '/o/!!.../anon-module.js', anonymous: true, });
Liferay.Loader.define( "// nessun nome :( function () { return { … } } );
Named Module Defini2on Anonymous Module Defini2on
Combo Loading?Nessun problema!
Combo Loading?Assolutamente NO!
Vengono concatenate in Combo Load?
Quando viene caricata?
Quando viene eseguita?
Viene eseguita ogni navigazione?
Sì, ma non per gli anonymous
1 volta, al primo require()
1 volta, al primo require()
No!!!! Sono moduli!!!
Caricamento via Liferay AMD Loader
Caricamento via Liferay npm Bundler
Caricamento via Liferay npm Bundler
Liferay.Loader.require('react', function (React) { !!... });
my-awesome-web/!!.../main.es.js import React from 'react';
Caricamento via Liferay npm Bundler
Liferay.Loader.require('[email protected]', function (React) { !!... });
my-awesome-web/!!.../main.es.js import React from 'react';
Caricamento via Liferay npm Bundler
Liferay.Loader.require('[email protected]', function (React) { !!... });
my-awesome-web/!!.../main.es.js import React from 'react';
my-awesome-web/package.json "dependencies": { "react": "^16.0.0" }
Caricamento via Liferay npm Bundler
Liferay.Loader.require('[email protected]', function (React) { !!... });
node_modules/react-redux/main.js import React from 'react';
my-awesome-web/!!.../main.es.js import { connect } from 'react-redux';
bundle.js
App sviluppata
con un framework
front-end moderno
Compilazione
tradizionale
file per file (Babel)
Liferay
npm Bundler
Liferay
AMD Loader
+
Combo Loader
Compilazione
unificata
(CRA, Vue CLI, Angular CLI)
????
(Lasciamo alle;ore il piacere
di deciderlo)
ES2018+ ES5 + AMD Liferay AMD+ Config
ES2018+ ES5 Caricamento…
bundle.js
Compilazione
tradizionale
file per file (Babel)
Liferay
npm Bundler
Liferay
AMD Loader
+
Combo Loader
Compilazione
unificata
(CRA, Vue CLI, Angular CLI)
✅ Componibile ✅ Dipendenze de-duplicate " Molte richieste dal client " Nessuna dead-code elimina8on
✅ Molto o9mizzato ✅ Integrabile a tu<o il tooling " Output opaco " Complessità di integrazione
????
(Lasciamo alle;ore il piacere
di deciderlo)
my-awesome-react-app/build ├── asset-manifest.json ├── index.html └── static/js ├── 1.4e00e461.chunk.js ├── main.3ff68361.chunk.js └── runtime~main.696ab712.js
my-awesome-react-app/build ├── asset-manifest.json ├── index.html └── static/js ├── 1.4e00e461.chunk.js ├── main.3ff68361.chunk.js └── runtime~main.696ab712.js
my-awesome-react-app/build/asset-manifest.json { "main.js": "/static/js/main.3ff68361.chunk.js", }
Carlo CervellinFront-End Engineer
GitHub @crcarlo
Pier Paolo RamonHead of Digital
GitHub @yuchi
TwiBer @_pier
+39 340 1755621
Domande?
Grazie!
#LRBC19
Top Related