Integrating a Modern Frontend Setup with AEM Natalia Venditto, Netcentric a Modern Frontend Setup
Total Page:16
File Type:pdf, Size:1020Kb
APACHE SLING & FRIENDS TECH MEETUP 10-12 SEPTEMBER 2018 Integrating a Modern Frontend Setup with AEM Natalia Venditto, Netcentric A modern frontend setup 2 How do we understand a modern setup? ▪ A modern setup ▪ ...does not necessarily include the latest tool in the market ▪ …it's standard enough that it can be easily maintained ▪ …does not force everyone in the team to a high knowledge ramp up investment ▪ …it implements industry (current) best practices ▪ ...requires a strategy 3 Defining a frontend strategy! photocredit: @rawpixel / unsplash.com 4 The `What?` and `How?` questions WHAT? HOW do we achieve? questions for your client questions for your team ieve / unsplash.com … browser support, performance reqs, http protocol (ie: http/2), accessibility, analytics, testing strategy, more productivity? photocredit: @kevingr 5 The `Which?` questions Which Build Which AEM Which JS Which CSS Tools/ features? Setup ECMAScript Spec Which Bundlers What version of Frameworks Preprocessor? Task Runners AEM? What new State Manag. (SASS, LESS, Linters/Coverage features? 3rd party/APIS PostCSS) Loaders/Plugins Clientlibs strategy 6 The win/win results matrix increased performance (author + end user experience/ROI, etc) enhanced productivity/flexibility guaranteed innovation/creativity (code quality, (browser feature support, testability, maintenance, accessibility) scalability) 7 Study case: directory structure 8 Directory structure . ~ |-- [PROJECT-ID]-3rd-party/ |-- [PROJECT-ID]-complete-package/ |-- [PROJECT-ID]-components/[PROJECT-ID]-components-package/ |-- src/main/jcr_root/apps/[PROJECT-ID]/ |-- commons/ |-- components/ |-- component1/ |-- component2/ |-- // as many components |-- pages/ |-- [PROJECT-ID]-configuration/ |-- [PROJECT-ID]-demo-content/ .pom.xml 9 Directory structure <?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" |-- components/component1/ jcr:primaryType="cq:ClientLibraryFolder" |-- clientlibs/ categories="[PROJECT-ID.publish.component1 |-- author/ ]" jsProcessor=”[min:gcc;obfuscate=true]” cssProcessor=”[min:gcc]” |-- publish/ /> |-- .content.xml |-- component1.publish.entry.js |-- component1.publish.entry.scss |-- css.txt |-- js.txt |-- .content.xml |-- component1.html 10 Study case: tools and configuration 11 Tools and configuration 12 Tools and configuration File Loaders Plugins Output System ▪ configure webpack to ▪ configure webpack to read ▪ configure webpack to traverse our component files according to output files in designated folders, collect loaders, and perform targets, so that we are able [name-of-component].entry.js additional operations to minify them, [name-of-component].entry.scss (transpilation, tree-shaking aggregate them and files and DCE, etc) compress them (in AEM (webpack allows us to configure with gcc) entry points per path or other params) 13 Setup Tools nvm install --lts cd [PROJECT-ID]-components/[PROJECT-ID]-components-package mkdir frontend cd frontend npm init –y // generates package.json npm install webpack -–save-dev // maintain as dev dependency //successive installations npm install modulename --save || --save-dev 14 Setup Tools test: /\.css$/, Transpiling Transpiling of CSS Browser of ES pre Linting Support (to JS ES5) processed code 15 Setup configuration . ~ |-- [PROJECT-ID]-components/[PROJECT-ID]-components-package/ |-- frontend/ last 2 version |-- .browserslistrc |-- .eslintignore > 1% |-- .eslintcache maintained node versions not dead |-- .eslintrc |-- .stylelintcache |-- .stylintrc |-- .gitignore |-- .npmrc |-- package.json .pom.xml 16 Setup Tools test: /\.css$/, Transpiling Minification Transpiling of CSS Browser Aggregation of ES pre Linting Support of JS and (to JS ES5) processed CSS code 17 Directory structure <?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" |-- components/component1/ jcr:primaryType="cq:ClientLibraryFolder" |-- clientlibs/ categories="[PROJECT-ID.publish.component1 |-- author/ ]" jsProcessor=”[min:gcc;obfuscate=true]” cssProcessor=”min:gcc]” |-- publish/ /> |-- .content.xml |-- component1.publish.entry.js |-- component1.publish.entry.scss |-- css.txt |-- js.txt |-- .content.xml |-- component1.html 18 Setup configuration . ~ |-- [PROJECT-ID]-3rd-party/ |-- [PROJECT-ID]-complete-package/ |-- [PROJECT-ID]-components/[PROJECT-ID]-components-package/ |-- frontend/ |-- build/config/ |-- webpack.config.dev.js |-- webpack.config.prod.js |-- whatever other configs (ie: unit testing, e2e...) |-- package.json |-- [PROJECT-ID]-configuration/ |-- [PROJECT-ID]-demo-content/ .pom.xml 19 Setup configuration ▪ for our frontend code build, we will favor webpack 4 optimized "mode" configuration, over OSGI environment definition, in order to leverage Webpacks caching and performance 20 Setup configuration 21 Setup configuration may need to update this (default) config for SplitChunkPlugin 22 Setup configuration ▪ edit the corresponding POM.xml, to make use of the frontend plugin for maven* -> https://mvnrepository.com/artifact/com.github.eirslett/frontend-mave n-plugin?repo=redhat-ga 23 Maven frontend plugin 24 Syncing with AEM webpack --watch 25 Setup configuration |-- components/component1/ |-- clientlibs/ |-- author/ |-- .content.xml |-- component1.author.entry.js |-- component1.author.scss |-- css.txt |-- js.txt |-- component1_dialog.js |-- publish/ |-- _cq_dialog/ |-- .content.xml |-- component1.html 26 Setup configuration . ~ |-- [PROJECT-ID]-components/[PROJECT-ID]-components-package/ |-- frontend/ |-- .browserslistrc |-- .eslintignore *.bundle.js |-- .eslintcache node_modules |-- .eslintrc *_dialog.js |-- .stylelintcache build/shared/variabl |-- .stylintrc es/*.js |-- .gitignore node/* |-- .npmrc |-- package.json build/config .pom.xml gulpfile.js 27 Study case: shipping the code (to the browser) 28 Loading styles via Content Policies 29 Loading techniques 30 Loading: Templating (Sightly, Handlebars...) |-- components/component1/ |-- clientlibs/ |-- author/ |-- publish/ <!--/* component1.author */--> <sly data-sly-test="${wcmmode.edit}" |-- additional-styles/ data-sly-use.clientLib="${'/libs/granite/sightly/tem plates/clientlib.html'}" |-- .content.xml data-sly-call="${clientLib.all @ categories='[PROJECT-ID].component1.author'}" /> |-- component1.add-styles.entry.js |-- component1.add-styles.scss<!--/* component1.publish */--> <sly |-- css.txt data-sly-use.clientLib="${'/libs/granite/sightly/tem |-- js.txt plates/clientlib.html'}" data-sly-call="${clientLib.all @ categories='[PROJECT-ID].component1.publish'}" /> |-- .content.xml |-- component1.html 31 Script loading attributes <script src="myproject.component1.js" defer></script> <script src="myproject.component1.js" async></script> <script src="myproject.component1.js" preload></script> <script ... 32 Lazy Loading 33 Inline load + Lazy Loading strategy hero area/above the fold lazy loaded chunks (and resources, such as images) 34 Intersection Observers API // test for browser support if (!'IntersectionObserver' in window && !'IntersectionObserverEntry' in window && !'intersectionRatio' in window.IntersectionObserverEntry.prototype) { // load polyfill now } 35 LazyLoading and SEO ▪ SSR (server side rendering techniques) ▪ Content Fragments ▪ Experience Fragments 36 Demo Time (added backup) 37 Loading styles via Content Policies 38 Loading styles via Content Policies 39 Loading styles via Content Policies clientlibs="some.c ategory" 40 Thank you! 41.