{"id":413269,"date":"2024-06-29T23:01:28","date_gmt":"2024-06-29T23:01:28","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=413269"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=413269","title":{"rendered":"<span>How I create browser applications inside browsers<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/3d\/4k\/ce\/3d4kcehnig2uoe5iikktmumkzji.jpeg\" alt=\"GitJS\" data-src=\"https:\/\/habrastorage.org\/webt\/3d\/4k\/ce\/3d4kcehnig2uoe5iikktmumkzji.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>In 2013 Canonical <a href=\"https:\/\/techcrunch.com\/2013\/08\/22\/edge-crowdfunding-fail\" rel=\"nofollow noopener noreferrer\">tried to crowdfund Ubuntu Edge smartphone<\/a>. Its main feature could be the ability to use the smartphone as a full-fledged P\u0421. Unfortunatly, the crowdfunding campaign did not accumulate enough money, so a dream of having a universal device remained to be the dream.<\/p>\n<p>  <\/p>\n<p>I&#8217;ve been searching for universality, too, on the software side, not the hardware one. Today I can confidently say I found the necessary combination: Git and JavaScript.<\/p>\n<p>  <\/p>\n<p>As you know, I have already described the benefits of browser applications (<a href=\"https:\/\/habr.com\/ru\/post\/462693\">nCKOB<\/a> static site generator) and the benefits of using Git instead of yet another back-end with API (<a href=\"https:\/\/habr.com\/ru\/post\/500236\">GitBudget<\/a> to track personal spendings). Once GitBudget was out, I spent the remaining 2020 to build a system allowing one to create browser applications right inside browsers. GitJS is the name of that system.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h1 id=\"gitjs\">GitJS<\/h1>\n<p>  <\/p>\n<p>The system uses Git for:<\/p>\n<p>  <\/p>\n<ul>\n<li>long-term data storage <strong>outside<\/strong> of device;<\/li>\n<li>talking to the outside world;<\/li>\n<li>delivering the application to a device over HTTP.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>Thus, Git is not used for version control, Git is merely a widespread technology to keep data with read (HTTP) and write permissions. This might be somewhat counterintuitive. However, this allows everyone to decide where and how to keep data: paid\/free, locally\/remotely.<\/p>\n<p>  <\/p>\n<p>You might argue that FTP\/rsync could be used instead of Git if we only need to keep data. However, there are no widespread services like SourceForge\/GitHub\/BitBucket\/GitLab for FTP\/rsync. Also, there are no implementations of FTP\/rsync that work inside browsers, and Git has <a href=\"https:\/\/isomorphic-git.org\" rel=\"nofollow noopener noreferrer\">Isomorphic-Git<\/a>.<\/p>\n<p>  <\/p>\n<p>JS (alongside HTML\/CSS) is used for:<\/p>\n<p>  <\/p>\n<ul>\n<li>user interface;<\/li>\n<li>logic;<\/li>\n<li>long-term data storage <strong>on<\/strong> device.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>GitJS consists of the following three mandatory parts (in the order of execution):<\/p>\n<p>  <\/p>\n<ol>\n<li><a href=\"https:\/\/gitlab.com\/gitjs\/gitjs.gitlab.io\/-\/blob\/master\/index.html\" rel=\"nofollow noopener noreferrer\">HTML page<\/a><br \/> \n<ul>\n<li>introduces GitJS rules<\/li>\n<li>has a tiny size to work for slow connections<\/li>\n<li>is requested\/delivered each time the page is completely refreshed<\/li>\n<li>may be hosted locally to work without the Internet<\/li>\n<\/ul>\n<\/li>\n<li><a href=\"https:\/\/bitbucket.org\/gitjs\/0000\/src\/master\/0000.js\" rel=\"nofollow noopener noreferrer\">GitJS rules<\/a><br \/> \n<ul>\n<li>are essentially a chunk of JS code<\/li>\n<li>introduce the concept of modules and their loading, saving, execution<\/li>\n<li>introduce the concept of sequences: a way to structure source code in a reactive-event-based manner<\/li>\n<li>are requested\/delivered by HTML page only if they are absent or need an update<\/li>\n<li>are saved by HTML page into LocalStorage to start faster next time<\/li>\n<\/ul>\n<\/li>\n<li><a href=\"https:\/\/git.opengamestudio.org\/kornerr\/nPOBEPuTb-JSZip\" rel=\"nofollow noopener noreferrer\">Startup module<\/a><br \/> \n<ul>\n<li>is located in the address string after <code>?<\/code> symbol<\/li>\n<li>is executed after the loading of GitJS rules<\/li>\n<li>does whatever is necessary, e.g., introduces dependent modules to be loaded before the main application should start<\/li>\n<li>the linked example depicts JSZip library test<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>  <\/p>\n<p>Startup module may introduce absolutely any additional rules to GitJS ones or even replace them, so your fantasy here is only limited by what browsers permit: e.g., you can&#8217;t erase all hard drive files of a user.<\/p>\n<p>  <\/p>\n<p>I&#8217;d like to stress that having an HTML page and Git web service locally lets you use GitJS without the Internet.<\/p>\n<p>  <\/p>\n<h1 id=\"gitjs-application-1-editor-of-gitjs-modules\">GitJS application \u21161: editor of GitJS modules<\/h1>\n<p>  <\/p>\n<p>Currently, the editor has very basic functionality:<\/p>\n<p>  <\/p>\n<p><strong>1.1. Editing of module&#8217;s text files<\/strong><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/hd\/4z\/lc\/hd4zlc9rikkl7r5ogiu1v34wa1w.png\" data-src=\"https:\/\/habrastorage.org\/webt\/hd\/4z\/lc\/hd4zlc9rikkl7r5ogiu1v34wa1w.png\"\/><\/p>\n<p>  <\/p>\n<p><strong>1.2. Publishing changes to Git<\/strong><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/du\/cj\/p_\/ducjp_yluecjroanxpvl_uc7deu.png\" data-src=\"https:\/\/habrastorage.org\/webt\/du\/cj\/p_\/ducjp_yluecjroanxpvl_uc7deu.png\"\/><\/p>\n<p>  <\/p>\n<p><strong>Note<\/strong>: browsers keep passwords.<\/p>\n<p>  <\/p>\n<p><strong>1.3. Editing the structure of a module<\/strong><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/7u\/lz\/xu\/7ulzxuu3ksw4ynyr-he3go-wd9k.png\" data-src=\"https:\/\/habrastorage.org\/webt\/7u\/lz\/xu\/7ulzxuu3ksw4ynyr-he3go-wd9k.png\"\/><\/p>\n<p>  <\/p>\n<p><strong>1.4. Opening previously loaded modules from LocalStorage\/IndexedDB<\/strong><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/th\/dy\/a2\/thdya2wvawtczzvft5o8bzbjxy4.png\" data-src=\"https:\/\/habrastorage.org\/webt\/th\/dy\/a2\/thdya2wvawtczzvft5o8bzbjxy4.png\"\/><\/p>\n<p>  <\/p>\n<p><strong>1.5. Saving changes locally into LocalStorage\/IndexedDB<\/strong><\/p>\n<p>  <\/p>\n<p>Here&#8217;s the editor&#8217;s <a href=\"http:\/\/gitjs.org\/%F0%9F%93%A6\" rel=\"nofollow noopener noreferrer\">last version<\/a>. The first run takes some time, be patient.<\/p>\n<p>  <\/p>\n<h1 id=\"gitjs-application-2-mahjong-solitaire\">GitJS application \u21162: Mahjong solitaire<\/h1>\n<p>  <\/p>\n<p>Currently, the game has the following functionality:<\/p>\n<p>  <\/p>\n<p><strong>2.1. Selection and removal of tiles off the field according to Mahjong solitaire rules<\/strong><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/iw\/du\/ym\/iwduym-yi84my86cc9yx9ff6jn0.png\" data-src=\"https:\/\/habrastorage.org\/webt\/iw\/du\/ym\/iwduym-yi84my86cc9yx9ff6jn0.png\"\/><\/p>\n<p>  <\/p>\n<p><strong>2.2. Tile theme selection<\/strong><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/nh\/sk\/ry\/nhskryxodniavajdibk62etvj9y.png\" data-src=\"https:\/\/habrastorage.org\/webt\/nh\/sk\/ry\/nhskryxodniavajdibk62etvj9y.png\"\/><\/p>\n<p>  <\/p>\n<p><strong>2.3. Field layout selection<\/strong><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/da\/a0\/yl\/daa0yltxvhbwl9gmkd1jilg-peg.png\" data-src=\"https:\/\/habrastorage.org\/webt\/da\/a0\/yl\/daa0yltxvhbwl9gmkd1jilg-peg.png\"\/><\/p>\n<p>  <\/p>\n<p><strong>2.4. Victory\/loss detection<\/strong><\/p>\n<p>  <\/p>\n<p>Here&#8217;s the game&#8217;s <a href=\"http:\/\/gitjs.org\/%F0%9F%80%84\/1.0.14\" rel=\"nofollow noopener noreferrer\">last version<\/a>.<\/p>\n<p>  <\/p>\n<p>In the end, this game will match the original <a href=\"http:\/\/opengamestudio.org\/en\/game\/ogs-mahjong-1.html\" rel=\"nofollow noopener noreferrer\">Mahjong<\/a> (released several years ago) in terms of features.<\/p>\n<p>  <\/p>\n<h1 id=\"limitations\">Limitations<\/h1>\n<p>  <\/p>\n<p>GitJS limitations stem from browser ones.<\/p>\n<p>  <\/p>\n<p><strong>1. CORS<\/strong><\/p>\n<p>  <\/p>\n<p>To be able to publish changes to Git, we have to meet CORS restrictions. Currently, major services <a href=\"https:\/\/github.com\/isomorphic-git\/isomorphic-git#cors-support\" rel=\"nofollow noopener noreferrer\">do not allow to publish Git changes easily<\/a>, so one would have to use either a proxy, or a personal Git service.<\/p>\n<p>  <\/p>\n<p><strong>2. Full-screen surfing on mobile<\/strong><\/p>\n<p>  <\/p>\n<p>Nowadays, browsers collapse navigation and other controls when you scroll a page that doesn&#8217;t fit into available space. This leaves the space at the top and the bottom of the screen free of controls but still unusable for touches because these touches bring those controls back. Such behaviour is very inconvenient for games.<\/p>\n<p>  <\/p>\n<p>Mahjong solitaire works around that problem by supporting portrait mode: you can shift the field left\/right. However, such a solution has its own drawbacks: one cannot see the field at a single glance, which makes the game harder to play.<\/p>\n<p>  <\/p>\n<h1 id=\"plans\">Plans<\/h1>\n<p>  <\/p>\n<p><a href=\"http:\/\/opengamestudio.org\/en\/news\/on-the-way-to-durable-applications.html\" rel=\"nofollow noopener noreferrer\">nCKOB<\/a> mentioned earlier will be rewritten as GitJS application. This would allow anyone to create statically generated sites without leaving a browser. We&#8217;ll see how this goes.<\/p>\n<p>  <\/p>\n<p>PS: The first image is &#171;Bayan&#187; picture created by Viktor Vasnetsov in 1910.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/539836\/\"> https:\/\/habr.com\/ru\/articles\/539836\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/3d\/4k\/ce\/3d4kcehnig2uoe5iikktmumkzji.jpeg\" alt=\"GitJS\" data-src=\"https:\/\/habrastorage.org\/webt\/3d\/4k\/ce\/3d4kcehnig2uoe5iikktmumkzji.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>In 2013 Canonical <a href=\"https:\/\/techcrunch.com\/2013\/08\/22\/edge-crowdfunding-fail\" rel=\"nofollow noopener noreferrer\">tried to crowdfund Ubuntu Edge smartphone<\/a>. Its main feature could be the ability to use the smartphone as a full-fledged P\u0421. Unfortunatly, the crowdfunding campaign did not accumulate enough money, so a dream of having a universal device remained to be the dream.<\/p>\n<p>  <\/p>\n<p>I&#8217;ve been searching for universality, too, on the software side, not the hardware one. Today I can confidently say I found the necessary combination: Git and JavaScript.<\/p>\n<p>  <\/p>\n<p>As you know, I have already described the benefits of browser applications (<a href=\"https:\/\/habr.com\/ru\/post\/462693\">nCKOB<\/a> static site generator) and the benefits of using Git instead of yet another back-end with API (<a href=\"https:\/\/habr.com\/ru\/post\/500236\">GitBudget<\/a> to track personal spendings). Once GitBudget was out, I spent the remaining 2020 to build a system allowing one to create browser applications right inside browsers. GitJS is the name of that system.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-413269","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/413269","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=413269"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/413269\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=413269"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=413269"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=413269"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}