ไลบรารีนี้ปรับปรุงประสิทธิภาพโดยใช้ไลบรารี Kotlin/JS จากโปรแกรม Kotlin/JVM และ Kotlin/Native ทำให้การดึงโค้ดเป็นเรื่องง่ายเหมือนกับการดึงข้อมูล:
Zipline ทำงานโดยการฝังกลไก QuickJS JavaScript ไว้ในโปรแกรม Kotlin/JVM หรือ Kotlin/Native ของคุณ มันเป็นเอ็นจิ้น JavaScript ขนาดเล็กและรวดเร็วซึ่งเหมาะสำหรับการฝังในแอปพลิเคชัน
(กำลังมองหา Duktape Android อยู่ใช่ไหม?)
มาสร้างเกมตอบคำถามที่มีคำถามใหม่ๆ ทุกวัน แม้ว่าผู้ใช้ของเราจะไม่ได้อัปเดตแอปก็ตาม เรากำหนดอินเทอร์เฟซของเราใน commonMain
เพื่อให้เราสามารถเรียกมันจาก Kotlin/JVM และนำไปใช้ใน Kotlin/JS
interface TriviaService : ZiplineService {
fun games (): List < TriviaGame >
fun answer ( questionId : String , answer : String ): AnswerResult
}
ต่อไปเราจะนำไปใช้ใน jsMain
:
class RealTriviaService : TriviaService {
// ...
}
มาเชื่อมต่อการใช้งานที่ทำงานใน Kotlin/JS กับอินเทอร์เฟซที่ทำงานใน Kotlin/JVM กันดีกว่า ใน jsMain
เรากำหนดฟังก์ชันที่ส่งออกเพื่อผูกการใช้งาน:
@JsExport
fun launchZipline () {
val zipline = Zipline .get()
zipline.bind< TriviaService >( " triviaService " , RealTriviaService ())
}
ตอนนี้เราสามารถเริ่มต้นเซิร์ฟเวอร์การพัฒนาเพื่อให้บริการ JavaScript ของเรากับแอปพลิเคชันที่ทำงานอยู่ซึ่งร้องขอได้
$ ./gradlew -p samples trivia:trivia-js:serveDevelopmentZipline --info --continuous
โปรดทราบว่า Gradle นี้จะไม่มีวันถึง 100% เป็นไปตามที่คาดไว้ เราต้องการให้เซิร์ฟเวอร์การพัฒนายังคงอยู่ต่อไป โปรดทราบว่า --continuous
แฟล็กจะทริกเกอร์การคอมไพล์ใหม่ทุกครั้งที่มีการเปลี่ยนแปลงโค้ด
คุณสามารถดูรายการแอปพลิเคชันที่ให้บริการได้ที่ localhost:8080/manifest.zipline.json โดยอ้างอิงถึงโมดูลโค้ดทั้งหมดสำหรับแอปพลิเคชัน
ใน jvmMain
เราจำเป็นต้องเขียนโปรแกรมที่ดาวน์โหลดโค้ด Kotlin/JS ของเราแล้วเรียกใช้มัน เราใช้ ZiplineLoader
ซึ่งจัดการการดาวน์โหลดโค้ด การแคช และการโหลด เราสร้าง Dispatcher
เพื่อรัน Kotlin/JS นี่จะต้องเป็นโปรแกรมเลือกจ่ายงานแบบเธรดเดียว เนื่องจากแต่ละอินสแตนซ์ Zipline จะต้องถูกจำกัดไว้ที่เธรดเดียว
suspend fun launchZipline ( dispatcher : CoroutineDispatcher ): Zipline {
val manifestUrl = " http://localhost:8080/manifest.zipline.json "
val loader = ZiplineLoader (
dispatcher,
ManifestVerifier . NO_SIGNATURE_CHECKS ,
OkHttpClient (),
)
return loader.loadOnce( " trivia " , manifestUrl)
}
ตอนนี้เราสร้างและรันโปรแกรม JVM เพื่อรวบรวมทุกอย่างเข้าด้วยกัน ทำสิ่งนี้ในเทอร์มินัลแยกต่างหากจากเซิร์ฟเวอร์การพัฒนา!
$ ./gradlew -p samples trivia:trivia-host:shadowJar
java -jar samples/trivia/trivia-host/build/libs/trivia-host-all.jar
Zipline ทำให้การแชร์อินเทอร์เฟซกับ Kotlin/JS เป็นเรื่องง่าย กำหนดอินเทอร์เฟซใน commonMain
นำไปใช้ใน Kotlin/JS และเรียกใช้จากแพลตฟอร์มโฮสต์ หรือทำตรงกันข้าม: ติดตั้งบนแพลตฟอร์มโฮสต์แล้วเรียกจาก Kotlin/JS
อินเทอร์เฟซแบบบริดจ์จะต้องขยาย ZiplineService
ซึ่งกำหนดเมธอด close()
เดียวเพื่อปล่อยทรัพยากรที่เก็บไว้
ตามค่าเริ่มต้น อาร์กิวเมนต์และค่าที่ส่งคืนจะเป็นค่าที่ส่งผ่าน Zipline ใช้ kotlinx.serialization เพื่อเข้ารหัสและถอดรหัสค่าที่ส่งข้ามขอบเขต
ประเภทอินเทอร์เฟซที่ขยายจาก ZiplineService
เป็นแบบอ้างอิงผ่าน: ผู้รับอาจเรียกใช้เมธอดบนอินสแตนซ์ที่ใช้งานจริง
ฟังก์ชั่นอินเทอร์เฟซอาจถูกระงับ Zipline ภายในใช้ setTimeout()
เพื่อให้โค้ดอะซิงโครนัสทำงานได้ตามที่ควรจะเป็นใน Kotlin/JS
Zipline ยังรองรับ Flow<T>
เป็นพารามิเตอร์หรือประเภทส่งคืน ทำให้ง่ายต่อการสร้างระบบปฏิกิริยา
ปัญหาคอขวดที่อาจเกิดขึ้นของการฝัง JavaScript กำลังรอให้เอ็นจิ้นรวบรวมซอร์สโค้ดอินพุต Zipline คอมไพล์ JavaScript ล่วงหน้าเป็นโค้ดไบต์ QuickJS ที่มีประสิทธิภาพเพื่อกำจัดผลกระทบด้านประสิทธิภาพนี้
คอขวดอื่นกำลังรอโค้ดเพื่อดาวน์โหลด Zipline แก้ไขปัญหานี้ด้วยการรองรับแอปพลิเคชันแบบโมดูลาร์ แต่ละโมดูลอินพุต (เช่นเดียวกับไลบรารีมาตรฐาน, การทำให้เป็นอนุกรม และ coroutines ของ Kotlin) จะถูกดาวน์โหลดพร้อมกัน แต่ละโมดูลที่ดาวน์โหลดจะถูกแคชไว้ นอกจากนี้ยังสามารถฝังโมดูลเข้ากับแอปพลิเคชันโฮสต์เพื่อหลีกเลี่ยงการดาวน์โหลดใดๆ หากไม่สามารถเข้าถึงเครือข่ายได้ หากโมดูลแอปพลิเคชันของคุณเปลี่ยนแปลงบ่อยกว่าไลบรารีของคุณ ผู้ใช้จะดาวน์โหลดเฉพาะสิ่งที่เปลี่ยนแปลงเท่านั้น
หากคุณประสบปัญหาด้านประสิทธิภาพในรันไทม์ QuickJS ทาง Zipline จะรวมตัวสร้างโปรไฟล์ตัวอย่างไว้ด้วย คุณสามารถใช้สิ่งนี้เพื่อดูรายละเอียดว่าแอปพลิเคชันของคุณใช้เวลา CPU อย่างไร
Zipline ใช้ console.log
โดยการส่งต่อข้อความไปยังแพลตฟอร์มโฮสต์ โดยจะใช้ android.util.Log
บน Android, java.util.logging
บน JVM และ stdout
บน Kotlin/Native
Zipline รวมแผนที่ต้นฉบับ Kotlin เข้ากับรหัสไบต์ QuickJS หากกระบวนการของคุณล้มเหลว stacktrace จะพิมพ์ไฟล์ .kt
และหมายเลขบรรทัด แม้ว่าจะมี JavaScript อยู่ข้างใต้ แต่นักพัฒนาก็ไม่จำเป็นต้องเชื่อมต่อกับไฟล์ .js
หลังจากใช้อินเทอร์เฟซแบบบริดจ์แล้ว จะต้องปิดเพื่อให้สามารถรวบรวมออบเจ็กต์เพียร์ได้ นี่เป็นเรื่องยากที่จะแก้ไขให้ถูกต้อง ดังนั้น Zipline จึงยืมแนวคิดจาก LeakCanary และตรวจจับอย่างจริงจังเมื่อไม่ได้รับสาย close()
Zipline รองรับลายเซ็น EdDSA Ed25519 และ ECDSA P-256 เพื่อตรวจสอบสิทธิ์ไลบรารีที่ดาวน์โหลด
การตั้งค่าตรงไปตรงมา สร้างคู่คีย์ EdDSA งานสำหรับสิ่งนี้ได้รับการติดตั้งด้วยปลั๊กอิน Zipline Gradle
$ ./gradlew :generateZiplineManifestKeyPairEd25519
...
---------------- ----------------------------------------------------------------
ALGORITHM: Ed25519
PUBLIC KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
PRIVATE KEY: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
---------------- ----------------------------------------------------------------
...
วางคีย์ส่วนตัวบนเซิร์ฟเวอร์บิลด์และกำหนดค่าให้ลงนามบิลด์:
zipline {
signingKeys {
create( " key1 " ) {
privateKeyHex.set( .. .)
algorithmId.set(app.cash.zipline.loader. SignatureAlgorithmId . Ed25519 )
}
}
}
ใส่กุญแจสาธารณะในแต่ละแอปพลิเคชันโฮสต์ และกำหนดค่าเพื่อตรวจสอบลายเซ็น:
val manifestVerifier = ManifestVerifier . Builder ()
.addEd25519( " key1 " , .. .)
.build()
val loader = ZiplineLoader (
manifestVerifier = manifestVerifier,
.. .
)
ทั้งการลงนามและการตรวจสอบยอมรับหลายคีย์เพื่อรองรับการหมุนเวียนคีย์
Zipline ได้รับการออกแบบมาเพื่อเรียกใช้โค้ดขององค์กรของคุณทุกที่ทุกเวลาที่คุณต้องการ ไม่มีแซนด์บ็อกซ์หรือการแยกกระบวนการ และไม่ควรใช้เพื่อรันโค้ดที่ไม่น่าเชื่อถือ
จำเป็นอย่างยิ่งที่ต้องจำไว้ว่าการออกแบบนี้ให้ความไว้วางใจโดยปริยายกับ:
ไม่ได้ป้องกันการประนีประนอมใดๆ ข้างต้น
นอกจากนี้ ยังไม่มีกลไกในการห้ามโค้ดปฏิบัติการเวอร์ชันเก่า (ลงนาม) ที่มีปัญหาที่ทราบ
มีบางสิ่งที่คุณสามารถทำได้เพื่อให้แน่ใจว่า Hot-Reload ทำงานเร็วที่สุดเท่าที่จะเป็นไปได้:
kotlin.incremental.js.ir=true
เพื่อเปิดใช้งานการคอมไพล์แบบเพิ่มหน่วยของ Kotlin/JSorg.gradle.unsafe.configuration-cache=true
เพื่อเปิดใช้งานแคชการกำหนดค่า Gradletasks.withType(DukatTask::class) { enabled = false }
เพื่อปิดงาน Dukat หากคุณไม่ได้ใช้การประกาศประเภท TypeScriptZipline ทำงานบน Android 4.3+ (API ระดับ 18+), Java 8+ และ Kotlin/Native
Zipline ใช้ API ที่ไม่เสถียรในการใช้งานและมีความละเอียดอ่อนต่อการอัปเดตเวอร์ชันสำหรับส่วนประกอบเหล่านี้
ส่วนประกอบ | เวอร์ชันที่รองรับ | หมายเหตุ |
---|---|---|
คอมไพเลอร์ Kotlin | 2.0.0 | ปลั๊กอินคอมไพเลอร์ Kotlin ยังไม่มี API ที่เสถียร |
การทำให้เป็นอนุกรม Kotlin | 1.6.3 | สำหรับ decodeFromDynamic() , encodeToDynamic() และ ContextualSerializer |
คอตลิน คูรูทีน | 1.8.1 | สำหรับ transformLatest() , Deferred.getCompleted() และ CoroutineStart.ATOMIC |
เราตั้งใจที่จะใช้ API ที่เสถียรทันทีที่พร้อมใช้งาน
เราตั้งใจที่จะให้โฮสต์ Zipline และรุ่นรันไทม์สามารถทำงานร่วมกันได้ เพื่อให้คุณสามารถอัปเกรดแต่ละรายการได้อย่างอิสระ
โฮสต์เวอร์ชัน Zipline | เวอร์ชันรันไทม์ Zipline ที่รองรับ |
---|---|
0.x | เวอร์ชัน 0.x เดียวกันกับโฮสต์ทุกประการ |
1.x | เวอร์ชัน 1.x ใดก็ได้ |
Copyright 2015 Square, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
โปรเจ็กต์นี้ก่อนหน้านี้รู้จักกันในชื่อ Duktape-Android และมาพร้อมกับเอ็นจิ้น Duktape JavaScript สำหรับ Android ประวัติ Duktape ยังคงอยู่ใน repo นี้เช่นเดียวกับแท็ก release เวอร์ชันที่มีจำหน่ายจะแสดงอยู่ใน Maven Central