В тази статия ще покажа как е възможно да се споделя един и същ код от клиентската страна в javascript и сървърната страна в pyhton.

Това е възможно благодарение на Haxe, език, който може да компилира на 8 езика (js, php, flash, python, java, c#,neko,c++).

В този пример същият шаблон се изобразява в python и javascript с Erazor, библиотека с шаблони, и страниците се обслужват с колба.

можете да намерите кода на този пример в това хранилище github https://github.com/francescoagati/isomorphic-haxe-python.

Нека видим отделните части на проекта.

build.hxml
В този файл има декларациите за целите на javascript и python, отделени от arg next.
За всяка цел има пътя до целевата папка, главния клас и библиотеките, които трябва да бъдат включени.

-js build/static/js/client.js
-main Client
-lib erazor
-dce full
-D analyzer
--next
-python build/server.py
-main Server
-lib erazor
-dce full
-D analyzer

arg dce се използва за активиране на функцията „Елиминиране на мъртвия код“ , която позволява да се елиминира кодът, който не се използва, а arg „-D анализатор“ се използва за активиране на статичен анализатор за оптимизации на кода.

article.html
Е шаблонът. Благодарение на Erazor и haxe макросите, шаблонът се преобразува в haxe код и се компилира към целевия език.

<h1>@title</h1>
<br>
<p>@body</p>

Template.hx
Класът за изобразяване на шаблона.
Анотацията includeTemplate се използва за дефиниране на пътя на шаблона.

@:includeTemplate("templates/article.html")
class Template extends erazor.macro.HtmlTemplate {
  public var title:String;
  public var body:String;
}

Server.hx
Flask се използва за обслужване на страниците.

Haxe externs се използват за картографиране на методите на Flask към клас Haxe.

Маршрутът от страната на сървъра обслужва страницата, компилирана в python, докато маршрутът от страната на клиента връща маркер на скрипт за изпълнение на javascript кода.

import haxe.Constraints.Function;
import python.KwArgs;
using python.Lib;


@:pythonImport("flask", "request")
  extern class Request implements Dynamic {
  public static var args:python.Dict<String,Dynamic>;
}


@:pythonImport("flask", "Flask")
extern class Flask {
  function new(module:String);
  function run(?opts:KwArgs<{?debug:Bool}>):Void;
  function route<T:Function>(path:String, ?opts:KwArgs<{?defaults:Dynamic}>):T->T;
}

class Server {
  public static function main() {

   var app = new Flask(untyped __name__);
   app.route("/server")(serverSide);
   app.route("/client")(clientSide);
   app.run();
  }


  static function clientSide() {
    return '
      <html>
        <body>
         <div id="content"></div>
          <script src="static/js/client.js"></script>
        </body>
      </html>

    ';
  }

  static function serverSide() {
    var template = new Template();
    template.title = "Hello from server side";
    template.body = "This content is rendered in python";
    return template.execute();
  }

}

Client.hx

Този клас изобразява шаблона за изтриване и инжектира изхода в div за съдържание.

class Client {
  public static function main() {
    var template = new Template();
    template.title="Hello for client side";
    template.body="This content is rendered in javascript";
    js.Browser.document.getElementById('content').innerHTML = template.execute();
  }
}