Menghasilkan ikon multi-platform multi-merek dengan Sketch dan skrip Node.js - Bagian # 2



Ini adalah bagian kedua dari posting tentang pembuatan pipa yang dapat mengambil file Sketch dan mengekspor semua ikon yang termasuk dalam file, dalam format yang berbeda, untuk platform yang berbeda, dengan kemungkinan AB menguji setiap ikon.

Anda dapat membaca bagian pertama dari posting di sini .



File Sketsa, dengan semua ikon yang dikumpulkan, ditata dan dinamai dengan benar, sudah siap. Sekarang saatnya untuk mulai menulis kode.

Cukuplah untuk mengatakan, prosesnya sangat coba-coba: setelah inti kode awal yang penting, yang dikembangkan oleh pemimpin tim saya Nikhil Verma (yang menetapkan fondasi skrip), saya melalui proses bertahap yang membutuhkan setidaknya tiga fase refactoring dan beberapa revisi. Untuk alasan ini, saya tidak akan membahas terlalu banyak tentang bagaimana skrip dikembangkan, tetapi lebih fokus pada bagaimana skrip bekerja hari ini, dalam bentuk akhirnya.

Skrip pembuatan


Skrip build - ditulis dalam Node.js - relatif mudah dalam alurnya: setelah mengimpor dependensi, mendeklarasikan daftar file Sketsa untuk diproses (sebagai daftar merek, dan untuk setiap merek daftar file untuk merek itu) dan memeriksa apakah Sketch diinstal pada klien, skrip loop pada susunan merek, dan untuk masing-masing skrip itu mengeksekusi langkah-langkah ini secara berurutan:

  1. Dapatkan token desain untuk merek (kita perlu nilai warna)
  2. Mengkloning file Sketsa yang terkait dengan merek, unzip mereka untuk mengekspos file JSON internal, dan memanipulasi beberapa nilai internal file JSON ini (lebih lanjut tentang ini nanti)
  3. Baca meta-data yang relevan dari file Sketch JSON ( document.json , meta.json , dan pages / pageUniqueID.json ); khususnya kita membutuhkan daftar gaya bersama dan daftar aset / ikon yang terkandung dalam file
  4. Setelah beberapa manipulasi lebih lanjut dari file Sketch JSON, kembalikan dan, dengan menggunakan file Sketsa (kloning dan diperbarui), ekspor dan hasilkan file hasil akhir untuk tiga platform (iOS, Android, Mobile Web)

Anda dapat melihat bagian yang relevan dari skrip pembuatan utama di sini:

// ... modules imports here const SKETCH_FILES = { badoo: ['icons_common'], blendr: ['icons_common', 'icons_blendr'], fiesta: ['icons_common', 'icons_fiesta'], hotornot: ['icons_common', 'icons_hotornot'], }; const SKETCH_FOLDER_PATH = path.resolve(__dirname, '../src/'); const SKETCH_TEMP_PATH = path.resolve(SKETCH_FOLDER_PATH, 'tmp'); const DESTINATION_PATH = path.resolve(__dirname, '../dist'); console.log('Build started...'); if (sketchtool.check()) { console.log(`Processing Sketch file via ${sketchtool.version()}`); build(); } else { console.info('You need Sketch installed to run this script'); process.exit(1); } // ---------------------------------------- function build() { // be sure to start with a blank slate del.sync([SKETCH_TEMP_PATH, DESTINATION_PATH]); // process all the brands declared in the list of Sketch files Object.keys(SKETCH_FILES).forEach(async (brand) => { // get the design tokens for the brand const brandTokens = getDesignTokens(brand); // prepare the Sketch files (unzipped) and get a list of them const sketchUnzipFolders = await prepareSketchFiles({ brand, sketchFileNames: SKETCH_FILES[brand], sketchFolder: SKETCH_FOLDER_PATH, sketchTempFolder: SKETCH_TEMP_PATH }); // get the Sketch metadata const sketchMetadata = getSketchMetadata(sketchUnzipFolders); const sketchDataSharedStyles = sketchMetadata.sharedStyles; const sketchDataAssets = sketchMetadata.assetsMetadata; generateAssetsPDF({ platform: 'ios', brand, brandTokens, sketchDataSharedStyles, sketchDataAssets }); generateAssetsSVGDynamicMobileWeb({ platform: 'mw', brand, brandTokens, sketchDataSharedStyles, sketchDataAssets }); generateAssetsVectorDrawableDynamicAndroid({ platform: 'android', brand, brandTokens, sketchDataSharedStyles, sketchDataAssets }); }); } 

Sebenarnya, seluruh kode pipa jauh lebih kompleks dari ini, dan kerumitannya terletak pada prepSketchFiles , getSketchMetadata , dan menghasilkan fungsi [format] [platform] perangkat asset . Saya akan mencoba menjelaskannya secara lebih rinci di bawah ini.

Mempersiapkan file Sketsa


Langkah pertama dalam proses pembuatan adalah persiapan file Sketsa, sehingga mereka dapat digunakan nanti untuk ekspor aset untuk platform yang berbeda.

File yang terkait dengan merek - untuk Blendr, misalnya, file icons_common.sketch dan icons_blendr.sketch - pada awalnya dikloning dalam folder sementara (lebih tepatnya, dalam subfolder bernama setelah merek yang sedang diproses) dan membuka ritsleting.

Kemudian file JSON internal diproses, menjadi awalan yang ditambahkan ke aset yang akan menjalani pengujian AB, sehingga ketika diekspor mereka akan disimpan dalam subfolder dengan nama yang telah ditentukan (nama unik percobaan). Untuk memahami aset mana yang akan diuji, kami cukup memeriksa apakah nama halaman tempat mereka disimpan dalam Sketsa diawali dengan "XP_" .


Perbandingan nama layer, di dalam file Sketch, sebelum dan sesudah pembaruan.

Dalam contoh di atas, ketika diekspor, aset akan disimpan dalam subfolder "this__is_an_experiment" , dengan nama file "icon-name [variant-name] .ext" .

Membaca metadata sketsa


Langkah penting kedua dalam proses ini adalah mengeluarkan semua meta-data yang relevan dari file Sketch, khususnya dari file JSON internal mereka. Seperti dijelaskan di atas, file-file ini adalah dua file utama ( document.json dan meta.json ) dan file halaman ( halaman / pageUniqueId.json ).

File document.json digunakan untuk mendapatkan daftar Gaya Bersama, yang muncul di bawah properti objek layerStyles :

 { "_class": "document", "do_objectID": "45D2DA82-B3F4-49D1-A886-9530678D71DC", "colorSpace": 1, ... "layerStyles": { "_class": "sharedStyleContainer", "objects": [ { "_class": "sharedStyle", "do_objectID": "9BC39AAD-CDE6-4698-8EA5-689C3C942DB4", "name": "features/feature-like", "value": { "_class": "style", "fills": [ { "_class": "fill", "isEnabled": true, "color": { "_class": "color", "alpha": 1, "blue": 0.10588235408067703, "green": 0.4000000059604645, "red": 1 }, "fillType": 0, "noiseIndex": 0, "noiseIntensity": 0, "patternFillType": 1, "patternTileScale": 1 } ], "blur": {...}, "startMarkerType": 0, "endMarkerType": 0, "miterLimit": 10, "windingRule": 1 } }, ... 

Untuk setiap gaya, kami menyimpan beberapa informasi dasar dalam objek nilai kunci. Ini akan digunakan nanti setiap kali kita perlu mengambil nama gaya berdasarkan ID uniknya (dalam Sketsa, properti do_objectID ):

 const parsedSharedStyles = {}; parsedDocument.layerStyles.objects.forEach((object) => { parsedSharedStyles[object.do_objectID] = { name: object.name, isFill: _.get(object, 'value.fills[0].color') !== undefined, isBorder: _.get(object, 'value.borders[0].color') !== undefined, }; }); 


Pada titik ini, kita beralih pada file meta.json untuk mendapatkan daftar halaman, khususnya kita memerlukan id dan nama unik mereka:

 { "commit": "623a23f2c4848acdbb1a38c2689e571eb73eb823", "pagesAndArtboards": { "EE6BE8D9-9FAD-4976-B0D8-AB33D2B5DBB7": { "name": "Icons", "artboards": { "3275987C-CE1B-4369-B789-06366EDA4C98": { "name": "badge-feature-like" }, "C6992142-8439-45E7-A346-FC35FA01440F": { "name": "badge-feature-crush" }, ... "7F58A1C4-D624-40E3-A8C6-6AF15FD0C32D": { "name": "tabbar-livestream" } ... } }, "ACF82F4E-4B92-4BE1-A31C-DDEB2E54D761": { "name": "XP_this__is_an_experiment", "artboards": { "31A812E8-D960-499F-A10F-C2006DDAEB65": { "name": "this__is_an_experiment/tabbar-livestream[variant1]" }, "20F03053-ED77-486B-9770-32E6BA73A0B8": { "name": "this__is_an_experiment/tabbar-livestream[variant2]" }, "801E65A4-3CC6-411B-B097-B1DBD33EC6CC": { "name": "this__is_an_experiment/tabbar-livestream[control]" } } }, 

Kemudian, untuk setiap halaman kami membaca file JSON yang sesuai di bawah folder halaman (seperti yang sudah dikatakan, nama file adalah [pageUniqueId] .json ), dan kami menelusuri aset-aset yang terkandung dalam halaman itu (mereka muncul sebagai layer). Dengan cara ini, untuk setiap ikon kita mendapatkan namanya, lebar / tingginya, meta-data Sketsa untuk ikon lapisan itu, dan jika itu ada di halaman percobaan, nama tes AB yang dipertanyakan, dan nama varian untuk ikon itu.

Perhatikan : objek "page.json" sangat kompleks, jadi saya tidak akan membahasnya di sini. Jika Anda penasaran dan ingin melihat seperti apa bentuknya, saya sarankan Anda untuk membuat file Sketsa baru yang kosong, menambahkan beberapa konten di dalamnya, dan menyimpannya; kemudian ganti ekstensi di zip, unzip dan lihat salah satu file yang muncul di bawah folder "halaman".

Saat memproses artboards, kami juga membuat daftar percobaan (dengan aset terkait) yang akan digunakan nanti untuk menentukan opsi ikon mana yang digunakan dan untuk eksperimen mana, mengaitkan nama opsi ikon ke objek "ikon dasar".

Untuk setiap file Sketsa yang sedang diproses yang terkait dengan merek, kami menghasilkan objek asetMetadata yang terlihat seperti ini:

 { "navigation-bar-edit": { "do_objectID": "86321895-37CE-4B3B-9AA6-6838BEDB0977", ...sketch_artboard_properties, "name": "navigation-bar-edit", "assetname": "navigation-bar-edit", "source": "icons_common", "width": 48, "height": 48 "layers": [ { "do_objectID": "A15FA03C-DEA6-4732-9F85-CA0412A57DF4", "name": "Path", ...sketch_layer_properties, "sharedStyleID": "6A3C0FEE-C8A3-4629-AC48-4FC6005796F5", "style": { ... "fills": [ { "_class": "fill", "isEnabled": true, "color": { "_class": "color", "alpha": 1, "blue": 0.8784313725490196, "green": 0.8784313725490196, "red": 0.8784313725490196 }, } ], "miterLimit": 10, "startMarkerType": 0, "windingRule": 1 }, }, ], ... }, "experiment-name/navigation-bar-edit[variant]": { "do_objectID": "00C0A829-D8ED-4E62-8346-E7EFBC04A7C7", ...sketch_artboard_properties, "name": "experiment-name/navigation-bar-edit[variant]", "assetname": "navigation-bar-edit", "source": "icons_common", "width": 48, "height": 48 ... 

Seperti yang Anda lihat, "ikon" yang sama (dalam hal ini navigasi-bar-edit ) dapat memiliki beberapa "aset" yang terkait dengannya, dalam hal eksperimen. Tetapi ikon yang sama dapat muncul dengan nama yang sama dalam file Sketsa kedua yang terkait dengan merek, dan ini sangat berguna: ini adalah trik yang telah kami gunakan, untuk mengkompilasi satu set ikon yang umum dan kemudian menentukan varian ikon tertentu yang berbeda tergantung pada merek.

Itu sebabnya kami mendeklarasikan file Sketsa yang terkait dengan masing-masing merek sebagai array:

 const SKETCH_FILES = { badoo: ['icons_common'], blendr: ['icons_common', 'icons_blendr'], fiesta: ['icons_common', 'icons_fiesta'], hotornot: ['icons_common', 'icons_hotornot'], }; 

Karena dalam hal ini urutan penting. Dan pada kenyataannya, dalam fungsi getSketchMetadata , dipanggil oleh skrip build, kami tidak mengembalikan objek asetMetadata (satu per file) sebagai daftar, melainkan melakukan penggabungan mendalam dari setiap objek, satu ke yang lain, lalu kami mengembalikan objek asetMetadata gabungan tunggal.

Ini tidak lebih dari gabungan "logis" dari file Sketsa, dan asetnya, menjadi satu file tunggal. Tetapi logikanya sebenarnya tidak sesederhana kelihatannya. Berikut adalah skema yang harus kami buat untuk mencari tahu apa yang terjadi ketika ada ikon dengan nama yang sama (mungkin di bawah pengujian AB) dalam file berbeda yang terkait dengan merek yang sama:


Skema logis tentang bagaimana "penggantian" dari ikon yang sama bekerja, antara seperangkat ikon dan ikon bersama yang dirancang khusus untuk label putih (juga mempertimbangkan kasus pengujian AB)

Membuat file akhir dalam berbagai format untuk berbagai platform


Langkah terakhir dari proses ini adalah pembuatan file ikon dengan format berbeda untuk platform yang berbeda (PDF untuk iOS, SVG / JSX untuk Web, dan VectorDrawable untuk Android).

Seperti yang dapat Anda lihat dari jumlah parameter yang diteruskan ke fungsi generateAssets [format] [platform] ini adalah bagian paling kompleks dari pipeline. Di sinilah proses mulai membelah dan menyimpang untuk platform yang berbeda. Lihat di bawah ini alur logis lengkap skrip, dan bagaimana bagian yang terkait dengan pembuatan aset terbagi menjadi tiga aliran yang serupa tetapi tidak identik:



Untuk menghasilkan aset akhir dengan warna yang benar terkait dengan merek yang sedang diproses, kita perlu melakukan serangkaian manipulasi pada file Sketch JSON: kita mengulangi secara berulang-ulang setiap lapisan yang memiliki gaya berbagi yang diterapkan, dan mengganti nilai warna dengan warna dari token desain untuk merek.

Untuk generasi Android, diperlukan manipulasi tambahan (lebih lanjut tentang ini nanti): kami mengubah properti aturan-isi setiap lapisan dari even-odd ke non-zero (ini dikendalikan oleh properti "windingRule" di objek JSON, di mana " 1 "berarti" genap-genap "dan" 0 "berarti" bukan-nol ").

Setelah menyelesaikan manipulasi ini, kami mengompres file Sketch JSON kembali ke file Sketch standar, sehingga dapat diproses untuk mengekspor aset dengan properti yang diperbarui (file yang diklon dan diperbarui adalah file Sketsa yang benar-benar normal: mereka dapat dibuka di Sketch , dilihat, diedit, disimpan, dll).

Pada titik ini kita dapat menggunakan sketchtool ( dalam pembungkus simpul ) untuk secara otomatis mengekspor semua aset dalam format tertentu untuk platform tertentu. Untuk setiap file yang terkait dengan merek (lebih tepatnya, versi yang dikloning dan dimutakhirkan) kami menjalankan perintah ini:

 sketchtool.run(`export slices ${cloneSketchFile} --formats=svg <i>--scales=1 </i>--output=${destinationFolder} --overwriting`); 

Seperti yang Anda tebak, perintah ini mengekspor aset dalam format tertentu, menerapkan penskalaan opsional (untuk saat ini kami selalu menyimpan skala aslinya), ke folder tujuan. Opsi --overwriting adalah kunci di sini: dengan cara yang sama kita melakukan "penggabungan mendalam" dari objek assetsMetadata (yang berjumlah "gabungan logis" dari file Sketsa), ketika kita mengekspor kita melakukannya dari banyak file ke dalam folder yang sama (unik per merek / platform). Ini berarti bahwa jika suatu aset - diidentifikasi dengan nama lapisannya - sudah ada dalam file Sketsa sebelumnya, itu akan ditimpa oleh ekspor berikut. Yang, sekali lagi, tidak lebih dari operasi "penggabungan".

Namun dalam hal ini, kita mungkin memiliki beberapa aset yang merupakan "hantu". Ini terjadi ketika ikon diuji AB dalam file, tetapi ditimpa dalam file berikutnya. Dalam kasus seperti itu, file varian diekspor ke folder tujuan, direferensikan dalam objek assetsMetadata sebagai aset (dengan kunci dan propertinya), tetapi tidak terkait dengan aset "basis" apa pun (karena penggabungan mendalam dari objek assetsMetadata aset ). File-file ini akan dihapus pada langkah selanjutnya, sebelum proses selesai.



Seperti disebutkan di atas, kita membutuhkan format final yang berbeda untuk platform yang berbeda. Untuk iOS kami menginginkan file PDF, dan kami dapat mengekspornya langsung dengan perintah sketchtool . Sementara, untuk Web Seluler kami menginginkan file JSX, dan untuk Android kami menginginkan file VectorDrawable; untuk alasan ini kami mengekspor aset dalam format SVG ke folder perantara, dan kemudian kami akan memprosesnya lebih lanjut.

File PDF untuk iOS


Anehnya, PDF adalah (hanya?) Format yang didukung oleh Xcode dan OS / iOS untuk mengimpor dan merender aset vektor ( berikut adalah penjelasan singkat tentang alasan teknis di balik pilihan ini oleh Apple).

Karena kita dapat mengekspor langsung dalam PDF melalui Sketchtool, tidak perlu langkah-langkah tambahan untuk platform ini: kita cukup menyimpan file secara langsung di folder tujuan, dan hanya itu.

Bereaksi / file JSX untuk web


Dalam kasus Web, kami menggunakan perpustakaan Node yang disebut svgr yang mengubah file SVG sederhana menjadi komponen Bereaksi. Tapi kami ingin melakukan sesuatu yang lebih kuat: kami ingin "melukis secara dinamis" ikon saat runtime, dengan warna yang berasal dari token desain. Untuk alasan ini, tepat sebelum konversi, kami mengganti dalam SVG nilai isian lintasan yang awalnya memiliki gaya bersama diterapkan, dengan nilai token terkait yang terkait dengan gaya itu.

Jadi, jika ini adalah file badge-feature-like.svg yang diekspor dari Sketch:

 <?xml version="1.0" encoding="UTF-8"?> <svg width="128px" height="128px" viewBox="0 0 128 128" version="1.1" xmlns="<a href="http://www.w3.org/2000/svg">http://www.w3.org/2000/svg</a>" xmlns:xlink="<a href="http://www.w3.org/1999/xlink">http://www.w3.org/1999/xlink</a>"> <!-- Generator: sketchtool 52.2 (67145) - <a href="http://www.bohemiancoding.com/sketch">http://www.bohemiancoding.com/sketch</a> --> <title>badge-feature-like</title> <desc>Created with sketchtool.</desc> <g id="Icons" fill="none" fill-rule="evenodd"> <g id="badge-feature-like"> <circle id="circle" fill="#E71032" cx="64" cy="64" r="64"> <path id="Shape" fill="#FFFFFF" d="M80.4061668,..."></path> </g> </g> </svg> 

ikon aset / ikon badge-feature-like.js akhir akan terlihat seperti ini:

 /* This file is generated automatically - DO NOT EDIT */ /* eslint-disable max-lines,max-len,camelcase */ const React = require('react'); module.exports = function badge_feature_like({ tokens }) { return ( <svg data-origin="pipeline" viewBox="0 0 128 128"> <g fill="none" fillRule="evenodd"> <circle fill={tokens.TOKEN_COLOR_FEATURE_LIKED_YOU} cx={64} cy={64} r={64} /> <path fill="#FFF" d="M80.4061668,..." /> </g> </svg> ); }; 

Seperti yang Anda lihat, kami telah mengganti nilai statis untuk warna isian lingkaran, dengan yang dinamis, yang mengambil nilainya dari token desain (ini akan tersedia untuk komponen Bereaksi <Ikon /> melalui Context API, tapi itu cerita lain).

Penggantian ini dimungkinkan melalui meta-data Sketsa untuk aset yang disimpan dalam aset Metadata objek: pengulangan secara rekursif melalui lapisan aset, dimungkinkan untuk membuat pemilih DOM (dalam kasus di atas, itu akan menjadi #Icons # badge-feature- seperti #circle ) dan gunakan itu untuk menemukan simpul di pohon SVG, dan ganti nilai atribut fill -nya (untuk operasi ini kita menggunakan library cheerio ).

File VectorDrawable untuk Android


Android mendukung grafik vektor menggunakan format vektor kustom, yang disebut VectorDrawable . Biasanya konversi dari SVG ke VectorDrawable dilakukan langsung di Android Studio oleh pengembang. Tapi di sini kami ingin mengotomatiskan seluruh proses, jadi kami perlu menemukan cara untuk mengubahnya melalui kode.

Setelah melihat berbagai pustaka dan alat, kami memutuskan untuk menggunakan pustaka yang disebut svg2vectordrawable . Tidak hanya itu dipelihara secara aktif (setidaknya, lebih baik dari yang lain yang kami temukan) tetapi juga lebih lengkap.

Faktanya adalah bahwa VectorDrawable tidak dalam paritas fitur dengan SVG: beberapa fitur canggih SVG (misalnya gradien radial, masker kompleks, dll.) Tidak didukung , dan beberapa dari mereka telah mendapatkan dukungan baru-baru ini (dengan Android API 24 dan lebih tinggi). Satu kelemahan dari hal ini adalah bahwa di Android pra-24 aturan isi "genap" tidak didukung . Tetapi di Badoo kita perlu mendukung Android 5 dan di atasnya. Itu sebabnya, seperti dijelaskan di atas, untuk Android kita perlu mengkonversi setiap jalur dalam file Sketch menjadi isian "non-zero".

Secara potensial, para desainer dapat melakukan ini secara manual:



tapi ini mungkin mudah diabaikan, dan jadi rentan terhadap kesalahan manusia.

Untuk alasan ini, kami telah menambahkan langkah ekstra dalam proses kami untuk Android, di mana kami secara otomatis mengonversi semua jalur menjadi nol di Sketch JSON. Ini agar ketika kita mengekspor ikon ke SVG, ikon tersebut sudah ada dalam format ini, dan setiap VectorDrawable yang dihasilkan juga kompatibel dengan perangkat Android 5.

File badge-feature-like.xml akhir dalam kasus ini terlihat seperti ini:

 <!-- This file is generated automatically - DO NOT EDIT --> <vector xmlns:android="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>" android:width="128dp" android:height="128dp" android:viewportWidth="128" android:viewportHeight="128"> <path android:fillColor="?color_feature_liked_you" android:pathData="M64 1a63 63 0 1 0 0 126A63 63 0 1 0 64 1z" /> <path android:fillColor="#FFFFFF" android:pathData="M80.406 ..." /> </vector> 

Seperti yang Anda lihat, juga dalam file VectorDrawable kami menyuntikkan nama variabel untuk warna isian , yang terkait dengan token desain melalui gaya kustom di aplikasi Android.

Inilah yang terlihat seperti VectorDrawable yang pernah diimpor di Android Studio:


Contoh ikon VectorDrawable yang diimpor ke Android Studio

Satu hal yang perlu diperhatikan dalam kasus ini: Android Studio memiliki cara yang sangat ketat dan preskriptif mengatur aset: tidak ada folder bersarang dan semua nama huruf kecil! Ini berarti kami harus membuat format yang sedikit berbeda untuk nama ikon mereka: dalam kasus aset yang sedang dalam percobaan, namanya akan seperti ic_icon-name__experiment-name__variant-name .

Kamus JSON sebagai perpustakaan aset


Setelah file aset disimpan dalam format terakhirnya, hal terakhir yang masih harus dilakukan adalah menyimpan semua informasi meta yang dikumpulkan selama proses pembangunan, dan menyimpannya dalam "kamus", sehingga dapat dibuat tersedia nanti ketika aset diimpor dan dikonsumsi oleh basis kode dari platform yang berbeda.

Setelah mengekstrak daftar datar ikon dari objek assetsMetadata , kami mengulanginya dan untuk setiap item kami memeriksa:

  • jika itu adalah aset normal (mis. tabbar-livestream ), dan jika ya, kita simpan saja;
  • jika ini merupakan varian dalam tes AB (mis. eksperimen / tabbar-livestream [varian] ), kita asosiasikan namanya, jalur, uji AB, dan nama varian, dengan properti properti dari aset "basis" (dalam hal ini, tabbar- streaming langsung ), dan kemudian kita menghapus entri varian dari daftar / objek (hanya "basis" yang dihitung);
  • jika itu adalah varian "hantu", kami menghapus file, dan kemudian menghapus entri dari daftar / objek.

Setelah loop selesai, kamus akan berisi daftar semua dan hanya ikon "dasar" (dan tes AB-nya, jika sedang dalam percobaan). Untuk masing-masing ini akan berisi nama, ukuran, jalur dan, jika ikon di bawah pengujian AB, informasi tentang berbagai opsi aset.

Kamus ini kemudian disimpan dalam format JSON di folder tujuan untuk merek dan platform . Di sini, misalnya, adalah file assets.json yang dihasilkan untuk aplikasi "Blendr" di "web seluler":

 { "platform": "mw", "brand": "blendr", "assets": { "badge-feature-like": { "assetname": "badge-feature-like", "path": "assets/badge-feature-like.jsx", "width": 64, "height": 64, "source": "icons_common" }, "navigation-bar-edit": { "assetname": "navigation-bar-edit", "path": "assets/navigation-bar-edit.jsx", "width": 48, "height": 48, "source": "icons_common" }, "tabbar-livestream": { "assetname": "tabbar-livestream", "path": "assets/tabbar-livestream.jsx", "width": 128, "height": 128, "source": "icons_blendr", "abtest": { "this__is_an_experiment": { "control": "assets/this__is_an_experiment/tabbar-livestream__control.jsx", "variant1": "assets/this__is_an_experiment/tabbar-livestream__variant1.jsx", "variant2": "assets/this__is_an_experiment/tabbar-livestream__variant2.jsx" }, "a_second-experiment": { "control": "assets/a_second-experiment/tabbar-livestream__control.jsx", "variantA": "assets/a_second-experiment/tabbar-livestream__variantA.jsx" } } }, ... } } 

Langkah terakhir adalah mengompres semua folder aset di. zip file, sehingga mereka dapat diunduh dengan lebih mudah.

Hasil akhir


Proses yang dijelaskan di atas - mulai dari kloning awal dan manipulasi file Sketch, hingga ekspor (dan konversi) aset dalam format yang diinginkan untuk setiap platform yang didukung, hingga penyimpanan meta-informasi yang dikumpulkan di perpustakaan aset - adalah diulang untuk setiap merek yang dinyatakan dalam skrip build.

Di bawah ini adalah tangkapan layar seperti apa struktur folder src dan dist , setelah proses pembangunan selesai:


Struktur folder "src" dan "dist" setelah proses build selesai.

Pada titik ini, dengan satu perintah sederhana dimungkinkan untuk mengunggah semua sumber daya (file JSON, file ZIP dan file aset) ke repositori jarak jauh, dan membuatnya tersedia untuk semua platform yang berbeda, untuk mengunduh dan menggunakan dalam basis kode mereka.

(Bagaimana platform yang sebenarnya mengambil dan memproses aset - melalui skrip khusus yang dibuat ad-hoc untuk tujuan ini - berada di luar cakupan artikel ini. Tetapi ini mungkin akan dibahas segera dalam posting blog khusus lainnya, oleh salah satu dari pengembang lain yang bekerja dengan saya di proyek ini).

Kesimpulan (dan pelajaran yang didapat sepanjang jalan)


Saya selalu menyukai Sketsa . Selama bertahun-tahun ini telah menjadi alat "de-facto" pilihan untuk desain web dan aplikasi (dan pengembangan). Jadi saya sangat tertarik dan ingin tahu untuk mengeksplorasi kemungkinan integrasi seperti html-sketchapp atau alat serupa, apa saja yang bisa kita gunakan dalam alur kerja dan jalur pipa kami.

Aliran (ideal) ini selalu menjadi cawan suci bagi saya ( dan banyak lainnya ):



Sketsa sebagai alat desain dapat dibayangkan sebagai kemungkinan "target" basis kode.

Tetapi saya harus mengakui bahwa saya baru-baru ini mulai bertanya-tanya apakah Sketch masih merupakan alat yang tepat, terutama dalam konteks Sistem Desain. Jadi, saya mulai menjelajahi alat-alat baru seperti Figma , dengan API terbuka, dan Framer X , dengan integrasinya yang luar biasa dengan React, karena saya tidak melihat upaya setara dari Sketch untuk bergerak menuju integrasi dengan kode (kode apa pun itu).

Nah, proyek ini berubah pikiran. Tidak sepenuhnya, tapi pasti banyak.

Mungkin Sketch tidak secara resmi mengekspos API-nya, tetapi tentu cara mereka membangun struktur internal file-file mereka adalah semacam API "tidak resmi". Mereka bisa menggunakan nama samar, atau mengaburkan kunci dalam objek JSON; alih-alih, mereka memilih konvensi penamaan semantik yang jelas, mudah dibaca, dapat dibaca manusia. Saya tidak bisa berpikir ini hanya kebetulan.

Fakta bahwa file Sketch dapat dimanipulasi telah membuka pikiran saya berbagai kemungkinan perkembangan dan peningkatan di masa depan. Dari pengaya untuk memvalidasi penamaan, penataan, dan struktur lapisan untuk ikon, hingga kemungkinan integrasi dengan wiki kami dan dokumentasi sistem desain kami (di kedua arah), melalui pembuatan aplikasi Node yang dihosting di Electron atau Carlo untuk memfasilitasi banyak dari tugas berulang yang harus dilakukan oleh desainer.

Satu bonus tak terduga dari proyek ini (setidaknya bagi saya) adalah bahwa sekarang file Sketsa dengan "ikon Cosmos" telah menjadi "sumber kebenaran", mirip dengan apa yang terjadi dengan sistem desain Cosmos . Jika sebuah ikon tidak ada, itu tidak ada di basis kode (atau lebih baik, itu tidak seharusnya ada: tapi setidaknya kita tahu itu pengecualian). Saya tahu itu agak jelas sekarang, tetapi tidak sebelumnya, setidaknya untuk saya.

Apa yang dimulai sebagai proyek MVP, segera menjadi penyelaman mendalam (secara harfiah) ke internal file Sketch, dengan kesadaran bahwa ini dapat dimanipulasi. Kami belum tahu ke mana semua ini akan mengarah, tapi sejauh ini itu sukses. Desainer, pengembang, PM, dan pemangku kepentingan, semua sepakat bahwa ini akan menghemat banyak pekerjaan manual untuk semua orang, dan mencegah banyak kesalahan potensial. Tapi itu juga akan membuka pintu untuk penggunaan ikon-ikon yang tidak mungkin sampai sekarang.

Satu hal terakhir: apa yang saya jelaskan di posting panjang ini adalah pipa yang telah kami bangun di sini untuk menyelesaikan masalah khusus kami , dan itu tentu sangat disesuaikan untuk konteks kami . Ingatlah bahwa itu mungkin tidak sesuai dengan kebutuhan bisnis Anda atau sesuai untuk konteks Anda .

Tetapi yang penting bagi saya, dan apa yang ingin saya bagikan, adalah hal itu bisa dilakukan. Mungkin dengan cara yang berbeda, dengan pendekatan yang berbeda dan format keluaran yang berbeda, mungkin melibatkan kompleksitas yang lebih sedikit (yaitu: Anda mungkin tidak memerlukan multi-branding dan pengujian AB). Tapi sekarang Anda dapat mengotomatiskan alur kerja yang terlibat dalam memberikan ikon Anda dengan skrip dan Skrip Node.js khusus.

Temukan cara Anda sendiri untuk melakukannya. Sangat menyenangkan (dan relatif mudah).

Kredit


Proyek besar ini dikembangkan bekerja sama dengan Nikhil Verma (Mobile Web), yang menciptakan versi pertama skrip build, dan Artem Rudoi (Android) dan Igor Savelev (iOS), yang mengembangkan skrip yang mengimpor dan menggunakan aset di platform asli masing-masing. Terima kasih, semuanya, ini adalah ledakan yang bekerja dengan Anda dalam proyek ini dan menyaksikannya menjadi hidup.

Source: https://habr.com/ru/post/id441042/


All Articles