Mustache.js: ES-Modul-Unterstützung

Erstellt am 29. Mai 2019  ·  18Kommentare  ·  Quelle: janl/mustache.js

Hallo!

Ich habe mich gefragt, ob es einen Plan gibt, eine ES-Modulversion von Moustache.js zu unterstützen ? Wenn ja, kann ich dazu beitragen.

Wieso den?
Ich arbeite am Deno- Projekt und es gibt eine Diskussion über das Templating (Deno unterstützt nur ES-Module). Das Problem ist, dass es im Moment keinen Template-Renderer gibt. Eine Idee war, Schnurrbart auf Deno zu mustache.mjs hinzugefügt wird, bearbeiten Sie : oder ändern Sie die Datei mustache.js, um es mit dem ES-Modul kompatibel zu machen.

Ihre Gedanken?

Referenz: https://github.com/denoland/deno_std/issues/391

Hilfreichster Kommentar

Status-Update; Wie ich in der PR, die Sie gegen meinen esm-ify-Zweig eröffnet haben , erwähnt habe, habe ich jetzt einige Tests durchgeführt, die sicherstellen, dass dieses Paket für verschiedene Modulsysteme, die wir seit Jahren in #724 unterstützen, wie vorgesehen funktioniert.

Ich werde das noch ein paar Tage ziehen lassen, da ich gerade ein paar Verbesserungen vorangetrieben habe, nur für den Fall, dass jemand Einwände oder weitere Optimierungen im Sinn hat.

Mit diesen Tests fühle ich mich wohl, wenn ich dieses Projekt weiterführen werde, um den Quellcode als ES-Modul zu schreiben und zu bauen, um das zu produzieren, was wir heute in mustache.js haben - das wird natürlich getan in einer kommenden PR.

Alle 18 Kommentare

Hallo @zekth!

Spannende Pläne haben Sie mit deno für die Zukunft. Ich bin sehr positiv dafür, dieses Projekt-ES-Modul kompatibel zu machen, und stimme Ihren Gedanken zur Vermeidung eines Ports voll und ganz zu.

Sie haben konkrete Vorstellungen, was dazu nötig wäre?

Hier ist ein (wirklich hässlicher) Port, den ich heute Morgen gemacht habe (in Typoskript) https://github.com/zekth/deno_mustache/blob/master/mod.ts

Ich habe einige Tests nur für den Anfang portiert.
Die einzige Sorge, die ich habe, sind all die verschiedenen Umgebungen, die Sie mit Schnurrbart unterstützen. Es ist besser, das ES-Modul der Haupt-js-Datei kompatibel zu haben als andere mjs denke ich, aber ich möchte nichts kaputt machen :)

Vielen Dank für den Hinweis! 👍

Da ich keine Erfahrung mit Deno habe, werde ich einige triviale Fragen abfeuern, um einige Diskussionen anzustoßen:

  1. Welche Anforderungen muss deno erfüllen, damit dies funktioniert? Muss es eine .mjs Datei sein oder ist es wichtig für type="module" von package.json ?
  2. Irgendwelche Anforderungen an die Dateibenennung?
  3. Spielt TypeScript hier irgendwie eine Rolle?

..und so weiter, wären alle für Dummies-Hinweise sehr dankbar. Im Moment habe ich zu wenig Wissen über Deno, um kreativ über plausible Wege nachzudenken.

  1. Es gibt keine besonderen Anforderungen, da die Bibliothek nur ein ES-Modul sein muss. Beispiel lodash funktioniert ohne jegliche Portierung. Das Laden des Moduls erfolgt über HTTP-Abruf, kein Paket Json oder ähnliches.
  2. Keine Namenskonvention
  3. Sie können TypeScript von JavaScript verwenden, Deno verarbeitet beides.

Zum Beispiel würde die Verwendung von Schnurrbart in Deno so aussehen:

import * as mustache from 'https://raw.githubusercontent.com/janl/mustache.js/master/mustache.js'
mustache.render(......

Wenn Sie mehr Informationen wünschen, können Sie diesen Talk von Ryan lesen :

Cool!

Hier ist also ein Geschwafel, um einige Gedanken und Kontext zu teilen. Mein Verständnis von ES-Modulen ist, dass sie in Bezug auf das, was export ed ist, syntaktisch analysierbar sein sollen. Das steht im dunklen Kontrast zu seinen Vorläufern wie CommonJS, AMD usw., die viel dynamischer sind.

Vor diesem IIFE, das heute den Körper von mustache.js umgibt , das dazu dient, das Modulsystem zu erkennen, in dem der Code derzeit ausgeführt wird, im ES-

Das bedeutet, dass es eine .js | .mjs | .ts Datei geben muss, die ein einfaches und einfaches export ... wie Sie es in Ihrem Port haben: zekth/deno_mustache/mod.ts#L689 .

Der Spaß beginnt, wenn wir auch das alte Verhalten beibehalten wollen, um mit Projekten kompatibel zu bleiben, die andere Modulsysteme verwenden oder gar nicht einmal ein Modulsystem, daher die Notwendigkeit des erwähnten IIFE-Wrappers :denken: Und zur Erinnerung, das bedeutet Projekte auf Servern und Browsern ausgeführt.

Da wir sicherlich nicht zwei verschiedene Implementierungen (ES-Module + der Rest) synchron halten wollen, fühlt es sich an, als ob es sich lohnt, einen Build-Schritt in Betracht zu ziehen. Wenn wir beispielsweise den Quellcode im ES-Modul-Stil geschrieben haben, könnte ein Build-Schritt ihn in ein Nicht-ES-Modul konvertieren, wie wir es heute haben. Oder umgekehrt, wenn das weniger aufdringlich ist.

Abschließend möchte ich sagen, dass ich ein großer Fan davon bin, so kleine Schritte wie möglich zu machen. Ich stehe TypeScript im Allgemeinen positiv gegenüber, aber ist es im Moment in Ordnung, wenn wir uns weiterhin auf ES-Module konzentrieren und eine andere Runde machen, die sich darauf konzentriert, ob wir in TypeScript konvertieren/typedefs exportieren oder nicht?

Kommen Ihnen noch andere Gedanken oder Korrekturen in den Sinn?

Sie haben völlig Recht, der erste Schritt wäre, den TypeScript-Stack hinzuzufügen und den Compiler zu verwenden, um mehrere Dateien wie commonjs / ES5 / ES6 usw. auszugeben ( https://www.typescriptlang.org/docs/handbook/compiler-options .html). Die Verwendung des TS-Compilers zwingt uns nicht zur Verwendung von TypeScript, wir können auch ES6-Code verwenden.

Oh das ist ein toller Vorschlag! Versuchen Sie zunächst, den TS-Compiler als normales Build-Tool von ES -> andere Modulsysteme zu verwenden. Das macht eine spätere plausible TS-Konvertierung viel weniger riskant.

Können Sie diesem Ansatz eine Chance geben? Nicht unbedingt alles auf einmal lösen, aber zumindest die ersten Bausteine. Es wäre wirklich wertvoll, etwas Konkretes zu sehen und zukünftige Diskussionen darauf zu stützen.

Sooo, ich habe versucht, in ein ES-Modul umzusteigen.

Mein Proof of Concept endete damit, dass ich rollup.js anstelle des TypeScript-Compilers (oder babel) verwendet habe, hauptsächlich wegen der UMD-Version, die sie generieren - wir brauchen die immer noch, um die Kompatibilität zu älteren Modulsystemen oder überhaupt keinem Modulsystem zu gewährleisten.

Besteht die Möglichkeit, dass Sie einen Testlauf mit demo machen, um zu sehen, ob es wie erwartet funktioniert? phillipj/mustache.js#esm-ify mustache.mjs

@phillipj wird es tun!

Einige Fehler, aber ich denke, das sind kleinere Korrekturen:

error TS2339: Property 'render' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► file:///Users/vlegoff/projects/genesys/github/telemetry/t/mustache.ts:10:23

10 var output = mustache.render('{{title}} spends {{calc}}', view);
                         ~~~~~~

error TS2554: Expected 2 arguments, but got 1.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:525:52

525   var context = (view instanceof Context) ? view : new Context(view);
                                                       ~~~~~~~~~~~~~~~~~

  An argument for 'parentContext' was not provided.

    ► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:377:25

    377 function Context (view, parentContext) {
                                ~~~~~~~~~~~~~


error TS2339: Property 'escape' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:640:21

640     return mustache.escape(value);
                        ~~~~~~

error TS2339: Property 'clearCache' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:659:10

659 mustache.clearCache = function clearCache () {
             ~~~~~~~~~~

error TS2339: Property 'parse' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:668:10

668 mustache.parse = function parse (template, tags) {
             ~~~~~

error TS2339: Property 'render' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:678:10

678 mustache.render = function render (template, view, partials, tags) {
             ~~~~~~

error TS2339: Property 'to_html' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:690:10

690 mustache.to_html = function to_html (template, view, partials, send) {
             ~~~~~~~

error TS2339: Property 'render' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:693:25

693   var result = mustache.render(template, view, partials);
                            ~~~~~~

error TS2339: Property 'escape' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:704:10

704 mustache.escape = escapeHtml;
             ~~~~~~

error TS2339: Property 'Scanner' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:707:10

707 mustache.Scanner = Scanner;
             ~~~~~~~

error TS2339: Property 'Context' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:708:10

708 mustache.Context = Context;
             ~~~~~~~

error TS2339: Property 'Writer' does not exist on type '{ name: string; version: string; tags: string[]; }'.

► https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs:709:10

709 mustache.Writer = Writer;
             ~~~~~~


Found 12 errors.

Code:

import mustache from 'https://raw.githubusercontent.com/phillipj/mustache.js/esm-ify/mustache.mjs';

var view = {
  title: 'Joe',
  calc: function() {
    return 2 + 4;
  },
};

var output = mustache.render('{{title}} spends {{calc}}', view);

console.log(output);

Soll ich versuchen, eine PR für Ihre .mjs Datei zu erstellen?

Danke!

Erkenne jetzt, dass ich etwas mehr Kontext zu dem sagen sollte, was ich anfangs versucht habe, sorry.

Wie bereits erwähnt, führte mein erster Versuch mit dem TypeScript-Compiler auch zu einigen Fehlern, die denen ähnlich sind, die Sie jetzt angegeben haben. Nichtsdestotrotz überraschte es mich, dass es eine Ausgabe erzeugte und es sehr nah an dem war, was ich wollte.

Was mir nicht gefallen hat, war der UMD-Code, der um die kompilierte Ausgabe gewickelt wurde. Hauptsächlich zwei Dinge:

  1. Es hat nicht den Fallback, den Paketinhalt im globalen Bereich verfügbar zu machen (denken Sie an window.Mustache ). Dies ist für unsere Benutzer, die kein Modulsystem haben, von entscheidender Bedeutung.
  2. In Projekten mit CommonJS wird der Inhalt dieses Pakets als module.exports.default und nicht als module.exports . Obwohl dies das richtige und erwartete Verhalten sein könnte, wenn CommonJS require() ein ES-Modul ist, wird es die Abwärtskompatibilität zerstören, was ich vermeiden wollte.

Da mein Hauptziel darin bestand, in erster Linie den Quellcode in ein ES-Modul umzuwandeln und nicht TypeScript einzuführen, beschloss ich, verschiedene Compiler/Bündel auszuprobieren, um zu sehen, ob sie die Dinge anders machten, um die beiden oben genannten Herausforderungen zu vermeiden.

Daher bin ich bei rollup.js gelandet. Es ist die UMD-Ausgabe, die wir brauchen, und sie verursacht keine grundlegenden Änderungen für Benutzer dieses Pakets.

Sooo zu meiner eigentlichen Frage; Müssen wir uns derzeit um TypeScript kümmern?

Mein Verständnis von vorhin in dieser Diskussion war, dass wir noch nicht vollständig auf TypeScript umstellen könnten, da es deno trotzdem helfen würde, wenn es sich tatsächlich um ein ES-Modul handelt, aber ich habe das vielleicht ein bisschen falsch verstanden?

Ich denke, das Hauptproblem ist die erste Initialisierung von Schnurrbart wie hier:
https://github.com/janl/mustache.js/blob/master/mustache.js#L14

und auch das: https://github.com/janl/mustache.js/blob/master/mustache.js#L536
kann umgeschrieben werden als new Context(view, null)

meinst du nicht?

Ich denke, das Hauptproblem ist die erste Initialisierung von Schnurrbart..

Du hast wahrscheinlich Recht. In der .mjs Version habe ich versucht, das zumindest in den eigentlichen Quellcode zu verschieben, anstatt ein Objekt zu sein, das vom UMD-Wrapper übergeben wird:

var mustache = {
  name: 'mustache.js',
  version: version,
  tags: [ '{{', '}}' ]
}

Es wäre cool, Ihren Ansatz zu sehen, der diese TypeScript-Fehler behebt 👍

kann als neuer Context(view, null) umgeschrieben werden

Fast.. Ist new Context(view, undefined) nicht gleichbedeutend damit, kein zweites Argument zu übergeben?

Ja richtig bezüglich der new Context

Ich werde sowas versuchen :)

Hier ist die PR: https://github.com/phillipj/mustache.js/pull/1
CI ist kaputt, aber ich verstehe nicht, warum ich diese Linting-Nachrichten bekommen habe

Super, vielen Dank! In den nächsten Tagen ziemlich beschäftigt, werde ich mein Bestes tun, um es vor Ende der Woche zu überprüfen.

Status-Update; Wie ich in der PR, die Sie gegen meinen esm-ify-Zweig eröffnet haben , erwähnt habe, habe ich jetzt einige Tests durchgeführt, die sicherstellen, dass dieses Paket für verschiedene Modulsysteme, die wir seit Jahren in #724 unterstützen, wie vorgesehen funktioniert.

Ich werde das noch ein paar Tage ziehen lassen, da ich gerade ein paar Verbesserungen vorangetrieben habe, nur für den Fall, dass jemand Einwände oder weitere Optimierungen im Sinn hat.

Mit diesen Tests fühle ich mich wohl, wenn ich dieses Projekt weiterführen werde, um den Quellcode als ES-Modul zu schreiben und zu bauen, um das zu produzieren, was wir heute in mustache.js haben - das wird natürlich getan in einer kommenden PR.

728 wurde zur öffentlichen Kontrolle geöffnet.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen