Tutorial Lengkap Flutter Web untuk Pemula. Awalnya kita hanya mengenal Flutter untuk membangun aplikasi berbasis mobile di Android dan ioS.
Sekarang, Flutter sudah berkembang…
Kita bisa membuat aplikasi berbasis web menggunakan Flutter.
Oleh karena itu, pada tutorial ini kita akan belajar tentang Flutter web disertai contoh membuat website portfolio menggunakan Flutter.
Rincian materi yang akan kita bahas adalah …
- Pengenalan Flutter Web
- Prinsip Kerja Flutter Web
- Upgrade Versi Flutter untuk Support Flutter Web
- Menjalankan Flutter Web untuk Pertama Kali
- Membuat Website Portfolio dengan Flutter Web
Sudah siap?
Yuk kita mulai.
Mengenal Apa Itu Flutter Web
Pada bulan Desember tahun 2018 yang lalu, Flutter Web sudah pernah disinggung pada acara Flutter Live.
Mereka mengenalkan suatu project Flutter Web yang disebut sebagai Flutter Hummingbird.
Project Hummingbird bertujuan agar Flutter bisa digunakan untuk membangun aplikasi berbasis Web.
Lalu, pada acara Google IO 2019, diumumkan kabar baik tentang rilisnya Flutter Web versi technical preview dari project Flutter Hummingbird.
Jadi, kita sudah bisa mencobanya…
Namun sebelum kita mencoba Flutter Web, ada baiknya kita memahami prinsip kerjanya terlebih dahulu…
Prinsip Kerja Flutter Web
Sebelum kita masuk ke prinsip kerja Flutter Web, kita coba pahami dulu prinsip kerja Flutter Mobile dan Desktop:
Secara garis besar, kita hanya perlu fokus pada bagian paling atas.
Bagian itu merupakan kode-kode program dari aplikasi kita.
… di bawahnya merupakan Flutter Engine untuk membangun aplikasi kita.
Jadi bisa disimpulkan begini:
- Kita ngoding menggunakan bahasa pemrograman Dart.
- Flutter akan build ke platform yang kita tuju menggunakan enginenya.
… sedangkan tugas dari platform-spesific embeder yaitu membungkus aplikasi yang kita buat agar bisa dijalankan di berbagai platform seperti Linux, Windows, Mac OS, dan Google Chrome.
Kasus di atas hanya fokus ke Flutter Desktop, gimana kalau Flutter Web?
Mirip.
Pada gambar di atas, Flutter menggunakan Dart2js untuk mengcompile script yang kita buat di Flutter ke Javascript.
Sehingga, Flutter dapat dijalankan pada browser.
Alurnya seperti ini …
Kita nggak perlu capek-capek mikirin yang bawah-bawah, fokus aja ke bagian atas. Kita cukup coding menggunakan Flutter, sisanya biar Flutter yang urus.
Wah, keren ya.
Makin ga sabar nih untuk mencobanya…
Cara Upgrade Versi Flutter
Okay, kita akan mulai mempersiapkan hal-hal yang berkaitan dengan Flutter.
… misalnya install dulu Flutter di komputer kita.
Coba dulu tonton video ini:
Jika sudah, sekarang kita akan melakukan upgrade versi Flutter agar support Flutter Web melalui perintah ini di terminal:
flutter upgrade
Tunggu sampai proses upgrade selesai. Biasanya akan memakan waktu yang lama. Sebab ada 100+ mb yang terdownload. Jadi, cepat atau lambat tergantung koneksi internet.
Sudah selesai upgrade?
Sekarang kita cek versi Flutter yang terinstall setelah melakukan upgrade.
Ketik perintah berikut ini:
flutter --version
Kalau sudah ada perubahan versi, itu artinya kita sudah berhasil melakukan upgrade.
Sekarang coba ketik perintah berikut ini untuk mengaktifkan Flutter web.
flutter config --enable-web
Selanjutnya, coba ketik perintah di bawah ini untuk memeriksa apakah Flutter kita sudah support dengan Flutter Web atau belum:
flutter doctor

Alhamdulillah, semuanya sudah enable termasuk Chrome – Develop For Web.
Sekarang kita sudah bisa membuat project Flutter Web.
Menjalankan Flutter Web Pertama Kali
Okey, semua perangkat sudah siap. Sekarang kita akan membuat project pertama dengan Flutter Web.
Jika belum tahu cara menjalankan project pertama dengan Flutter, silahkan baca ini:
Silahkan ketik perintah berikut ini untuk membuat project baru:
flutter create flutter_web
Saat pertama kali membuat project, sudah tersedia folder web yang dapat kita gunakan untuk membuat website.
Untuk menjalankannya di browser Chrome, silahkan ketik perintah berikut ini:
flutter run -d chrome
Jika berhasil, kita akan mendapatkan tampilan seperti ini:
Wow, mantab betul ya si Flutter ini.
Agar terbiasa, coba kita buat class baru bernama Home
.
Silahkan buat file baru dan beri nama home.dart
pada direktori lib
.
Kemudian ketik kode berikut ini di dalam file home.dart
:
import 'package:flutter/material.dart'; class Home extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ilmu Coding'), centerTitle: true, ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Container( width: 300.0, height: 300.0, decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( fit: BoxFit.cover, image: new NetworkImage( "https://ilmucoding.com/wp-content/uploads/2020/01/Logo-Ilmu-Coding-1200x1035.jpg", ), ), ), ), Column( children: <Widget>[ Text( 'Selamat datang di Tutorial Flutter Web Ilmu Coding', style: TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold), ), SizedBox(height: 30), ], ), Column( children: <Widget>[ Text("Ini adalah demo aplikasi web yang dibuat menggunakan Flutter."), SizedBox(height: 30), ], ), ], ), ), ); } }
Lalu modifikasi file main.dart
menjadi seperti di bawah ini:
import 'package:flutter/material.dart'; import 'package:flutter_web/home.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Tutorial Lengkap Flutter Web untuk Pemula - Ilmu Coding', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.teal, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: Home(), ); } }
Selanjutnya modifikasi file index.html
yang ada di dalam direktori web dengan kode berikut ini:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tutorial Lengkap Flutter Web untuk Pemula - Ilmu Coding</title> <meta name="description" content="Tutorial Lengkap Flutter Web untuk Pemula."> <meta name="keywords" content="Flutter, Flutter Web, Flutter Hummingbird, Hummingbird"> <meta name="author" content="Ilmu Coding"> <!-- iOS meta tags & icons --> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-title" content="flutter_web"> <link rel="apple-touch-icon" href="icons/Icon-192.png"> <link rel="manifest" href="manifest.json"> </head> <body> <script> if ('serviceWorker' in navigator) { window.addEventListener('load', function () { navigator.serviceWorker.register('flutter_service_worker.js'); }); } </script> <script src="main.dart.js" type="application/javascript"></script> </body> </html>
Jalankan projectnya, baik dengan Hot Reload atau mengetik perintah:
flutter run -d chrome
Jika berhasil, maka akan tampil seperti berikut ini:
Wuiih, kita sudah berhasil membuat project Flutter Web.
Keren!
Membuat Website Portfolio dengan Flutter Web
Sekarang kita akan membuat project portfolio menggunakan Flutter Web.
Hasilnya akan seperti ini pada tampilan depan:
… dan ini tampilan untuk membuat halaman project.
Untuk demo, silahkan kunjungi https://wildanfuady.surge.sh/#/
Pertanyaannya, gimana cara buatnya?
Step 1: Menambahkan File Assets
Silahkan buka pubspec.yaml
kemudian tambahkan package dan assets berikut:
name: flutter_web description: Portfolio Wildan Fuady. publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: sdk: ">=2.7.0 <3.0.0" dependencies: flutter: sdk: flutter http: any cupertino_icons: ^0.1.3 dev_dependencies: flutter_test: sdk: flutter flutter: uses-material-design: true assets: - assets/ - assets/works/ fonts: - family: GoogleSansRegular fonts: - asset: assets/GoogleSansRegular.ttf
Kemudian buat folder baru bernama assets
di dalam direktori project dan isi folder tersebut dengan gambar / assets yang kita miliki.
Step 2: Membuat Structure Project
Kita akan fokus pada folder lib
. Silahkan buat file / folder sesuai dengan gambar di bawah ini:
assets.dart
class Assets{ static const moon = 'assets/moon.png'; static const avatar = 'assets/avatar.png'; static const facebook = 'assets/facebook.png'; static const github = 'assets/github.png'; static const instagram = 'assets/instagram.png'; static const linkedin = 'assets/linkedin.png'; static const medium = 'assets/medium.png'; static const medium_light = 'assets/medium_light.png'; static const twitter = 'assets/twitter.png'; static const website = 'assets/works/website.png'; static const folder = 'assets/works/folder.png'; }
Kode tersebut saya gunakan untuk mengelompokan file-file assets. Tujuannya agar lebih mudah saat memanggilnya.
constants.dart
class Constants{ static const MEDIUM_IMAGE_CDN = 'https://miro.medium.com/fit/c/115/115/'; static const BLOG_URL = 'http://www.medium.com/@ilmucoding/'; static const PROFILE_MEDIUM = 'http://www.medium.com/@ilmucoding'; static const PROFILE_LINKEDIN = 'https://www.linkedin.com/in/wildanfuady/'; static const PROFILE_FACEBOOK = 'https://www.facebook.com/wildan110694/'; static const PROFILE_GITHUB = 'https://github.com/wildanfuady/'; static const PROFILE_TWITTER = 'https://twitter.com/wildanfuady_/'; static const PROFILE_INSTAGRAM = 'https://www.instagram.com/wildanfuady_/'; }
Mirip seperti assets, class ini saya gunakan untuk mengelompokan link tertentu.
projects.dart
import 'package:flutter_web/models/project_model.dart'; import 'assets.dart'; final List<Project> projects = [ Project( name: 'Funlish', image: Assets.website, description: 'Aplikasi pembelajaran kursus Bahasa Inggris berbasis website menggunakan Codeigniter 3', link: '#'), Project( name: 'Firebird Care', image: Assets.website, description: 'Aplikasi jasa bongkar pasang air impact menggunakan Codeigniter 3', link: '#'), Project( name: 'E-loker', image: Assets.website, description: 'Aplikasi pendaftaran lowongan kerja suatu perusahaan berbasis website menggunakan Codeigniter 3. ', link: '#'), ];
Kode tersebut saya gunakan untuk menampilkan list project ke dalam aplikasi website.
themes.dart
import 'package:flutter/material.dart'; darkTheme(context) { return ThemeData( fontFamily: 'GoogleSansRegular', primarySwatch: Colors.blue, primaryColor: Colors.black, accentColor: Colors.blue, disabledColor: Colors.grey, cardColor: Color(0xff1f2124), canvasColor: Colors.black, brightness: Brightness.dark, buttonTheme: Theme.of(context).buttonTheme.copyWith( colorScheme: ColorScheme.dark(), buttonColor: Colors.blue, splashColor: Colors.black), appBarTheme: AppBarTheme( elevation: 0.0, ), ); } lightTheme(context) { return ThemeData( fontFamily: 'GoogleSansRegular', primarySwatch: Colors.blue, primaryColor: Colors.white, accentColor: Colors.blue, disabledColor: Colors.grey, cardColor: Colors.white, canvasColor: Colors.white, brightness: Brightness.light, buttonTheme: Theme.of(context).buttonTheme.copyWith( colorScheme: ColorScheme.light(), buttonColor: Colors.blue, splashColor: Colors.white), appBarTheme: AppBarTheme( elevation: 0.0, ), ); }
Kode di atas saya gunakan untuk mengelompokan warna dark dan light serta menambahkan fontnya.
project_model.dart
Kita memerlukan sebuah class Project agar lebih tertata rapi.
Ketik kode berikut:
import 'package:flutter/material.dart'; class Project{ String image; String name; String description; String link; Project({@required this.image,@required this.name,@required this.description, this.link}); }
home.dart
import 'package:flutter_web/config/assets.dart'; import 'package:flutter_web/tabs/about_tab.dart'; import 'package:flutter_web/tabs/projects_tab.dart'; import 'package:flutter_web/widgets/theme_inherited_widget.dart'; import 'package:flutter/material.dart'; class Home extends StatefulWidget { @override _HomeState createState() => _HomeState(); } class _HomeState extends State<Home> { int _selectedIndex = 0; static List<Widget> tabWidgets = <Widget>[ AboutTab(), ProjectsTab(), ]; @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( actions: <Widget>[ IconButton( icon: ThemeSwitcher.of(context).isDarkModeOn?Icon(Icons.wb_sunny):Image.asset(Assets.moon,height: 20,width: 20,), onPressed: ()=> ThemeSwitcher.of(context).switchDarkMode(), ) ], ), body: Center( child: tabWidgets.elementAt(_selectedIndex), ), bottomNavigationBar: BottomNavigationBar( items: const <BottomNavigationBarItem>[ BottomNavigationBarItem( icon: Icon(Icons.account_circle), title: Text('About'), ), BottomNavigationBarItem( icon: Icon(Icons.mobile_screen_share), title: Text('Projects'), ) ], currentIndex: _selectedIndex, onTap: (index)=> setState(() => _selectedIndex = index), selectedItemColor: Theme.of(context).accentColor, ), ); } }
home.dart
digunakan untuk menampilkan halaman yang pertama kali muncul saat aplikasi dijalankan.
about_tab.dart
import 'package:flutter_web/config/assets.dart'; import 'package:flutter_web/config/constants.dart'; import 'package:flutter/material.dart'; import 'dart:html' as html; import '../widgets/theme_inherited_widget.dart'; class AboutTab extends StatelessWidget { @override Widget build(BuildContext context) { return SingleChildScrollView( child: Center( child: Padding( padding: const EdgeInsets.only(bottom: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ CircleAvatar( radius: 100, backgroundImage: Image.asset(Assets.avatar).image, ), SizedBox( height: 20, ), Text( 'Wildan Fuady', textScaleFactor: 4, ), SizedBox( height: 20, ), Text( 'Web. Android. Flutter. Author. Trainer.', style: Theme.of(context).textTheme.caption, textScaleFactor: 2, textAlign: TextAlign.center, ), SizedBox( height: 40, ), Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ FlatButton.icon( icon: SizedBox( width: 20, height: 20, child: Image.asset(Assets.github)), label: Text('Github'), onPressed: () => html.window .open(Constants.PROFILE_GITHUB, 'wildanfuady'), ), FlatButton.icon( icon: SizedBox( width: 20, height: 20, child: Image.asset(Assets.twitter)), label: Text('Twitter'), onPressed: () => html.window .open(Constants.PROFILE_TWITTER, 'wildanfuady'), ), FlatButton.icon( icon: SizedBox( width: 20, height: 20, child: Image.asset( ThemeSwitcher.of(context).isDarkModeOn ? Assets.medium : Assets.medium_light)), label: Text('Medium'), onPressed: () => html.window .open(Constants.PROFILE_MEDIUM, 'wildanfuady'), ) ], ), Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ FlatButton.icon( icon: SizedBox( width: 20, height: 20, child: Image.asset(Assets.instagram)), label: Text('Instagram'), onPressed: () => html.window .open(Constants.PROFILE_INSTAGRAM, 'wildanfuady'), ), FlatButton.icon( icon: SizedBox( width: 20, height: 20, child: Image.asset(Assets.facebook)), label: Text('Facebook'), onPressed: () => html.window .open(Constants.PROFILE_FACEBOOK, 'wildanfuady'), ), FlatButton.icon( icon: SizedBox( width: 20, height: 20, child: Image.asset(Assets.linkedin)), label: Text('Linkedin'), onPressed: () => html.window .open(Constants.PROFILE_LINKEDIN, 'wildanfuady'), ) ], ) ], ), ), ), ); } }
Kode ini saya gunakan untuk menampilkan gambar utama dan sosial media di halaman about.
project_tab.dart
import 'package:flutter_web/config/projects.dart'; import 'package:flutter_web/widgets/project_widget.dart'; import 'package:flutter_web/widgets/responsive_widget.dart'; import 'package:flutter/material.dart'; class ProjectsTab extends StatelessWidget { @override Widget build(BuildContext context) { return ResponsiveWidget( largeScreen: GridView.count( padding: EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 32.0), crossAxisCount: 3, childAspectRatio: MediaQuery.of(context).size.width / (MediaQuery.of(context).size.height / 1.3), children: List.generate( projects.length, (index) => ProjectWidget(projects[index], 0)), ), smallScreen: ListView.builder( itemCount: projects.length, itemBuilder: (context, index) => ProjectWidget( projects[index], (index == projects.length - 1 ? 16.0 : 0))), ); } }
Kode ini saya gunakan untuk menampilkan halaman project saat menu project diklik.
project_widget.dart
import 'package:flutter_web/models/project_model.dart'; import 'package:flutter/material.dart'; import 'dart:html' as html; class ProjectWidget extends StatelessWidget { final Project _project; final double _bottomPadding; ProjectWidget(this._project,this._bottomPadding ); @override Widget build(BuildContext context) { final width = MediaQuery.of(context).size.width; final height = MediaQuery.of(context).size.height; return Card( margin: EdgeInsets.fromLTRB(16.0,16.0,16.0,_bottomPadding), child:InkWell( onTap: onProjectClick, child: Padding( padding: const EdgeInsets.all(8.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: <Widget>[ Expanded( flex: 40, child: Image.asset( _project.image, width: width * .25, height: width*.25, )), Expanded( flex: 3, child: Container(), ), Expanded( flex: 60, child: Container( padding: EdgeInsets.only(top: 8.0), child: Column( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text(_project.name, style: Theme.of(context).textTheme.title), SizedBox( height: height * .01, ), Text( _project.description, textScaleFactor: 1.2, style: Theme.of(context).textTheme.caption, ), ], ), ), ) ], ), ), ), ); } void onProjectClick(){ if(_project.link!=null) html.window.open(_project.link, 'wildanfuady'); } }
Code di atas saya gunakan untuk membuat custom widget ketika menampilkan halaman project.
responsive_widget.dart
import 'package:flutter/material.dart'; class ResponsiveWidget extends StatelessWidget { final Widget largeScreen; final Widget mediumScreen; final Widget smallScreen; const ResponsiveWidget( {Key key, @required this.largeScreen, this.mediumScreen, this.smallScreen}) : super(key: key); static bool isSmallScreen(BuildContext context) { return MediaQuery.of(context).size.width < 800; } static bool isLargeScreen(BuildContext context) { return MediaQuery.of(context).size.width > 800; } static bool isMediumScreen(BuildContext context) { return MediaQuery.of(context).size.width > 800 && MediaQuery.of(context).size.width < 1200; } @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth > 800) { return largeScreen; } else if (constraints.maxWidth < 1200 && constraints.maxWidth > 800) { return mediumScreen ?? largeScreen; } else { return smallScreen ?? largeScreen; } }, ); } }
Code di atas saya gunakan untuk membuat layout yang responsive pada aplikasi Flutter Web.
theme_inherited_widget.dart
import 'package:flutter/material.dart'; class ThemeSwitcher extends InheritedWidget { final _ThemeSwitcherWidgetState data; // We'll use ThemeSwitcher to get access to the current state of ThemeSwitcherWidget const ThemeSwitcher({ Key key, @required this.data, @required Widget child, }) : assert(child != null), super(key: key, child: child); static _ThemeSwitcherWidgetState of(BuildContext context) { //This method returns the current state of the ThemeSwitcherWidget. This will be used down the tree return (context.inheritFromWidgetOfExactType(ThemeSwitcher) as ThemeSwitcher) .data; } @override bool updateShouldNotify(ThemeSwitcher old) { return this != old; } } class ThemeSwitcherWidget extends StatefulWidget { final bool initialDarkModeOn; // this is the initial state of the variable final Widget child; // child to which this boolean variable should be propagated upon change. This will be our app in this case ThemeSwitcherWidget({Key key, this.initialDarkModeOn, this.child}) : assert(initialDarkModeOn != null), assert(child != null), super(key: key); @override _ThemeSwitcherWidgetState createState() => _ThemeSwitcherWidgetState(); } class _ThemeSwitcherWidgetState extends State<ThemeSwitcherWidget> { bool isDarkModeOn; void switchDarkMode() { //method used to toggle dark mode during the runtime of the app setState(() { isDarkModeOn = !isDarkModeOn; }); } @override Widget build(BuildContext context) { isDarkModeOn = isDarkModeOn ?? widget.initialDarkModeOn; // this is the build method which would build the widget tree with the above info return ThemeSwitcher( data: this, child: widget.child, ); } }
Theme Switcher kita gunakan untuk mengatur theme sesuai dengan pilihan user.
main.dart
import 'package:flutter/material.dart'; import 'package:flutter_web/pages/home.dart'; import 'package:flutter_web/widgets/theme_inherited_widget.dart'; import 'config/themes.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ThemeSwitcherWidget ( initialDarkModeOn: false, child: WildanFuady(), ); } } class WildanFuady extends StatelessWidget { const WildanFuady({ Key key, }) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Wildan Fuady', theme:ThemeSwitcher.of(context).isDarkModeOn?darkTheme(context):lightTheme(context), home: Home(), ); } }
Waw. Banyak juga ya kodenya :v
Tenang … Sekarang kita akan coba hosting ke surge.
Step 3: Build
Sebelum di hosting, kita harus build dulu projectnya. Ketik perintah berikut ini:
flutter build web
Tunggu sampai prosesnya selesai…
Kalau sudah, kita akan lanjut ke hosting!
Step 4: Hosting ke Surge
Surge adalah layanan hosting gratis untuk website statis.
Kita perlu install dulu surgenya…
… ketik perintah ini:
npm install --global surge
Jika sudah, sekarang kita masuk ke dalam direktori build/web.
cd build/web
Kemudian ketik perintah berikut ini:
surge
Isi email dan password untuk login / register, custom sub domain project kita dan lanjutkan prosesnya sampai berhasil.
Perhatikan gambar di bawah ini:
Jika diminta email dan password, silahkan isi saja ya.
Selesai…
Alhamdulillah.
Cek demonya di: https://wildanfuady.surge.sh/#/
Salam Belajar
Alhamdulillah telah selesai tutorial lengkap flutter web untuk pemula yang cukup panjang ini.
… eits. Tapi jangan puas dulu ya.
Sebab masih banyak hal yang perlu kita pelajar lho tentang tutorial Flutter Web ini.
Misalnya:
Oh iya, kalau mau download source codenya, silahkan melalui link Github di bawah ini ya:
Please share tutorial ini kalau bermanfaat ya. Jangan lupa untuk kirimkan komentar kalian di artikel ini.
So, Terima kasih ya.
Selamat belajar …
tutorialnya menurut saya bagus, cuman hasil jadi dengan mengikuti koding secara struktur ada miss sedikit, tapi thanks untuk artikelnya.
Terima kasih. Mohon sertakan saran agar ke depannya lebih baik lagi.
kok jadinya berat banget ya? padahal simple gitu. bayangkan kalau lebih complex bisa bisa user kabur duluan
saya coba standart sih.
link https://wildanfuady.surge.sh/#/ kok berat ya slur bukanya? dan hasilnya ga keluar
Betul memang berat, tapi hasilnya ada kok. Saya sudah coba. Pastikan koneksi stabil dan lancar.
Pak mau nanya dong, kalau di deploy server hosting lain seperti webhost00 atau niagahoster bisa ga sih?
karena pas build kan ada file “index.html” nya juga ya? apa bisa langsung upload aja ke file managernya?
Silahkan dicoba mas …