Πώς να δημιουργήσετε μια εφαρμογή ηλεκτρονικής επιφάνειας εργασίας σε JavaScript: Multithreading, SQLite, Native Modules και άλλα κοινά σημεία πόνου

Ως πλαίσιο για την ανάπτυξη εφαρμογών για επιτραπέζιους υπολογιστές, η Electron έχει πολλά να προσφέρει. Παρέχει πλήρη πρόσβαση στο API του Node και στην οικοσφαίρα. Εφαρμόζεται σε όλα τα μεγάλα λειτουργικά συστήματα (με μία βάση κώδικα). Και με την αρχιτεκτονική που βασίζεται στον Ιστό, μπορείτε να χρησιμοποιήσετε τις πιο πρόσφατες δυνατότητες του CSS για να δημιουργήσετε προηγμένες διεπαφές χρήστη.

Υπάρχουν πολλά άρθρα που αφορούν την ενεργοποίηση και την εκτέλεση του Electron, αλλά λιγότερα αφιερωμένα στη χρήση του SQLite ή στον τρόπο αντιμετώπισης των πολλαπλών νημάτων. Θα δούμε πώς να χρησιμοποιούμε το Electron για τη δημιουργία εφαρμογών που χειρίζονται μεγάλες ποσότητες δεδομένων ή εκτελούν πολλές εργασίες.

Συγκεκριμένα, θα καλύψουμε:

  • Πώς λειτουργεί το Electron (εν συντομία) και πώς η αρχιτεκτονική του επηρεάζει αυτό που μπορούμε να κάνουμε
  • Πολλαπλών νημάτων
  • Χρήση τοπικών βάσεων δεδομένων όπως SQLite ή εγγραφή σε οποιοδήποτε αρχείο μέσα σε μια εφαρμογή Electron
  • Εγγενείς ενότητες
  • Μερικά gotchas που πρέπει να γνωρίζετε
  • Συσκευασία μιας εφαρμογής χρησιμοποιώντας εγγενείς λειτουργικές μονάδες

Πώς λειτουργεί το Electron - συνοπτικά

Αξίζει να επαναλάβετε τις βασικές αρχές πίσω από την αρχιτεκτονική της Electron. Μια εφαρμογή ηλεκτρονίων αποτελείται από τουλάχιστον δύο διαδικασίες. Το κύριο νήμα είναι η είσοδος στην εφαρμογή σας και κάνει όλη την απαραίτητη εργασία για να δείξει τη διαδικασία απόδοσης (ή τις διαδικασίες) στους χρήστες σας. Μπορεί να υπάρχει μόνο μία παρουσία της κύριας διαδικασίας.

Οι διαδικασίες απόδοσης χρησιμοποιούν το Chromium για την απόδοση της εφαρμογής σας. Ακριβώς όπως κάθε καρτέλα τρέχει στη δική της διαδικασία, το ίδιο ισχύει και για κάθε απόδοση. Φορτώνονται χρησιμοποιώντας τη μέθοδο loadURL του κατασκευαστή BrowserWindow, η οποία πρέπει να οδηγεί σε ένα τοπικό ή απομακρυσμένο αρχείο HTML. Αυτό σημαίνει ότι ο μόνος τρόπος για να ξεκινήσετε μια διαδικασία απόδοσης είναι να χρησιμοποιήσετε ένα αρχείο HTML ως καταχώριση.

Προειδοποιήσεις της αρχιτεκτονικής του Electron

Η απλότητα του Electron είναι ένα από τα μεγαλύτερα πλεονεκτήματά της. Η κύρια διαδικασία σας κάνει οποιαδήποτε διαμόρφωση είναι απαραίτητη και στη συνέχεια μεταβιβάζει ένα αρχείο HTML ή μια διεύθυνση URL στη διαδικασία απόδοσης. Αυτό το αρχείο μπορεί να κάνει οτιδήποτε μπορεί να κάνει μια κανονική εφαρμογή ιστού - και μπορείτε να πάτε από εκεί.

Όμως, το γεγονός ότι μπορεί να υπάρξει μόνο μία κύρια διαδικασία καθιστά ασαφές τον τρόπο εφαρμογής του multithreading. Η τεκμηρίωση της Electron υποδηλώνει ότι οι διεργασίες απόδοσης είναι αυστηρά σχεδιασμένες για το έργο της απόδοσης διεπαφών χρήστη (που όπως θα δούμε, δεν είναι αληθές)

Είναι σημαντικό να γνωρίζετε ότι κάνοντας οτιδήποτε υπολογιστικά εντατικό στην κύρια διαδικασία θα επιβραδύνει (ή παγώσει) τις διαδικασίες απόδοσης. Είναι ζωτικής σημασίας κάθε εργασία εντατικής εργασίας να απομακρυνθεί από το κύριο νήμα. Είναι καλύτερο να το αφήσετε αποκλειστικά στο καθήκον να κάνετε ό, τι είναι απαραίτητο για να ξεκινήσετε τις διαδικασίες απόδοσης. Δεδομένου ότι δεν μπορούμε να κάνουμε εντατική εργασία στην ίδια διαδικασία απόδοσης που αποδίδει το frontend της εφαρμογής (καθώς αυτό θα επηρεάσει επίσης τη διεπαφή χρήστη), χρειαζόμαστε μια άλλη προσέγγιση.

Πολλαπλών νημάτων

Υπάρχουν τρεις γενικές προσεγγίσεις στο multithreading στο Electron:

  • Χρησιμοποιήστε εργαζόμενους στο Διαδίκτυο
  • Περάστε νέες διαδικασίες για να εκτελέσετε εργασίες
  • Εκτελέστε (κρυφές) διαδικασίες απόδοσης ως εργαζόμενοι

Εργαζόμενοι στο Διαδίκτυο

Δεδομένου ότι το Electron είναι ενσωματωμένο στο Chromium, οτιδήποτε μπορεί να γίνει σε ένα πρόγραμμα περιήγησης μπορεί να γίνει σε μια διαδικασία απόδοσης. Αυτό σημαίνει ότι μπορείτε να χρησιμοποιήσετε εργαζόμενους στο Διαδίκτυο για την εκτέλεση εντατικών εργασιών σε ξεχωριστά θέματα. Το πλεονέκτημα αυτής της προσέγγισης είναι η απλότητα και η διατήρηση του ισομορφισμού με μια διαδικτυακή εφαρμογή.

Ωστόσο, υπάρχει μια πολύ μεγάλη προειδοποίηση - δεν μπορείτε να χρησιμοποιήσετε εγγενείς ενότητες. Από τεχνική άποψη μπορείτε, αλλά κάτι τέτοιο θα προκαλέσει σφάλμα στην εφαρμογή σας. Αυτό είναι ένα σημαντικό πρόβλημα, καθώς κάθε εφαρμογή που χρειάζεται multithreading μπορεί επίσης να χρειαστεί να χρησιμοποιεί εγγενείς λειτουργικές μονάδες (όπως node-sqlite3).

Δίπλα στις νέες διαδικασίες

Το Electron χρησιμοποιεί το Node ως χρόνο εκτέλεσης, που σημαίνει ότι έχετε πλήρη πρόσβαση σε ενσωματωμένες λειτουργικές μονάδες όπως το σύμπλεγμα. Οι νέες διαδικασίες μπορούν να διαμορφωθούν για να εκτελέσουν εργασίες, διατηρώντας εντατική εργασία από το κύριο νήμα.

Το κύριο ζήτημα είναι ότι, σε αντίθεση με τις διεργασίες απόδοσης, οι θυγατρικές διαδικασίες δεν μπορούν να χρησιμοποιούν μεθόδους από τη βιβλιοθήκη Electron. Αυτό σας αναγκάζει να διατηρήσετε ένα κανάλι επικοινωνίας με την κύρια διαδικασία μέσω IPC. Οι διεργασίες απόδοσης μπορούν να χρησιμοποιήσουν την απομακρυσμένη λειτουργική μονάδα για να καθορίσουν ότι η κύρια διαδικασία θα κάνει εργασίες μόνο για αυτό χωρίς αυτό το επιπλέον βήμα.

Ένα άλλο ζήτημα είναι ότι εάν χρησιμοποιείτε λειτουργικές μονάδες ES ή λειτουργίες TC39 του JavaScript, θα πρέπει να διασφαλίσετε ότι εκτελείτε μεταφρασμένες εκδόσεις των σεναρίων σας. Θα πρέπει επίσης να τα συμπεριλάβετε στη συσκευασμένη εφαρμογή σας. Αυτό το ζήτημα επηρεάζει οποιαδήποτε εφαρμογή κόμβου που διχάζει τις διαδικασίες, αλλά προσθέτει ένα άλλο επίπεδο πολυπλοκότητας στη διαδικασία δημιουργίας σας. Μπορεί επίσης να γίνει δύσκολο κατά την εξισορρόπηση των απαιτήσεων συσκευασίας της εφαρμογής σας με τη χρήση εργαλείων ανάπτυξης που χρησιμοποιούν χαρακτηριστικά όπως η ζωντανή επαναφόρτωση.

Χρήση διεργασιών απόδοσης ως νήματα εργαζομένων

Οι διαδικασίες απόδοσης αντιμετωπίζονται συμβατικά ως χρησιμοποιούνται για την απόδοση της διεπαφής χρήστη. Ωστόσο, δεν δεσμεύονται σε αυτό το μοναδικό καθήκον. Μπορούν να κρυφτούν και να εκτελεστούν στο παρασκήνιο διαμορφώνοντας τη σημαία εκπομπής που μεταβιβάστηκε στο BrowserWindow.

Κάτι τέτοιο έχει πολλά πλεονεκτήματα. Σε αντίθεση με τους εργαζόμενους στο Διαδίκτυο, έχετε την ελευθερία να χρησιμοποιείτε εγγενείς ενότητες. Και σε αντίθεση με τις διχαλωτές διεργασίες, μπορείτε ακόμα να χρησιμοποιήσετε τη βιβλιοθήκη ηλεκτρονίων για να πείτε στην κύρια διαδικασία να κάνετε πράγματα όπως άνοιγμα διαλόγου ή δημιουργία ειδοποιήσεων λειτουργικού συστήματος.

Μία πρόκληση κατά τη χρήση του Electron είναι το IPC. Παρόλο που είναι απλό, απαιτεί μεγάλη ποσότητα πλάκας boiler και επιβάλλει τη δυσκολία εντοπισμού σφαλμάτων μεγάλου αριθμού ακροατών συμβάντων. Είναι επίσης ένα άλλο πράγμα που πρέπει να κάνετε στο τεστ μονάδας. Χρησιμοποιώντας μια διαδικασία απόδοσης ως νήμα εργαζομένων, μπορείτε να το παρακάμψετε εντελώς. Όπως θα κάνατε με έναν διακομιστή, μπορείτε να ακούσετε σε μια τοπική θύρα και να λάβετε αιτήματα, δίνοντάς σας τη δυνατότητα να χρησιμοποιήσετε εργαλεία όπως το GraphQL + React Apollo. Μπορείτε επίσης να χρησιμοποιήσετε διαδικτυακές υποδοχές για επικοινωνία σε πραγματικό χρόνο. Ένα άλλο μπόνους είναι ότι δεν χρειάζεται να χρησιμοποιήσετε το ipcRenderer και μπορείτε να διατηρήσετε τις ηλεκτρονικές και διαδικτυακές εφαρμογές σας ισόμορφες (εάν θέλετε να χρησιμοποιήσετε μια κοινόχρηστη βάση κώδικα για μια εφαρμογή επιτραπέζιου υπολογιστή και ιστού).

Για προχωρημένες περιπτώσεις χρήσης, αυτή η προσέγγιση μπορεί να συνδυαστεί με ομαδοποίηση για να έχετε το καλύτερο όλων των κόσμων. Το μόνο μειονέκτημα είναι ότι θα πρέπει να καταχωρίσετε ένα αρχείο HTML ως την καταχώριση για τις διεργασίες απόδοσης εργαζομένου (το οποίο μοιάζει με κάποιο hack).

Πώς να χρησιμοποιήσετε το SQLite (ή οτιδήποτε χρειάζεστε για να γράψετε)

Υπάρχουν αρκετές προσεγγίσεις στη διαχείριση της κατάστασης που δεν απαιτούν εγγενείς ενότητες. Για παράδειγμα, ο χειρισμός όλης της κατάστασής σας στο πλαίσιο ενός προγράμματος απόδοσης με το Redux.

Ωστόσο, εάν πρέπει να χειριστείτε μεγάλες ποσότητες δεδομένων, αυτό δεν θα αρκεί. Συγκεκριμένα, θα δούμε πώς να χρησιμοποιούμε το SQLite σε μια εφαρμογή ηλεκτρονίων.

Για να αναπτύξετε την εφαρμογή σας Electron, θα πρέπει πρώτα να τη συσκευάσετε. Υπάρχουν πολλά διαθέσιμα εργαλεία για να γίνει αυτό - το πιο δημοφιλές είναι το Electron Builder. Το Electron χρησιμοποιεί τη μορφή αρχείου ASAR για τη δέσμευση της εφαρμογής σας σε ένα μόνο, μη συμπιεσμένο αρχείο. Τα αρχεία ASAR είναι μόνο για ανάγνωση - που σημαίνει ότι δεν μπορείτε να γράψετε δεδομένα σε αυτά. Αυτό σημαίνει ότι δεν μπορείτε να συμπεριλάβετε τη βάση δεδομένων σας στο αρχείο ASAR μαζί με τον υπόλοιπο κωδικό σας (στο ηλεκτρονικό πρόγραμμα δημιουργίας, αυτό θα βρίσκεται κάτω από τα "αρχεία").

Αντ 'αυτού, συμπεριλάβετε τη βάση δεδομένων σας στον κατάλογο πόρων του πακέτου ηλεκτρονίων σας. Η δομή αρχείων μιας συσκευασμένης εφαρμογής ηλεκτρονίων και πού να τοποθετήσετε τη βάση δεδομένων σας μπορεί να δει παρακάτω:

Το πακέτο ASAR που ονομάζεται app.asar υπάρχει στο ./Contents/Resources. Μπορείτε να τοποθετήσετε τη βάση δεδομένων σας ή οποιοδήποτε αρχείο θέλετε να γράψετε, αλλά να συμπεριλάβετε στη συσκευασμένη εφαρμογή σας, στον ίδιο κατάλογο. Αυτό μπορεί να επιτευχθεί με το Electron Builder χρησιμοποιώντας τη διαμόρφωση "extraResources".

Μια άλλη προσέγγιση είναι η δημιουργία μιας βάσης δεδομένων σε άλλο κατάλογο εντελώς. Ωστόσο, θα πρέπει να λάβετε υπόψη τη διαγραφή αυτού του αρχείου σε όλες τις πλατφόρμες εάν οι χρήστες αποφασίσουν να απεγκαταστήσουν την εφαρμογή σας.

Συσκευασία με εγγενείς ενότητες

Η συντριπτική πλειονότητα των ενοτήτων Node είναι σενάρια γραμμένα σε JavaScript. Οι εγγενείς ενότητες είναι λειτουργικές μονάδες γραμμένες σε C ++ και έχουν συνδέσεις για χρήση με τον κόμβο. Λειτουργούν ως διασύνδεση με άλλες βιβλιοθήκες που γράφονται στο C / C ++ και συνήθως διαμορφώνονται για μεταγλώττιση μετά την εγκατάσταση.

Ως μονάδες χαμηλού επιπέδου, πρέπει να καταρτιστούν για αρχιτεκτονικές στόχους και λειτουργικά συστήματα. Μια εγγενής λειτουργική μονάδα που έχει συνταχθεί σε υπολογιστή Windows δεν θα λειτουργεί σε υπολογιστή Linux - παρόλο που μια κανονική λειτουργική μονάδα θα λειτουργούσε. Αυτό είναι ένα πρόβλημα για το Electron, καθώς τελικά πρέπει να συσκευάσουμε τα πάντα σε εκτελέσιμα .dmg (OSX), .exe (Windows) ή .deb (Linux).

Οι εφαρμογές ηλεκτρονίων που χρησιμοποιούν εγγενείς μονάδες πρέπει να συσκευάζονται στο σύστημα στο οποίο στοχεύουν. Δεδομένου ότι θέλετε να αυτοματοποιήσετε αυτήν τη διαδικασία σε έναν αγωγό CI / CD, θα χρειαστεί να δημιουργήσετε τις εγγενείς εξαρτήσεις σας πριν από τη συσκευασία. Για να το επιτύχετε αυτό, μπορείτε να χρησιμοποιήσετε ένα εργαλείο που αναπτύχθηκε από την ομάδα Electron που ονομάζεται electron-rebuild.

Εάν αναπτύσσετε ένα μη εμπορικό έργο ανοιχτού κώδικα, μπορείτε να χρησιμοποιήσετε το TravisCI (Linux, OSX) και το Appveyor (Windows) για αυτόματη δημιουργία, δοκιμή και ανάπτυξη της εφαρμογής σας δωρεάν.

Η ρύθμιση για αυτό μπορεί να είναι δύσκολη αν έχετε δοκιμές ενσωμάτωσης, καθώς θα χρειαστεί να εγκαταστήσετε ορισμένες εξαρτήσεις για να λειτουργούν οι δοκιμές χωρίς κεφαλή. Ένα παράδειγμα config για OSX και Linux με TravisCI μπορεί να βρεθεί εδώ και ένα παράδειγμα Appveyor config εδώ (αυτά τα παραδείγματα βασίζονται στη διαμόρφωση στο έργο electron-react-boilerplate, με την προσθήκη OSX και ανάπτυξης).

Γκότσα

Όταν η εφαρμογή Electron είναι συσκευασμένη, ορισμένες ενσωματωμένες ιδιότητες του κόμβου που σχετίζονται με διαδρομές ενδέχεται να μην συμπεριφέρονται όπως θα περίμενε κανείς και δεν θα συμπεριφερθούν όπως κάνουν όταν εκτελείτε το προκαθορισμένο δυαδικό για την εξυπηρέτηση της εφαρμογής σας.

Μεταβλητές όπως __dirname, __filename και μέθοδοι όπως το process.cwd δεν θα συμπεριφέρονται όπως αναμένεται σε μια συσκευασμένη εφαρμογή (δείτε ζητήματα εδώ, εδώ και εδώ). Χρησιμοποιήστε το app.getAppPath.

Μια τελευταία σημείωση για τη συσκευασία

Κατά την ανάπτυξη μιας εφαρμογής Electron, ίσως θελήσετε να χρησιμοποιήσετε τις λειτουργίες παραγωγής (εξυπηρετώντας πακέτο κώδικα με το προκαθορισμένο δυαδικό) και ανάπτυξης (χρησιμοποιώντας webpack-dev-server ή webpack-serve για παρακολούθηση των αρχείων σας).

Για να διατηρήσετε τη λογική σας, δημιουργήστε και εξυπηρετήστε τις δέσμες σας από τον ίδιο κατάλογο με τον πηγαίο κώδικα. Αυτό σημαίνει ότι όταν επιλέγετε αυτά τα αρχεία για συσκευασία, τυχόν παραδοχές διαδρομής αρχείου παραμένουν συνεπείς σε όλες αυτές τις λειτουργίες και το πακέτο σας.

Τουλάχιστον, η κύρια διαδικασία σας θα πρέπει να οδηγεί στο μονοπάτι του αρχείου HTML των διεργασιών απόδοσης. Εάν μετακινήσετε αυτό το αρχείο σε έναν άλλο κατάλογο ως μέρος της διαδικασίας κατασκευής, θα αναγκαστείτε να διατηρήσετε τις παραδοχές της δομής αρχείων και αυτό μπορεί γρήγορα να γίνει ένα άλλο φορολογικό επίπεδο επιπλοκών που πρέπει να διατηρήσετε.

Τα ζητήματα εντοπισμού σφαλμάτων που σχετίζονται με λανθασμένα μονοπάτια αρχείων σε μια συσκευασμένη εφαρμογή αποτελούν πολύ μεγάλη περίπτωση δοκιμής και σφάλματος.

Περίληψη

Υπάρχουν πολλές προσεγγίσεις στο multithreading στο Electron. Οι εργαζόμενοι στο Διαδίκτυο είναι βολικοί, αλλά δεν έχουν τη δυνατότητα να χρησιμοποιούν εγγενείς ενότητες. Η διαμόρφωση νέων διεργασιών λειτουργεί όπως θα συνέβαινε στον κόμβο, αλλά η έλλειψη ικανότητας χρήσης της βιβλιοθήκης ηλεκτρονίων αναγκάζει τη χρήση IPC για κοινές εργασίες και μπορεί γρήγορα να γίνει περίπλοκη. Η χρήση διεργασιών απόδοσης ως εργαζόμενοι παρέχει την πλήρη ισχύ όλων των διαθέσιμων εργαλείων διακομιστή Node ως αντικατάσταση της επικοινωνίας μέσω IPC, διατηρώντας παράλληλα την πρόσβαση σε εγγενείς λειτουργικές μονάδες και μεθόδους από τη βιβλιοθήκη απόδοσης ηλεκτρονικών.

Καθώς τα Electron πακέτα αρχείων σε αρχείο ASAR μόνο για ανάγνωση, οποιοδήποτε αρχείο στο οποίο πρέπει να γράψουμε (όπως μια βάση δεδομένων SQLite) δεν μπορεί να συμπεριληφθεί. Αντ 'αυτού, αυτά μπορούν να τοποθετηθούν στον κατάλογο πόρων όπου θα παραμείνουν στη συσκευασμένη εφαρμογή.

Τέλος, λάβετε υπόψη το γεγονός ότι σε μια συσκευασμένη εφαρμογή, ορισμένες ιδιότητες του κόμβου δεν συμπεριφέρονται όπως θα περίμενε κανείς. Και για λόγους σαφήνειας, αντιστοιχίστε τη δομή αρχείων της συσκευασμένης εφαρμογής σας με τον πηγαίο κώδικα.