Pernahkah Anda berpikir tentang menggunakan set teknologi paling sederhana yang ada saat mengembangkan proyek web Anda berikutnya? Jika demikian, maka materi, terjemahan yang kami terbitkan hari ini, ditulis khusus untuk Anda.
Kerangka kerja JavaScript ada untuk membantu kami membangun aplikasi dengan kemampuan serupa menggunakan pendekatan generik. Namun, banyak aplikasi tidak membutuhkan semua kekuatan yang disediakan kerangka kerja. Menggunakan kerangka kerja dalam proyek kecil atau menengah, yang memiliki persyaratan spesifik tertentu, mungkin merupakan pemborosan waktu dan energi yang tidak perlu.

Pada artikel ini, kita akan berbicara tentang penggunaan teknologi modern dalam pengembangan aplikasi web yang kapabilitasnya tidak dibatasi oleh kapabilitas kerangka kerja. Omong-omong, jika Anda membutuhkannya, maka Anda, menggunakan teknologi yang dijelaskan di sini, dapat membuat kerangka kerja Anda yang sangat terspesialisasi. JavaScript murni dan teknologi web dasar lainnya memberi pengembang kemampuan untuk melakukan apa yang mereka butuhkan tanpa membatasi diri pada ruang lingkup alat yang mereka gunakan.
Ulasan
Sebelum kita memulai bisnis, mari kita bahas alat yang kita butuhkan.
β Arsitektur Aplikasi
Untuk memastikan kecepatan pemuatan aplikasi dan kegunaan yang tinggi, kami akan menggunakan pola desain berikut:
- Arsitektur Aplikasi Shell.
- Pola PRPL (Push, Render, Pre-cache, memuat Malas).
β Sistem pembangunan proyek
Dalam proyek kami, kami membutuhkan sistem perakitan berkualitas tinggi yang disesuaikan dengan kebutuhan kami. Di sini kita akan menggunakan Webpack, menyajikan persyaratan berikut untuk sistem membangun proyek:
- Dukungan untuk ES6 dan kemampuan impor sumber daya dinamis.
- Dukungan untuk SASS dan CSS.
- Konfigurasi mode pengembangan yang terpisah dan karya nyata aplikasi.
- Kemampuan untuk mengkonfigurasi pekerja layanan secara otomatis.
β Fitur JavaScript Canggih
Kami akan menggunakan set minimum fitur JavaScript modern yang memungkinkan kami untuk mengembangkan apa yang kami butuhkan. Berikut adalah fitur yang dimaksud:
- Modul
- Berbagai cara untuk membuat objek (objek literal, kelas).
- Impor sumber daya yang dinamis.
- Fungsi panah.
- Templat literal.
Sekarang kami memiliki gagasan umum tentang apa yang kami butuhkan, kami siap untuk mulai mengembangkan proyek kami.
Arsitektur aplikasi
Munculnya Aplikasi Web Progresif (PWA) telah berkontribusi pada kedatangan solusi arsitektur baru dalam pengembangan web. Ini memungkinkan aplikasi web memuat dan menampilkan lebih cepat. Kombinasi arsitektur App Shell dan pola PRPL dapat menyebabkan aplikasi web menjadi cepat dan responsif, mirip dengan aplikasi biasa.
β Apa itu App Shell dan PRPL?
App Shell adalah pola arsitektur yang digunakan untuk mengembangkan PWA, bila digunakan, jumlah minimum sumber daya kritis untuk operasi situs dikirim ke browser pengguna saat situs dimuat. Komposisi bahan-bahan ini biasanya mencakup semua sumber daya yang diperlukan untuk tampilan pertama aplikasi. Sumber daya semacam itu juga dapat di-cache menggunakan pekerja layanan.
Singkatan PRPL diuraikan sebagai berikut:
- Push - mengirim sumber daya penting ke klien untuk rute sumber (khususnya, menggunakan HTTP / 2).
- Render - menampilkan rute asli.
- Pra-cache - cache dari rute atau sumber daya yang tersisa sebelumnya.
- Lazy load - "lazy" memuat bagian-bagian aplikasi yang diperlukan (khususnya, atas permintaan pengguna).
β Implementasi App Shell dan PRPL dalam kode
Pola App Shepp dan PRPL dibagikan. Ini memungkinkan Anda untuk menerapkan pendekatan lanjutan dalam pengembangan proyek web. Begini pola aplikasi Shell dalam kode:
<!DOCTYPE html> <html lang="en"> <head>    <meta charset="utf-8" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <meta http-equiv="X-UA-Compatible" content="ie=edge" />            <style>        html {            box-sizing: border-box;        }        *,        *:after,        *:before {            box-sizing: inherit;        }        body {            margin: 0;            padding: 0;            font: 18px 'Oxygen', Helvetica;            background: #ececec;        }        header {            height: 60px;            background: #512DA8;            color: #fff;            display: flex;            align-items: center;            padding: 0 40px;            box-shadow: 1px 2px 6px 0px #777;        }        h1 {            margin: 0;        }        .banner {            text-decoration: none;            color: #fff;            cursor: pointer;        }        main {            display: flex;            justify-content: center;            height: calc(100vh - 140px);            padding: 20px 40px;            overflow-y: auto;        }        button {            background: #512DA8;            border: 2px solid #512DA8;            cursor: pointer;            box-shadow: 1px 1px 3px 0px #777;            color: #fff;            padding: 10px 15px;            border-radius: 20px;        }        .button {            display: flex;            justify-content: center;        }        button:hover {            box-shadow: none;        }        footer {            height: 40px;            background: #2d3850;            color: #fff;            display: flex;            align-items: center;            padding: 40px;        }    </style>        <title>Vanilla Todos PWA</title> </head> <body>    <body>                        <header>            <h3><font color="#3AC1EF">β<a class="banner"> Vanilla Todos PWA </a></font></h3>        </header>        <main id="app"></main>        <footer>            <span>Β© 2019 Anurag Majumdar - Vanilla Todos SPA</span>        </footer>                                     <script async src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script>                <noscript>            This site uses JavaScript. Please enable JavaScript in your browser.        </noscript>    </body> </body> </html> 
Setelah mempelajari kode ini, Anda dapat memahami bahwa template App Shell menyediakan untuk pembuatan "shell" aplikasi, yang merupakan "kerangka" yang berisi minimal markup. Mari kita analisis kode ini (selanjutnya, fragmen kode yang akan kita rujuk selama analisis ditandai dengan komentar, seperti 
<!-- β1 --> ).
- Fragmen No. 1. Gaya paling penting dibangun ke dalam markup, dan tidak disajikan sebagai file terpisah. Ini dilakukan agar kode CSS akan diproses langsung saat memuat halaman HTML.
- Fragmen No. 2. Ini adalah "shell" dari aplikasi tersebut. Area-area ini nantinya akan dikendalikan oleh kode JavaScript. Ini terutama berlaku untuk apa yang akan ada di tag maindenganapppengenal (<main id="app"></main>).
- Fragmen No. 3. Di sini skrip ikut bermain. Atribut asyncmemungkinkan Anda untuk tidak memblokir parser selama pemuatan skrip.
"Kerangka" aplikasi di atas mengimplementasikan langkah-langkah Push dan Render dari pola PRPL. Ini terjadi ketika browser mem-parsing kode HTML untuk membentuk representasi visual dari halaman. Pada saat yang sama, browser dengan cepat menemukan sumber daya yang penting untuk output halaman. Selain itu, skrip disajikan di sini (fragmen No. 3), yang bertanggung jawab untuk menampilkan rute asli dengan memanipulasi DOM (pada langkah Render).
Namun, jika kami tidak menggunakan pekerja layanan untuk menembolok "shell" dari aplikasi, maka kami tidak akan mendapatkan peningkatan kinerja, misalnya, saat memuat ulang halaman.
Kode di bawah ini menunjukkan pekerja layanan caching kerangka dan semua sumber daya statis aplikasi.
 var staticAssetsCacheName = 'todo-assets-v3'; var dynamicCacheName = 'todo-dynamic-v3';  
Mari kita menganalisis kode ini.
- Fragmen No. 1. Menangani acara installpekerja layanan membantu cache sumber daya statis. Di sini Anda dapat menyimpan sumber daya "kerangka" aplikasi (CSS, JavaScript, gambar, dan sebagainya) untuk rute pertama (sesuai dengan konten "kerangka"). Selain itu, Anda dapat mengunduh sumber daya aplikasi lain, membuatnya dapat berfungsi tanpa koneksi Internet. Caching sumber daya, selain caching kerangka, sesuai dengan langkah Pra-cache dari pola PRPL.
- Fragmen No. 2. Memproses acara activatecache yang tidak digunakan.
- Fragmen No. 3. Baris sumber kode ini memuat dari cache jika ada di sana. Jika tidak, permintaan jaringan dibuat. Selain itu, jika permintaan jaringan dibuat untuk menerima sumber daya, ini berarti bahwa sumber daya ini belum di-cache. Sumber daya semacam itu ditempatkan dalam cache terpisah yang baru. Script ini membantu cache data aplikasi dinamis.
Sampai saat ini, kami telah membahas sebagian besar solusi arsitektur yang akan digunakan dalam aplikasi kami. Satu-satunya hal yang belum kita bicarakan adalah langkah memuat Malas dari pola PRPL. Kami akan kembali lagi nanti, tetapi untuk saat ini kami akan berurusan dengan sistem perakitan proyek.
Sistem pembangunan proyek
Arsitektur yang baik saja, tanpa sistem pembangunan proyek yang layak, tidak cukup untuk membuat aplikasi yang berkualitas. Di sinilah Webpack sangat berguna. Ada alat lain untuk membangun proyek (bundler), misalnya - Parcel dan Rollup. Tetapi apa yang akan kami terapkan berdasarkan Webpack juga bisa dilakukan dengan menggunakan cara lain.
Di sini kita berbicara tentang bagaimana fitur yang kami minati terkait dengan plugin untuk Webpack. Ini akan memungkinkan Anda untuk dengan cepat memahami esensi sistem build kami. Pemilihan plug-in untuk bundler dan konfigurasi yang tepat adalah langkah paling penting menuju sistem pembangunan proyek berkualitas tinggi. Setelah menguasai prinsip-prinsip ini, Anda akan dapat menggunakannya di masa depan saat mengerjakan aplikasi Anda sendiri.
Tidak mudah untuk menyempurnakan alat seperti Webpack dari awal. Dalam kasus seperti itu, sangat membantu untuk mendapatkan bantuan yang baik. Panduan ini, dengan mana bagian yang sesuai dari bahan ini ditulis, adalah artikel 
ini . Jika Anda memiliki masalah dengan Webpack - hubungi dia. Sekarang mari kita ingat dan terapkan persyaratan untuk sistem perakitan proyek yang telah kita bicarakan sejak awal.
βMendukung ES6 dan kemampuan impor sumber daya dinamis
Untuk mengimplementasikan fitur-fitur ini, kami membutuhkan Babel, transporter populer yang memungkinkan Anda untuk mengubah kode yang ditulis menggunakan fitur ES6 menjadi kode yang dapat dijalankan di lingkungan ES5. Untuk membuat Babel bekerja dengan Webpack, kita dapat menggunakan paket-paket berikut:
- @babel/core
- @babel/plugin-syntax-dynamic-import
- @babel/preset-env
- babel-core
- babel-loader
- babel-preset-env
Berikut ini contoh file 
.babelrc untuk digunakan dengan Webpack:
 {   "presets": ["@babel/preset-env"],   "plugins": ["@babel/plugin-syntax-dynamic-import"] } 
Saat mengkonfigurasi Babel, baris 
presets dari file ini digunakan untuk mengkonfigurasi Babel untuk mengkompilasi ES6 ke ES5, dan baris 
plugins sehingga impor dinamis dapat digunakan di Webpack.
Ini adalah bagaimana Babel digunakan dengan Webpack (di sini adalah potongan dari file pengaturan Webpack - 
webpack.config.js ):
 module.exports = {   entry: {        
Bagian 
rules file ini menjelaskan cara menggunakan 
babel-loader untuk menyesuaikan proses transpilation. Sisa dari file ini dihilangkan demi singkatnya.
βSASS dan dukungan CSS
Untuk memberikan dukungan untuk sistem perakitan proyek SASS dan CSS kami, kami membutuhkan plugin berikut:
- sass-loader
- css-loader
- style-loader
- MiniCssExtractPlugin
Berikut tampilan file pengaturan Webpack di mana data tentang plugin ini dimasukkan:
 module.exports = {   entry: {        
Loader terdaftar di bagian 
rules . Karena kami menggunakan plugin untuk mengekstrak gaya CSS, entri yang sesuai dimasukkan di bagian 
plugins .
β Pengaturan terpisah mode pengembangan dan kerja nyata aplikasi
Ini adalah bagian yang sangat penting dari proses pembuatan aplikasi. Semua orang tahu bahwa ketika membuat aplikasi, beberapa pengaturan digunakan untuk membangun versi yang digunakan selama pengembangan, sementara yang lain digunakan untuk versi produksinya. Berikut adalah daftar paket yang berguna di sini:
- clean-webpack-plugin: untuk membersihkan isi folder- dist.
- compression-webpack-plugin: untuk mengompresi isi folder- dist.
- copy-webpack-plugin: untuk menyalin sumber daya statis, misalnya, file, dari folder dengan data sumber aplikasi ke folder- dist.
- html-webpack-plugin: untuk membuat file- index.htmldi folder- dist.
- webpack-md5-hash: untuk hashing file aplikasi dalam folder- dist.
- webpack-dev-server: untuk memulai server lokal yang digunakan selama pengembangan.
Beginilah 
webpack.config.js file 
webpack.config.js dihasilkan:
 const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const WebpackMd5Hash = require('webpack-md5-hash'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const CompressionPlugin = require('compression-webpack-plugin'); module.exports = (env, argv) => ({   entry: {       main: './src/main.js'   },   devtool: argv.mode === 'production' ? false : 'source-map',   output: {       path: path.resolve(__dirname, 'dist'),       chunkFilename:           argv.mode === 'production'               ? 'chunks/[name].[chunkhash].js'               : 'chunks/[name].js',       filename:           argv.mode === 'production' ? '[name].[chunkhash].js' : '[name].js'   },   module: {       rules: [           {               test: /\.js$/,               exclude: /node_modules/,               use: {                   loader: 'babel-loader'               }           },           {               test: /\.scss$/,               use: [                   'style-loader',                   MiniCssExtractPlugin.loader,                   'css-loader',                   'sass-loader'               ]           }       ]   },   plugins: [       new CleanWebpackPlugin('dist', {}),       new MiniCssExtractPlugin({           filename:               argv.mode === 'production'                   ? '[name].[contenthash].css'                   : '[name].css'       }),       new HtmlWebpackPlugin({           inject: false,           hash: true,           template: './index.html',           filename: 'index.html'       }),       new WebpackMd5Hash(),       new CopyWebpackPlugin([            
Seluruh konfigurasi Webpack disajikan sebagai fungsi yang mengambil dua argumen. Argumen 
argv digunakan di sini, yang mewakili argumen yang diteruskan ke fungsi ini ketika perintah 
webpack atau 
webpack-dev-server webpack . Berikut ini uraian perintah-perintah ini dalam file proyek 
package.json :
 "scripts": {   "build": "webpack --mode production && node build-sw",   "serve": "webpack-dev-server --mode=development --hot", }, 
Akibatnya, jika kita menjalankan perintah 
npm run build , versi produksi aplikasi akan dibuat. Jika Anda menjalankan perintah 
npm run serve , server pengembangan akan mulai, mendukung proses pengerjaan aplikasi.
Bagian 
plugins dan 
devServer file di atas menunjukkan cara mengkonfigurasi plugins dan server pengembangan.
Di bagian yang dimulai dengan 
new CopyWebpackPlugin , Anda menentukan sumber daya yang ingin Anda salin dari bahan sumber aplikasi.
Etting Mengatur pekerja layanan
Kita semua tahu bahwa kompilasi daftar file secara manual, misalnya, yang dimaksudkan untuk caching, adalah tugas yang agak membosankan. Oleh karena itu, di sini kita akan menggunakan skrip perakitan pekerja layanan khusus yang menemukan file dalam folder 
dist dan menambahkannya sebagai konten cache dalam templat pekerja layanan. Setelah itu, file pekerja layanan akan ditulis ke folder 
dist . Konsep-konsep yang kita bicarakan ketika melamar pekerja layanan tidak berubah. Berikut ini adalah kode skrip 
build-sw.js :
 const glob = require('glob'); const fs = require('fs'); const dest = 'dist/sw.js'; const staticAssetsCacheName = 'todo-assets-v1'; const dynamicCacheName = 'todo-dynamic-v1';  
Mari kita menganalisis kode ini.
- Fragmen No. 1. Di sini daftar file dari folder distditempatkan di arraystaticAssetsCacheFiles.
- Fragmen No. 2. Ini adalah templat pekerja layanan yang kita bicarakan. Saat membuat kode selesai, variabel digunakan. Ini membuat templat menjadi universal, memungkinkan Anda untuk menggunakannya di masa mendatang, selama pengembangan proyek. Kami juga memerlukan templat karena kami menambahkan informasi tentang isi folder distke dalamnya, yang dapat berubah seiring waktu. Untuk ini,stringFileCachesArraykonstanstringFileCachesArray.
- Fragmen No. 3. Di sini, kode pekerja layanan yang baru dibuat disimpan dalam konstanta serviceWorkerScriptditulis ke file yang terletak didist/sw.js
Untuk menjalankan skrip ini, gunakan perintah 
node build-sw . Itu perlu dieksekusi setelah perintah 
webpack --mode production .
Script untuk membangun pekerja layanan yang disajikan di sini sangat menyederhanakan tugas mengatur file caching. Perlu dicatat bahwa skrip ini telah menemukan aplikasi dalam proyek nyata.
Jika Anda ingin menggunakan perpustakaan khusus yang dirancang untuk memecahkan masalah bekerja aplikasi web progresif offline, lihat 
Workbox . Ini memiliki fitur yang dapat disesuaikan sangat menarik.
β Gambaran umum paket yang digunakan dalam proyek
Ini adalah file 
package.json dari proyek kami, di mana Anda dapat menemukan informasi tentang paket-paket yang digunakan dalam proyek ini:
 { "name": "vanilla-todos-pwa", "version": "1.0.0", "description": "A simple todo application using ES6 and Webpack", "main": "src/main.js", "scripts": {   "build": "webpack --mode production && node build-sw",   "serve": "webpack-dev-server --mode=development --hot" }, "keywords": [], "author": "Anurag Majumdar", "license": "MIT", "devDependencies": {   "@babel/core": "^7.2.2",   "@babel/plugin-syntax-dynamic-import": "^7.2.0",   "@babel/preset-env": "^7.2.3",   "autoprefixer": "^9.4.5",   "babel-core": "^6.26.3",   "babel-loader": "^8.0.4",   "babel-preset-env": "^1.7.0",   "clean-webpack-plugin": "^1.0.0",   "compression-webpack-plugin": "^2.0.0",   "copy-webpack-plugin": "^4.6.0",   "css-loader": "^2.1.0",   "html-webpack-plugin": "^3.2.0",   "mini-css-extract-plugin": "^0.5.0",   "node-sass": "^4.11.0",   "sass-loader": "^7.1.0",   "style-loader": "^0.23.1",   "terser": "^3.14.1",   "webpack": "^4.28.4",   "webpack-cli": "^3.2.1",   "webpack-dev-server": "^3.1.14",   "webpack-md5-hash": "0.0.6" } } 
Jika kita berbicara tentang dukungan proyek-proyek seperti itu, perlu dicatat bahwa alat dalam ekosistem Webpack sering diperbarui. Sering terjadi bahwa plugin yang ada diganti dengan yang baru. Oleh karena itu, penting, ketika memutuskan apakah akan menggunakan yang baru dan bukan beberapa paket, untuk fokus bukan pada paket itu sendiri, tetapi pada fitur yang harus mereka terapkan. Sebenarnya, itulah sebabnya kami berbicara di atas tentang peran yang dimainkan paket ini atau itu.
JavaScript fitur modern
Selama pengembangan aplikasi web, programmer memiliki pilihan - apakah akan menulis implementasi sendiri dari fitur-fitur seperti deteksi perubahan, perutean, penyimpanan data, atau menggunakan paket yang ada.
Sekarang kita akan berbicara tentang set minimum teknologi yang diperlukan untuk memastikan operasi proyek kami. Jika perlu, rangkaian teknologi ini dapat diperluas menggunakan kerangka kerja atau paket yang ada.
β Modul
Kami akan menggunakan kemampuan ES6 untuk mengimpor dan mengekspor modul, mengingat setiap file sebagai modul ES6. Fitur ini sering ditemukan dalam kerangka kerja populer seperti Angular dan React, sangat nyaman untuk menggunakannya. Berkat konfigurasi Webpack yang kami miliki, kami dapat menggunakan ekspresi sumber daya impor dan ekspor. Berikut tampilannya di file 
app.js :
 import { appTemplate } from './app.template'; import { AppModel } from './app.model'; export const AppComponent = {  
βBerbagai cara untuk membuat objek
Pembuatan komponen adalah bagian penting dari proses pengembangan aplikasi kami. Di sini sangat mungkin untuk menggunakan beberapa alat modern, seperti komponen web, tetapi agar tidak menyulitkan proyek, kami akan menggunakan objek JavaScript biasa, yang dapat dibuat baik menggunakan objek literal atau menggunakan sintaks kelas yang muncul dalam standar ES6 .
Keunikan menggunakan kelas untuk membuat objek adalah bahwa setelah deskripsi kelas, Anda perlu membuat instance objek berdasarkan, dan kemudian mengekspor objek ini. Untuk menyederhanakan banyak hal bahkan lebih kuat, kita akan menggunakan di sini objek biasa yang dibuat menggunakan objek literal. Berikut adalah kode untuk file 
app.js mana Anda dapat melihat aplikasi mereka.
 import { appTemplate } from './app.template'; import { AppModel } from './app.model'; export const AppComponent = {   init() {       this.appElement = document.querySelector('#app');       this.initEvents();       this.render();   },   initEvents() {       this.appElement.addEventListener('click', event => {           if (event.target.className === 'btn-todo') {               import(  './todo/todo.module')                   .then(lazyModule => {                       lazyModule.TodoModule.init();                   })                   .catch(error => 'An error occurred while loading Module');           }       });       document.querySelector('.banner').addEventListener('click', event => {           event.preventDefault();           this.render();       });   },   render() {       this.appElement.innerHTML = appTemplate(AppModel);   } }; 
Di sini kita membentuk dan mengekspor komponen 
AppComponent , yang dapat langsung Anda gunakan di bagian lain aplikasi.
Anda bisa menggunakan kelas ES6 atau komponen web dengan sangat baik dalam situasi seperti itu, mengembangkan proyek dengan gaya yang lebih dekat dengan deklaratif daripada yang digunakan di sini. Di sini, agar tidak menyulitkan proyek pelatihan, pendekatan imperatif digunakan.
Import Impor sumber daya dinamis
Ingat bahwa, berbicara tentang pola PRPL, kita belum menemukan bagian yang diwakili oleh huruf L (pemuatan Malas)? Impor sumber daya yang dinamis adalah hal yang membantu kami mengatur pemuatan komponen atau modul yang malas. Karena kami menggunakan arsitektur App Shell dan pola PRPL untuk menyimpan "kerangka" aplikasi dan sumber dayanya, proses impor dinamis memuat sumber daya dari cache, bukan dari jaringan.
Harap perhatikan bahwa jika kami hanya menggunakan arsitektur App Shell, maka sumber daya aplikasi yang tersisa, yaitu isi folder 
chunks , tidak akan di-cache.
Contoh impor sumber daya dinamis dapat dilihat pada fragmen kode di atas komponen 
AppComponent , khususnya, di mana peristiwa klik tombol dikonfigurasikan (kita berbicara tentang metode objek 
initEvents() ). Yaitu, jika pengguna aplikasi mengklik tombol 
btn-todo , modul 
btn-todo akan dimuat. Modul ini adalah file JavaScript biasa yang berisi sekumpulan komponen yang direpresentasikan sebagai objek.
β Fungsi panah dan templat literal
Fungsi panah sangat berguna ketika Anda membutuhkan 
this dalam fungsi tersebut untuk menunjukkan konteks di mana fungsi tersebut dinyatakan. Selain itu, fungsi panah memungkinkan Anda menulis kode yang lebih ringkas daripada menggunakan fungsi konvensional. Berikut ini contoh fungsi tersebut:
 export const appTemplate = model => `   <section class="app">       <h3><font color="#3AC1EF">β ${model.title} </font></h3>       <section class="button">           <button class="btn-todo"> Todo Module </button>       </section>   </section> `; 
Fungsi 
appTemplate mengambil model (parameter 
model ) dan mengembalikan string HTML yang berisi data yang diambil dari model. . , - .
, , . 
reduce() HTML-:
 const WorkModel = [   {       id: 1,       src: '',       alt: '',       designation: '',       period: '',       description: ''   },   {       id: 2,       src: '',       alt: '',       designation: '',       period: '',       description: ''   },    
, . . , , .
:
- model. β ,- reduce(), .
- model.reduce, HTML-, , . , , , β .
. , , β .
Todo-, . .
. 
. , , , .
-
-, , -, . , , . , JavaScript -, .
, .
-. Lighthouse.
Ringkasan
, , JavaScript, . , , , .
Pembaca yang budiman! -, ?
