Migración de JavaScript (o TypeScript) a AssemblyScript
Nota: el SDK de AssemblyScript (@fastly/as-compute) para Compute@Edge de Fastly se ha sustituido por el SDK de JavaScript (@fastly/js-compute), más actual y completo en cuanto a funcionalidades.
Hace poco anunciamos que Compute@Edge</u>, nuestro entorno informático sin servidores, añadiría compatibilidad con AssemblyScript</u>, tras lo cual publicamos un artículo en el que explicábamos por qué AssemblyScript podría ser un excelente punto de partida</u> para los desarrolladores de JavaScript y TypeScript interesados en Compute@Edge y WebAssembly. Hoy, más que hablar sobre la estrecha relación que existe entre AssemblyScript y JavaScript, voy a enseñar en qué consiste. Como Senior Software Engineer de Compute@Edge e integrante del equipo principal de AssemblyScript, me gustaría profundizar en el proceso de migración de aplicaciones comunes de JavaScript a AssemblyScript y lo que se debe tener en cuenta.
En primer lugar, veamos qué queremos migrar exactamente. Hace poco creé una breve demo en lenguaje de marcado de AssemblyScript para Compute@Edge</u> basada en la demo experimental <u>as-bind</u>
de Markdown Parser</u>. El trayecto de ida y vuelta de la demo duró unos 25 ms, según lo que vi en el despacho de mi casa. Quería saber cuánto tiempo se invertía en ejecutar el código de mi aplicación en comparación con subir el lenguaje de marcado y descargar el HTML, y también en convertir el lenguaje de marcado a HTML en comparación con otras partes de la aplicación. Para crear algo así como una aplicación de Node.js, podríamos escribir el siguiente código:
const prettyMilliseconds = require("pretty-ms");
function getPrettyExecutionTime() {
// Get our start time in milliseconds (Unix Timestamp)
const start = Date.now();
// Do a random amount of busy work
let iterations = 100000 + Math.floor(Math.random() * 10000000);
for (let i = 0; i < iterations; i++) {
iterations -= 1;
}
// Get our start time in milliseconds (Unix Timestamp)
const end = Date.now();
// Log out the Execution time in a human readable format
let responseString = "";
responseString +=
"Pretty Unix timestamp: " +
prettyMilliseconds(start, { verbose: true }) +
"\n";
responseString +=
"Busy work execution time: " +
prettyMilliseconds(end - start, {
verbose: true,
formatSubMilliseconds: true,
});
return responseString;
}
console.log(getPrettyExecutionTime());
Si nos fijamos en el código de Node.js, nos damos cuenta de que utiliza el objeto global Date de JavaScript</u> para obtener un valor de tiempo similar a una marca de tiempo Unix (es decir, el número de milisegundos transcurridos desde el 1 de enero de 1970 a las 00:00:00 UTC) para marcar el inicio y el final de la ejecución de nuestra aplicación de Node.js. A continuación, registramos estas marcas de tiempo en un formato legible para seres humanos mediante la dependencia <u>pretty-ms</u>
disponible en npm</u>, así como la diferencia entre ambas para conocer el tiempo total de ejecución.
Pongamos que queremos migrar esta funcionalidad de la aplicación de Node.js a la aplicación de AssemblyScript. Tendríamos que hacer algo así:
Determinar si los objetos globales de JavaScript (como los de
window
yglobal
) presentes en el código fuente se pueden sustituir por la biblioteca estándar de AssemblyScript, llamadas al host de WASI o bibliotecas de AssemblyScript de terceros (estas se suelen encontrar en npm).Determinar si las dependencias importadas de JavaScript (y las dependencias de estas dependencias) tienen equivalentes de AssemblyScript. En caso negativo, habría que migrarlas (ver el paso 1).
Añadir tipos de AssemblyScript al código de JavaScript (o sustituir los tipos de TypeScript por otros compatibles con AssemblyScript</u>).
Ajustar y cambiar de sitio el código de JavaScript que podría causar problemas al utilizar sintaxis o bibliotecas de AssemblyScript aún en desarrollo (en mi opinión, los dos principales elementos de desarrollo más importantes en el compilador de AssemblyScript a finales de 2020 son las clausuras y las expresiones regulares). A continuación, ajustar el código que interactúa con las dependencias o los objetos globales de JavaScript para que funcionen con las nuevas API de sustitución.
Sigamos este proceso con nuestra aplicación de Node.js. Nos ponemos con el paso 1 y nos damos cuenta de que la aplicación de Node.js emplea <u>Math</u>
y <u>Date</u>
. Concretamente, tenemos que sustituir la funcionalidad de Math.floor()
, Math.random()
y Date.now()
. Como se puede ver, la biblioteca estándar de AssemblyScript ofrece su propio</u> <u>Math.floor</u>
global, por lo que no hay que hacer ningún cambio. AssemblyScript también ofrece su propio <u>Math.random()</u>
global; sin embargo, las notas sobre el uso</u> indican que también se debe añadir import “wasi”
, ya que utiliza los enlaces WASI admitidos por Compute@Edge para generar números aleatorios. Básicamente, solo hay que migrar una línea de código. Por último, tenemos que migrar Date.now()
, lo cual puede suponer un problema. AssemblyScript ofrece un objeto global Date</u> que requiere importar el objeto Date
de un host de JavaScript. Compute@Edge no importa el objeto Date de JavaScript en los módulos de WebAssembly, así que necesitamos WASI o bibliotecas de terceros para llevar a cabo la sustitución.
Para ello, podemos buscar algo como «assemblyscript wasi date» en Google y encontrar <u>as-wasi</u>
. as-wasi
es una «capa de AssemblyScript de alto nivel para la interfaz de sistema de WebAssembly (WASI)». En otras palabras, ofrece una API de alto nivel con funcionalidades comunes a nivel de sistema para aplicaciones de AssemblyScript que utilizan enlaces WASI de AssemblyScript. Según la documentación de referencia, proporciona su propio <u>Date.now()</u>
, que es un muy buen sustituto para Date.now()
de JavaScript. De esta forma, sabemos que es posible trasladar el código fuente de nuestra aplicación a Compute@Edge. No obstante, debemos seguir este mismo proceso con todas las dependencias. Nuestra aplicación de Node.js tiene una sola dependencia: el paquete pretty-ms
de npm con licencia de MIT, que acumula más de un millón de descargas semanales</u>, buena muestra de su popularidad. Al fijarnos en el código fuente de pretty-ms
, advertimos que tiene una dependencia parse-ms
y que utiliza los objetos globales Math
y Number
. Si volvemos al paso 1, vemos que los objetos Math
y Number
de la biblioteca estándar de AssemblyScript ocupan el lugar deseado en el código fuente.
Antes de pasar a parse-ms
, me gustaría señalar algunos aspectos de la sintaxis que debemos modificar. En primer lugar, el código fuente contiene clausuras representadas por funciones anidadas. AssemblyScript permite trasladar y anidar funciones puras, pero vamos a convertirlas en sus propias funciones para ahorrarnos quebraderos de cabeza. También conviene destacar que este código utiliza sintaxis CommonJS para require()
y la exportación de módulos. AssemblyScript sigue la sintaxis estándar de importación y exportación ES Module</u>, que es similar a la de TypeScript, por lo que debemos hacer otro pequeño cambio en dicha sintaxis. A continuación tenemos parse-ms
, nuestra última dependencia.
Solo hay que mirar el código fuente de <u>parse-ms</u>
undefined para saber que esta dependencia es insignificante. De nuevo, la biblioteca estándar de AssemblyScript es suficiente para todos los objetos globales. Hay un fragmento que puede comprobar si el valor enviado a la función de exportación es un número, pero podemos ignorarlo porque el compilador de AssemblyScript se encarga de eso.
Hemos determinado que los objetos globales de JavaScript y todas las dependencias se pueden migrar, y esto también va por nuestra aplicación de Node.js. ¡Ya podemos ponernos a programar! Voy a generar una nueva aplicación de Compute@Edge en AssemblyScript utilizando la CLI de Fastly</u> y ejecutando fastly compute init
. A su vez, esto generará el kit inicial de AssemblyScript</u> con <u>@fastly/as-compute</u>
0.1.3</u>. A continuación, me pondré a migrar el código a mi aplicación de AssemblyScript. Los fragmentos de código que aparecen abajo tienen un montón de comentarios para explicar lo que hacemos con JavaScript y los tipos relativos de TypeScript, así que vamos a echar un vistazo al código resultante. Empiezo con la dependencia más anidada, que es parse-ms
(código fuente de JavaScript</u>), y creo assembly/parse-ms.ts
:
// This file is a port of:
// https://github.com/sindresorhus/parse-ms/blob/326500f7395fba4f47e73e36e6e770ad47c358d2/index.js
// The file is commented respective to how this is ported.
// As of 2020, AssemblyScript closure support is still in progress, and only supports pure nested functions
// Thus, we will pull out the nested function into its own function.
// This isn't required, but can avoid headaches in the future.
// This function takes in a float, but rounds it to an integer.
// In Typescript, `f64` would have been `number` types, but we must be explicit with the type of number in AS
// Ported from: https://github.com/sindresorhus/parse-ms/blob/326500f7395fba4f47e73e36e6e770ad47c358d2/index.js#L7
function roundTowardsZero(valueToRound: f64): f64 {
if (valueToRound > 0) {
return Math.floor(valueToRound);
} else {
return Math.ceil(valueToRound);
}
}
// Define a class that represents the returned object fom the exported function
// We are exporting this as well, that way the type can be used
// Also, the `f64` type in TypeScript would be `number`, but in AS we must be explicit with the number type
// Ported from: https://github.com/sindresorhus/parse-ms/blob/326500f7395fba4f47e73e36e6e770ad47c358d2/index.js#L9
export class ParsedMilliseconds {
days: f64;
hours: f64;
minutes: f64;
seconds: f64;
milliseconds: f64;
microseconds: f64;
nanoseconds: f64;
}
// Export a function to parse our milliseconds into our return type.
// Also, the `f64` type in TypeScript would be `number`, but in AS we must be explicit with the number type.
// Ported from: https://github.com/sindresorhus/parse-ms/blob/master/index.js#L2
export function parseMilliseconds(milliseconds: f64): ParsedMilliseconds {
// We don't need to do a type check here, since we are using a typed language!
// Referring to: https://github.com/sindresorhus/parse-ms/blob/326500f7395fba4f47e73e36e6e770ad47c358d2/index.js#L3
// We moved roundTowardsZero into its own function
// Referring to: https://github.com/sindresorhus/parse-ms/blob/326500f7395fba4f47e73e36e6e770ad47c358d2/index.js#L7
// AssemblyScript will construct an instance of our return type (e.g new ParsedMilliseconds())
// Since the return object has all the same properties of our return type.
// This is so that we can pass a float into our `roundTowardsZero` function to handle the special rounding.
return {
days: roundTowardsZero(milliseconds / 86400000),
hours: roundTowardsZero(milliseconds / 3600000) % 24,
minutes: roundTowardsZero(milliseconds / 60000) % 60,
seconds: roundTowardsZero(milliseconds / 1000) % 60,
milliseconds: roundTowardsZero(milliseconds) % 1000,
microseconds: roundTowardsZero(milliseconds * 1000) % 1000,
nanoseconds: roundTowardsZero(milliseconds * 1e6) % 1000,
};
}
Como ya tenemos parse-ms
, podemos migrar pretty-ms
(código fuente de JavaScript</u>). pretty-ms
ofrece varias opciones para controlar el número de decimales</u>. Esto depende de JavaScript Number.prototype.toFixed</u>. Sin embargo, AssemblyScript plantea un problema con su biblioteca estándar</u>. Podríamos escribir su implementación en este ejemplo, pero no vamos a incluir esta funcionalidad para abreviar. En su lugar, creamos assembly/pretty-ms.ts
:
// This file is a port of:
// https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js
// The file is commented respective to how this is ported.
// Import our ported ported `parse-ms` module
// This ports the `require()` call:
// Ported From: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L2
import { parseMilliseconds } from "./parse-ms";
const SECOND_ROUNDING_EPSILON: f32 = 0.0000001;
// Define our options object that will be passed into our exported `prettyMilliseconds` function
// The options are from the documentation: https://github.com/sindresorhus/pretty-ms#options
// However, we removed the `DecimalDigits` options and `keepDecimalsOnWholeSeconds`, as Float.toFixed is in progress:
// https://github.com/AssemblyScript/assemblyscript/issues/1163
// In Typescript, `f64` and `i32` would have been `number` types, but we must be explicit with the type of number in AS
// Ported from: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L8
export class PrettyMillisecondsOptions {
compact: boolean = false;
unitCount: i32 = 0;
verbose: boolean = false;
separateMilliseconds: boolean = false;
formatSubMilliseconds: boolean = false;
colonNotation: boolean = false;
}
// This function takes in our word (which would be a string),
// and the count of that word (a float), to pluralize it.
// Also, the `i32` type in TypeScript would be `number`, but in AS, we must be explicit with the number type.
// Ported from: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L4
function pluralize(word: string, count: f64): string {
// Since AssemblyScript is type checked, there is no need for ===
// We can use the standard ==
// Referring to: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L4
if (count == 1) {
return word;
}
return word + "s";
}
// As of 2020, AssemblyScript closure support is still in progress and only supports pure nested functions
// Thus, we will pull out the nested function into its own function.
// We pass in the options and results that were previously accessible by the closure, and return the results
// We also typed all of the parameters, to their respective types they would have been in JS or TS.
// One notable parameter is `valueString`. In JavaScript, optional parameters will default to `undefined`.
// In AssemblyScript, we would want to initialize this parameter with a value of its type and check that value later.
// We could have done a `valueString: string | null = null` to also signify it's an optional high-level typed parameter in a more
// JS-like fashion, but we use an empty string as it is a simpler replacement to check for.
// Ported from: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L33
function add(
options: PrettyMillisecondsOptions,
result: Array<string>,
value: f64,
long: string,
short: string,
valueString: string = ""
): Array<string> {
if (
(result.length === 0 || !options.colonNotation) &&
value === 0 &&
!(options.colonNotation && short === "m")
) {
return result;
}
// AssemblyScript doesn't have `undefined`, so we need to be
// a bit more explicit with our typecheck here
// Referring to: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L38
if (valueString == "") {
valueString = value.toString();
}
// AssemblyScript would normally default types to i32, if the compiler can't figure out what
// the type is from its initial assignment. So we need to define these types as strings,
// since they are being used as strings
// Ported from: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L39
let prefix: string = "";
let suffix: string = "";
if (options.colonNotation) {
prefix = result.length > 0 ? ":" : "";
suffix = "";
const wholeDigits = valueString.includes(".")
? valueString.split(".")[0].length
: valueString.length;
const minLength = result.length > 0 ? 2 : 1;
valueString =
"0".repeat(<i32>Math.max(0, minLength - wholeDigits)) + valueString;
} else {
prefix = "";
// Since we removed the `DecimalDigits` options and `keepDecimalsOnWholeSeconds`, as Float.toFixed is in progress:
// https://github.com/AssemblyScript/assemblyscript/issues/1163
// Let's remove the trailing `.0` to clean things up by parsing our f64 into an i32
valueString = I32.parseInt(valueString).toString();
suffix = options.verbose ? " " + pluralize(long, value) : short;
}
result.push(prefix + valueString + suffix);
return result;
}
// Export a function to parse our milliseconds into our human readable milliseconds string.
// Also, the `i32` type in TypeScript would be `number`, but in AS we must be explicit with the number type.
// Ported from: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L8
export function prettyMilliseconds(
milliseconds: f64,
options: PrettyMillisecondsOptions
): string {
if (!Number.isFinite(milliseconds)) {
throw new Error("Expected a finite number");
}
if (options.colonNotation) {
options.compact = false;
options.formatSubMilliseconds = false;
options.separateMilliseconds = false;
options.verbose = false;
}
// Since we aren't supporting DecimalDigits options in this port, we don't need to modify them
// Referring to: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L20
// It is best to define most high-level types by their object and type
// Therefore our Array is defined as `new Array<string>()` instead of `[]`
// Ported from: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L25
let result = new Array<string>();
const parsed = parseMilliseconds(milliseconds);
// As mentioned earlier, we pulled the add function into its own function.
// Thus, we update our result as we add instead of using the closure.
// We also updated the other `add()` calls below, but only commenting here for brevity.
// Also, we don't need the Math.trunc() call since we are doing integer division by default, unlike JavaScript
// Ported from: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L57
result = add(options, result, Math.floor(parsed.days / 365), "year", "y");
result = add(options, result, parsed.days % 365, "day", "d");
result = add(options, result, parsed.hours, "hour", "h");
result = add(options, result, parsed.minutes, "minute", "m");
if (
options.separateMilliseconds ||
options.formatSubMilliseconds ||
(!options.colonNotation && milliseconds < 1000)
) {
result = add(options, result, parsed.seconds, "second", "s");
if (options.formatSubMilliseconds) {
result = add(options, result, parsed.milliseconds, "millisecond", "ms");
result = add(options, result, parsed.microseconds, "microsecond", "µs");
result = add(options, result, parsed.nanoseconds, "nanosecond", "ns");
} else {
const millisecondsAndBelow =
parsed.milliseconds +
parsed.microseconds / 1000 +
parsed.nanoseconds / 1e6;
// Since we aren't supporting DecimalDigits options in this port, we don't need `millisecondsDecimalDigits`
// Referring to: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L78
const roundedMilliseconds =
millisecondsAndBelow >= 1
? Math.round(millisecondsAndBelow)
: Math.ceil(millisecondsAndBelow);
// Since we aren't supporting DecimalDigits options in this port, we don't need `millisecondsDecimalDigits`
// Referring to: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L87
const millisecondsString: string = roundedMilliseconds.toString();
result = add(
options,
result,
parseFloat(millisecondsString),
"millisecond",
"ms",
millisecondsString
);
}
} else {
const seconds = (milliseconds / 1000) % 60;
// Since we aren't supporting DecimalDigits options in this port, we don't need `secondsDecimalDigits`
// Referring to: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L78
const secondsString = seconds.toString();
result = add(
options,
result,
parseFloat(secondsString),
"second",
"s",
secondsString
);
}
if (result.length === 0) {
return "0" + (options.verbose ? " milliseconds" : "ms");
}
if (options.compact) {
return result[0];
}
// We can replace the type check with a `> 0` check since we are using a typed language!
// Referring to: https://github.com/sindresorhus/pretty-ms/blob/eda21362097d47ab309dca8cf07dc79b25fb0efa/index.js#L119
if (options.unitCount > 0) {
const separator = options.colonNotation ? "" : " ";
return result.slice(0, <i32>Math.max(options.unitCount, 1)).join(separator);
}
return options.colonNotation ? result.join("") : result.join(" ");
}
¡Genial! Ahora vamos a migrar la lógica principal de las aplicaciones de Node.js a assembly/pretty-execution-time.ts
. Recordemos que decidimos usar el objeto Date
de as-wasi
. Para ello, tenemos que instalar as-wasi
en nuestro proyecto escribiendo npm install --save as-wasi
en el terminal y crear assembly/pretty-execution-time.ts
:
import "wasi";
import { Date } from "as-wasi";
import { prettyMilliseconds } from "./pretty-ms";
export function getPrettyExecutionTime(): string {
// Get our start time in milliseconds (Unix Timestamp)
// In "as-wasi" this returns the milliseconds as a float
// However, we will cast this to an integer for prettyMilliseconds
const start = Date.now();
// Do a random amount of busy work
let iterations = 100000 + Math.floor(Math.random() * 10000000);
for (let i = 0; i < iterations; i++) {
iterations -= 1;
}
// Get our start time in milliseconds (Unix Timestamp)
const end = Date.now();
let responseString = "";
responseString +=
"Pretty Unix timestamp: " +
prettyMilliseconds(start, { verbose: true }) +
"\n";
responseString +=
"Busy work execution time: " +
prettyMilliseconds(end - start, {
verbose: true,
formatSubMilliseconds: true,
});
return responseString;
}
Por último, vamos a llamar a la función getPrettyExecutionTime
que hemos exportado en el archivo de AssemblyScript que actúa como punto de entrada de Compute@Edge. Modificamos assembly/index.ts
:
import { Request, Response, Fastly } from "@fastly/as-compute";
// Import our pretty-execution time
import { getPrettyExecutionTime } from "./pretty-execution-time";
// Remove the unnecessary backend constants for our application
// Referring to: https://github.com/fastly/compute-starter-kit-assemblyscript-default/blob/78e536b046cff9e2a3e81945ef8b02ddc7bf2a75/assembly/index.ts#L3
// The entry point for your application.
//
// Use this function to define your main request handling logic. It could be
// used to route based on the request properties (such as method or path), send
// the request to a backend, make completely new requests, and/or generate
// synthetic responses.
function main(req: Request): Response {
// Make any desired changes to the client request.
req.headers().set("Host", "example.com");
// We can filter requests that have unexpected methods.
const VALID_METHODS = ["HEAD", "GET", "POST"];
if (!VALID_METHODS.includes(req.method())) {
return new Response(String.UTF8.encode("This method is not allowed"), {
status: 405,
});
}
let method = req.method();
let urlParts = req.url().split("//").pop().split("/");
let host = urlParts.shift();
let path = "/" + urlParts.join("/");
// If request is a `GET` to the `/` path, send a default response.
if (method == "GET" && path == "/") {
return new Response(String.UTF8.encode(getPrettyExecutionTime()), {
status: 200,
});
}
// Remove the unnecessary routes for our application
// Referring to: https://github.com/fastly/compute-starter-kit-assemblyscript-default/blob/78e536b046cff9e2a3e81945ef8b02ddc7bf2a75/assembly/index.ts#L42
// Catch all other requests and return a 404.
return new Response(
String.UTF8.encode("The page you requested could not be found"),
{
status: 404,
}
);
}
// Get the request from the client.
let req = Fastly.getClientRequest();
// Pass the request to the main request handler function.
let resp = main(req);
// Send the response back to the client.
Fastly.respondWith(resp);
¡Aplicación terminada y lista para el despliegue! La versión definitiva se puede ver aquí</u>.
Antes de terminar, me gustaría hacer unos cuantos apuntes:
Habría sido más fácil migrar los equivalentes de
parse-ms
ypretty-ms
de TypeScript, dado que algunos tipos de AssemblyScript y TypeScript se solapan. Los tipos de AssemblyScript suelen ser un poco más específicos, por lo que identificar esos tipos y cambiarlos es mucho más sencillo que añadirlos de cero.El compilador de AssemblyScript hace lo posible por identificar los tipos cuando se declaran variables, pero el resultado a veces es diferente de lo que se espera de primeras. Si crees que se produce algún comportamiento fuera de lo común después de una migración, puedes añadir los tipos que habías dejado en manos del compilador.
pretty-ms
yparse-ms
son mucho más fáciles de migrar que entornos de JavaScript tan grandes como Express</u> o Apollo</u>. Elegimos estos paquetes porque son muy populares, pero podrían migrarse en formato de tutorial breve. Los paquetes grandes suelen utilizar más partes de las API globales. Por ejemplo, una API Node.js muy común es el módulo de archivos del sistema</u><u>fs</u>
.fs
tiene equivalentes de WASI enas-wasi
, que es el<u>sistema de archivos</u>
de<u>as-wasi</u>
. El caso es que no todas las API de JavaScript en Node.js o el navegador son compatibles, puesto que AssemblyScript, WASI y WebAssembly son tecnologías relativamente nuevas.</u>Si migras una biblioteca que se pueda utilizar en distintos proyectos de AssemblyScript y la licencia te lo permite, no dudes en subirla a npm. ¡La comunidad de AssemblyScript te lo agradecerá! El proceso para publicar un paquete de AssemblyScript es</u> similar al de subir un paquete normal de JavaScript</u>. La única diferencia es que, en vez de utilizar la clave principal de
package.json
, AssemblyScript busca una entrada «ascMain» en package.json</u> que debería estar asociada al archivo de entrada de AssemblyScript en tu biblioteca. Por ejemplo, si el archivo de entrada de tu biblioteca esassembly/index.ts
, podrías añadirpackage.json: ”ascMain”: “assembly/index.ts”
.</u>
AssemblyScript es un lenguaje nuevo y con muchas posibilidades, así que tenemos muchas ganas de ver lo lejos que la gente puede llegar con él. Esperamos que esta guía ayude a apreciar las similitudes entre escribir en AssemblyScript y hacerlo en JavaScript o TypeScript y a comprender por qué es una gran opción para llevar JavaScript y TypeScript a Compute@Edge o al mundo de WebAssembly en general. Date de alta en nuestras notificaciones por correo electrónico</u> para enterarte de todo lo relacionado con Compute@Edge.</u>