{"id":13417793,"url":"https://github.com/lastmjs/zwitterion","last_synced_at":"2025-05-15T01:08:38.550Z","repository":{"id":14497640,"uuid":"69318508","full_name":"lastmjs/zwitterion","owner":"lastmjs","description":"A web dev server that lets you import anything*","archived":false,"fork":false,"pushed_at":"2025-04-19T02:36:50.000Z","size":957,"stargazers_count":585,"open_issues_count":65,"forks_count":14,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-05-06T12:45:57.262Z","etag":null,"topics":["assemblyscript","c","cpp","es2016","es6","es7","esnext","javascript","rust","spa","typescript","wasm","webassembly"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lastmjs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-27T04:14:09.000Z","updated_at":"2025-04-17T20:23:27.000Z","dependencies_parsed_at":"2024-01-15T03:58:08.077Z","dependency_job_id":"d0bb1ffe-77bf-4fdd-b47c-32dd44c70499","html_url":"https://github.com/lastmjs/zwitterion","commit_stats":{"total_commits":513,"total_committers":3,"mean_commits":171.0,"dds":"0.10916179337231968","last_synced_commit":"8930d85b8cde6739e4ed1742b3fa1023c0e5f8aa"},"previous_names":[],"tags_count":122,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lastmjs%2Fzwitterion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lastmjs%2Fzwitterion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lastmjs%2Fzwitterion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lastmjs%2Fzwitterion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lastmjs","download_url":"https://codeload.github.com/lastmjs/zwitterion/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254254042,"owners_count":22039792,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assemblyscript","c","cpp","es2016","es6","es7","esnext","javascript","rust","spa","typescript","wasm","webassembly"],"created_at":"2024-07-30T22:00:52.706Z","updated_at":"2025-05-15T01:08:33.541Z","avatar_url":"https://github.com/lastmjs.png","language":"TypeScript","funding_links":[],"categories":["Tools","TypeScript","Projects","c","typescript","Build Systems"],"sub_categories":["Web frameworks-libraries","IDE"],"readme":"[![build status](https://github.com/lastmjs/zwitterion/workflows/test/badge.svg)](https://github.com/lastmjs/zwitterion/actions) [![npm version](https://img.shields.io/npm/v/zwitterion.svg?style=flat)](https://www.npmjs.com/package/zwitterion) [![dependency Status](https://david-dm.org/lastmjs/zwitterion/status.svg)](https://david-dm.org/lastmjs/zwitterion) [![devDependency Status](https://david-dm.org/lastmjs/zwitterion/dev-status.svg)](https://david-dm.org/lastmjs/zwitterion?type=dev)\n\n# Zwitterion\n\nA web dev server that lets you import anything*\n\n\\* If by anything you mean: JavaScript ES2015+, TypeScript, JSON, JSX, TSX, AssemblyScript, Rust, C, C++, WebAssembly, and in the future anything that compiles to JavaScript or WebAssembly.\n\nZwitterion is designed to be an instant replacement for your current web development static file server.\n\nProduction deployments are also possible through the static build.\n\nFor example, you can write stuff like the following and it just works:\n\n`./index.html`:\n\n```html\n  \u003c!DOCTYPE html\u003e\n\n  \u003chtml\u003e\n    \u003chead\u003e\n      \u003cscript type=\"module\" src=\"app.ts\"\u003e\u003c/script\u003e\n    \u003c/head\u003e\n\n    \u003cbody\u003e\n      This is the simplest developer experience I've ever had!\n    \u003c/body\u003e\n  \u003c/html\u003e\n```\n\n`./app.ts`:\n\n```typescript\nimport { getHelloWorld } from './hello-world.ts';\n\nconst helloWorld: string = getHelloWorld();\n\nconsole.log(helloWorld);\n```\n\n`./hello-world.ts`:\n\n```typescript\nexport function getHelloWorld(): string {\n  return 'Why hello there world!';\n}\n```\n\nReally, it just works. \n\nZwitterion lets you get back to the good old days of web development. \n\nJust write your source code in any supported language and run it in the browser.\n\nAlso...Zwitterion is NOT a bundler. It eschews bundling for a simpler experience.\n\n## Current Features\n\n* ES2015+\n* TypeScript\n* JSON\n* JSX\n* TSX\n* AssemblyScript\n* Rust (basic support)\n* C (basic support)\n* C++ (basic support)\n* WebAssembly Text Format (Wat)\n* WebAssembly (Wasm)\n* Bare imports (`import * as stuff from 'library';` instead of `import * as stuff from '../node_modules/library/index.js';`)\n* Single Page Application routing (by default the server returns `index.html` on unhandled routes)\n* Static build for production deployment\n\n## Upcoming Features\n\n* More robust Rust integration (i.e. automatic local Rust installation during npm installation)\n* More robust C integration\n* More robust C++ integration\n* Import maps\n* HTTP2 optimizations\n\n# Documentation\n\n* [Examples](examples)\n* [Installation and Basic Use](#installation-and-basic-use)\n* [Production Use](#production-use)\n* [Languages](#languages)\n  * [JavaScript](#javascript)\n  * [TypeScript](#typescript)\n  * [JSON](#json)\n  * [JSX](#jsx)\n  * [TSX](#tsx)\n  * [AssemblyScript](#assemblyscript)\n  * [Rust](#rust)\n  * [C](#c)\n  * [C++](#c-1)\n  * [WebAssembly Text Format (Wat)](#webassembly-text-format-wat)\n  * [WebAssembly (Wasm)](#webassembly-wasm)\n* [Command Line Options](#command-line-options)\n* [Special Considerations](#special-considerations)\n* [Under the Hood](#under-the-hood)\n\n## Installation and Basic Use\n\n### Local Installation and Use\n\nInstall Zwitterion in the directory that you would like to serve files from:\n\n```bash\nnpm install zwitterion\n```\n\nRun Zwitterion by accessing its executable directly from the terminal:\n\n```\nnode_modules/.bin/zwitterion\n```\n\nor from an npm script:\n\n```\n{\n  ...\n  \"scripts\": {\n    \"start\": \"zwitterion\"\n  }\n  ...\n}\n```\n\n### Global Installation and Use\n\nInstall Zwitterion globally to use across projects:\n\n```bash\nnpm install -g zwitterion\n```\n\nRun Zwitterion from the terminal:\n\n```bash\nzwitterion\n```\n\nor from an npm script:\n\n```\n{\n  ...\n  \"scripts\": {\n    \"start\": \"zwitterion\"\n  }\n  ...\n}\n```\n\n## Production Use\n\nIt is recommended to use Zwitterion in production by creating a static build of your project. A static build essentially runs all relevant files through Zwitterion, and copies those and all other files in your project to a `dist` directory. You can take this directory and upload it to a Content Delivery Network (CDN), or another static file hosting service.\n\nYou may also use a running Zwitterion server in production, but for performance and potential security reasons it is not recommended. \n\nTo create a static build, run Zwitterion with the `--build-static` option. You will probably need to add the `application/javascript` MIME type to your hosting provider for your TypeScript, AssemblyScript, Rust, Wasm, and Wat files.\n\nFrom the terminal:\n\n```bash\nzwitterion --build-static\n```\n\nFrom an npm script:\n\n```bash\n{\n  ...\n  \"scripts\": {\n    \"build-static\": \"zwitterion --build-static\"\n  }\n  ...\n}\n```\n\nThe static build will be located in a directory called `dist`, in the same directory that you ran the `--build-static` command from.\n\n## Languages\n\n### JavaScript\n\nJavaScript is the language of the web. You can learn more [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript).\n\nImporting JavaScript ES2015+ is straightforward and works as expected. Simply use import and export statements without any modifications. It is recommended to use explicit file extensions:\n\n`./app.js`:\n\n```javascript\nimport { helloWorld } from './hello-world.js';\n\nconsole.log(helloWorld());\n```\n\n`./hello-world.js`:\n\n```javascript\nexport function helloWorld() {\n  return 'Hello world!';\n}\n```\n\nJavaScript transpilation is done by the TypeScript compiler. By default, the TypeScript compiler's `compilerOptions` are set to the following:\n\n```JSON\n  {\n    \"module\": \"ES2015\",\n    \"target\": \"ES2015\"\n  }\n```\n\nYou can override these options by creating a `.json` file with your own `compilerOptions` and telling Zwitterion where to locate it with the `--tsc-options-file` command line option. The available options can be found [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html). Options are specified as a JSON object. For example:\n\n`tsc-options.json`:\n\n```JSON\n{\n  \"target\": \"ES5\"\n}\n```\n\nTell Zwitterion where to locate it:\n\n```bash\nzwitterion --tsc-options-file tsc-options.json\n```\n\n### TypeScript\n\nTypeScript is a typed superset of JavaScript. You can learn more [here](https://www.typescriptlang.org).\n\nImporting TypeScript is straightforward and works as expected. Simply use import and export statements without any modifications. It is recommended to use explicit file extensions:\n\n\n`./app.ts`:\n\n```typescript\nimport { helloWorld } from './hello-world.ts';\n\nconsole.log(helloWorld());\n```\n\n`./hello-world.ts`:\n\n```typescript\nexport function helloWorld(): string {\n  return 'Hello world!';\n}\n```\n\nBy default, the TypeScript compiler's `compilerOptions` are set to the following:\n\n```JSON\n  {\n    \"module\": \"ES2015\",\n    \"target\": \"ES2015\"\n  }\n```\n\nYou can override these options by creating a `.json` file with your own `compilerOptions` and telling Zwitterion where to locate it with the `--tsc-options-file` command line option. The available options can be found [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html). Options are specified as a JSON object. For example:\n\n`tsc-options.json`:\n\n```JSON\n{\n  \"target\": \"ES5\"\n}\n```\n\nTell Zwitterion where to locate it:\n\n```bash\nzwitterion --tsc-options-file tsc-options.json\n```\n\n### JSON\n\nJSON is provided as a default export. It is recommended to use explicit file extensions:\n\n`./app.js`:\n\n```javascript\nimport helloWorld from './hello-world.json';\n\nconsole.log(helloWorld);\n```\n\n`./hello-world.json`:\n\n```json\n{\n  \"hello\": \"world\"\n}\n```\n\n### JSX\n\nImporting JSX is straightforward and works as expected. Simply use import and export statements without any modifications. It is recommended to use explicit file extensions:\n\n`./app.js`:\n\n```javascript\nimport { helloWorldElement } from './hello-world.jsx';\n\nReactDOM.render(\n  helloWorldElement,\n  document.getElementById('root')\n);\n```\n\n`./hello-world.jsx`:\n\n```javascript\nexport const hellowWorldElement = \u003ch1\u003eHello, world!\u003c/h1\u003e;\n```\n\nJSX transpilation is done by the TypeScript compiler. By default, the TypeScript compiler's `compilerOptions` are set to the following:\n\n```JSON\n  {\n    \"module\": \"ES2015\",\n    \"target\": \"ES2015\"\n  }\n```\n\nYou can override these options by creating a `.json` file with your own `compilerOptions` and telling Zwitterion where to locate it with the `--tsc-options-file` command line option. The available options can be found [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html). Options are specified as a JSON object. For example:\n\n`tsc-options.json`:\n\n```JSON\n{\n  \"target\": \"ES5\"\n}\n```\n\nTell Zwitterion where to locate it:\n\n```bash\nzwitterion --tsc-options-file tsc-options.json\n```\n\n### TSX\n\nImporting TSX is straightforward and works as expected. Simply use import and export statements without any modifications. It is recommended to use explicit file extensions:\n\n`./app.js`:\n\n```javascript\nimport { helloWorldElement } from './hello-world.tsx';\n\nReactDOM.render(\n  helloWorldElement,\n  document.getElementById('root')\n);\n```\n\n`./hello-world.tsx`:\n\n```javascript\n\nconst helloWorld: string = 'Hello, world!';\n\nexport const hellowWorldElement = \u003ch1\u003e{ helloWorld }\u003c/h1\u003e;\n```\n\nTSX transpilation is done by the TypeScript compiler. By default, the TypeScript compiler's `compilerOptions` are set to the following:\n\n```JSON\n  {\n    \"module\": \"ES2015\",\n    \"target\": \"ES2015\"\n  }\n```\n\nYou can override these options by creating a `.json` file with your own `compilerOptions` and telling Zwitterion where to locate it with the `--tsc-options-file` command line option. The available options can be found [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html). Options are specified as a JSON object. For example:\n\n`tsc-options.json`:\n\n```JSON\n{\n  \"target\": \"ES5\"\n}\n```\n\nTell Zwitterion where to locate it:\n\n```bash\nzwitterion --tsc-options-file tsc-options.json\n```\n\n### AssemblyScript\n\nAssemblyScript is a new language that compiles a strict subset of TypeScript to WebAssembly. You can learn more about it in [The AssemblyScript Book](https://docs.assemblyscript.org).\n\nZwitterion assumes that AssemblyScript files have the `.as` file extension. This is a Zwitterion-specific extension choice, as the AssemblyScript project has not yet chosen its own official file extension. You can follow that discussion [here](https://github.com/AssemblyScript/assemblyscript/issues/1003). Zwitterion will follow the official extension choice once it is made.\n\nImporting AssemblyScript is nearly identical to importing JavaScript or TypeScript. The key difference is that the default export of your entry AssemblyScript module is a function that returns a promise. This function takes as its one parameter an object containing imports to the AssemblyScript module. \n\nPassing values to and from functions exported from AssemblyScript modules should be straightforward, but there are some limitations. Zwitterion uses [as-bind](https://github.com/torch2424/as-bind) under the hood to broker values to and from AssemblyScript modules. Look there if you need more information.\n\nYou can import AssemblyScript from JavaScript or TypeScript files like this:\n\n`./app.js`:\n\n```javascript\nimport addModuleInit from './add.as';\n\nrunAssemblyScript();\n\nasync function runAssemblyScript() {\n  const adddModule = await addModuleInit();\n\n  console.log(addModule.add(1, 1));\n}\n\n```\n\n`./add.as`:\n\n```typescript\nexport function add(x: i32, y: i32): i32 {\n  return x + y;\n}\n```\n\nIf you want to pass in imports from outside of the AssemblyScript environment, you create a file with export declarations defining the types of the imports. You then pass your imports in as an object to the AssemblyScript module init function. The name of the property that defines your imports for a module must be the exact filename of the file exporting the import declarations. For example:\n\n`./app.js`:\n\n```javascript\nimport addModuleInit from './add.as';\n\nrunAssemblyScript();\n\nasync function runAssemblyScript() {\n  const adddModule = await addModuleInit({\n    'env.as': {\n      log: console.log\n    }\n  });\n\n  console.log(addModule.add(1, 1));\n}\n```\n\n`./env.as`:\n\n```typescript\nexport declare function log(x: number): void;\n```\n\n`./add.as`:\n\n```typescript\nimport { log } from './env.as';\n\nexport function add(x: i32, y: i32): i32 {\n\n  log(x + y);\n\n  return x + y;\n}\n```\n\nYou can also import AssemblyScript from within AssemblyScript files, like so:\n\n`./add.as`:\n\n```typescript\nimport { subtract } from './subtract.as';\n\nexport function add(x: i32, y: i32): i32 {\n  return subtract(x + y, 0);\n}\n```\n\n`./subtract.as`:\n\n```typescript\nexport function subtract(x: i32, y: i32): i32 {\n  return x - y;\n}\n```\n\nBy default, no compiler options have been set. The available options can be found [here](https://docs.assemblyscript.org/details/compiler). You can add options by creating a `.json` file with an array of option names and values, and telling Zwitterion where to locate it with the `--asc-options-file` command line option. For example:\n\n`./asc-options.json`:\n\n```JSON\n[\n  \"--optimizeLevel\", \"3\",\n  \"--runtime\", \"none\",\n  \"--shrinkLevel\", \"2\"\n]\n```\n\nTell Zwitterion where to locate it:\n\n```bash\nzwitterion --asc-options-file asc-options.json\n```\n\n### Rust\n\nRust is a low-level language focused on performance, reliability, and productivity. Learn more [here](https://www.rust-lang.org).\n\nRust support is currently very basic (i.e. no [wasm-bindgen](https://rustwasm.github.io/docs/wasm-bindgen) support). You must have Rust installed on your machine. You can find instructions for installing Rust [here](https://www.rust-lang.org/tools/install). It is a goal of Zwitterion to automatically install a local version of the necessary Rust tooling when Zwitterion is installed, but that is currently a work in progress.\n\nImporting Rust is nearly identical to importing JavaScript or TypeScript. The key difference is that the default export of your entry Rust module is a function that returns a promise. This function takes as its one parameter an object containing imports to the Rust module. You can import Rust from JavaScript or TypeScript files like this:\n\n`./app.js`\n\n```javascript\nimport addModuleInit from './add.rs';\n\nrunRust();\n\nasync function runRust() {\n  const addModule = await addModuleInit();\n\n  console.log(addModule.add(5, 5));\n}\n```\n\n`./add.rs`\n\n```rust\n#![no_main]\n\n#[no_mangle]\npub fn add(x: i32, y: i32) -\u003e i32 {\n  return x + y;\n}\n```\n\n### C\n\nC support is currently very basic. You must have Emscripten installed on your machine. You can find instructions for installing Emscripten [here](https://emscripten.org/docs/getting_started/downloads.html). It is a goal of Zwitterion to automatically install a local version of the necessary C tooling when Zwitterion is installed, but that is currently a work in progress.\n\nImporting C is nearly identical to importing JavaScript or TypeScript. The key difference is that the default export of your entry C module is a function that returns a promise. This function takes as its one parameter an object containing imports to the C module. You can import C from JavaScript or TypeScript files like this:\n\n`./app.js`\n\n```javascript\nimport addModuleInit from './add.c';\n\nrunC();\n\nasync function runC() {\n  const addModule = await addModuleInit();\n\n  console.log(addModule.add(5, 5));\n}\n```\n\n`./add.c`\n\n```c\nint add(int x, int y) {\n  return x + y;\n}\n```\n\n### C++\n\nC++ support is currently very basic. You must have Emscripten installed on your machine. You can find instructions for installing Emscripten [here](https://emscripten.org/docs/getting_started/downloads.html). It is a goal of Zwitterion to automatically install a local version of the necessary C++ tooling when Zwitterion is installed, but that is currently a work in progress.\n\nImporting C++ is nearly identical to importing JavaScript or TypeScript. The key difference is that the default export of your entry C++ module is a function that returns a promise. This function takes as its one parameter an object containing imports to the C++ module. You can import C++ from JavaScript or TypeScript files like this:\n\n`./app.js`\n\n```javascript\nimport addModuleInit from './add.cpp';\n\nrunCPP();\n\nasync function runCPP() {\n  const addModule = await addModuleInit();\n\n  console.log(addModule.add(5, 5));\n}\n```\n\n`./add.cpp`\n\n```c++\nextern \"C\" {\n  int add(int x, int y) {\n    return x + y;\n  }\n}\n\n```\n\n### WebAssembly Text Format (Wat)\n\nWat is a textual representation of the Wasm binary format. It allows Wasm to be more easily written by hand. Learn more [here](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format).\n\nImporting Wat is nearly identical to importing JavaScript or TypeScript. The key difference is that the default export of your entry Wat module is a function that returns a promise. This function takes as its one parameter an object containing imports to the Wat module. You can import Wat from JavaScript or TypeScript files like this:\n\n`./app.js`\n\n```javascript\nimport addModuleInit from './add.wat';\n\nrunWat();\n\nasync function runWat() {\n  const addModule = await addModuleInit();\n\n  console.log(addModule.add(5, 5));\n}\n```\n\n`./add.wat`\n\n```Lisp\n(module\n  (func $add (param $x i32) (param $y i32) (result i32)\n    (i32.add (get_local $x) (get_local $y))\n  )\n  (export \"add\" (func $add))\n)\n```\n\n### WebAssembly (Wasm)\n\nWasm is a binary instruction format built to be efficient, safe, portable, and open. Learn more [here](https://webassembly.org/).\n\nImporting Wasm is nearly identical to importing JavaScript or TypeScript. The key difference is that the default export of your entry Wasm module is a function that returns a promise. This function takes as its one parameter an object containing imports to the Wasm module. You can import Wasm from JavaScript or TypeScript files like this:\n\n`./app.js`\n\n```javascript\nimport addModuleInit from './add.wasm';\n\nrunWasm();\n\nasync function runWasm() {\n  const addModule = await addModuleInit();\n\n  console.log(addModule.add(5, 5));\n}\n```\n\n`./add.wasm`\n\n```\nImagine this is a compiled Wasm binary file with a function called `add`\n```\n\n## Command Line Options\n\n### Port\n\nSpecify the server's port:\n\n```bash\n--port [port]\n```\n\n### Build Static\n\nCreate a static build of the current working directory. The output will be in a directory called dist in the current working directory:\n\n```bash\n--build-static\n```\n\n### Exclude\n\nA comma-separated list of paths, relative to the current directory, to exclude from the static build:\n\n```bash\n--exclude [exclude]\n```\n\n### Include\n\nA comma-separated list of paths, relative to the current directory, to include in the static build\n\n```bash\n--include [include]\n```\n\n### SPA Root\n\nA path to a file, relative to the current directory, to serve as the SPA root. It will be returned for the root path and when a file cannot be found:\n\n```bash\n--spa-root [spaRoot]\n```\n\n### Disable SPA\n\nDisable the SPA redirect to index.html:\n\n```bash\n--disable-spa\n```\n\n### Headers File\n\nA path to a JSON file, relative to the current directory, for custom HTTP headers:\n\n```bash\n--headers-file [headersFile]\n```\n\nCustom HTTP headers are specified as a JSON object with the following shape:\n\n```typescript\ntype CustomHTTPHeaders = {\n    [regexp: string]: HTTPHeaders;\n}\n\ntype HTTPHeaders = {\n    [key: string]: string;\n}\n```\n\nFor example:\n\n`./headers.json`\n\n```json\n{\n  \"^service-worker.ts$\": {\n    \"Service-Worker-Allowed\": \"/\"\n  }\n}\n```\n\n### TSC Options File\n\nA path to a JSON file, relative to the current directory, for tsc compiler options:\n\n```bash\n--tsc-options-file [tscOptionsFile]\n```\n\nThe available options can be found [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html). Options are specified as a JSON object. For example:\n\n`tsc-options.json`:\n\n```JSON\n{\n  \"target\": \"ES5\"\n}\n```\n\n### ASC Options File\n\nA path to a JSON file, relative to the current directory, for asc compiler options:\n\n```bash\n--asc-options-file [ascOptionsFile]\n```\n\nBy default, no compiler options have been set. The available options can be found [here](https://docs.assemblyscript.org/details/compiler). Options are specified as an array of option names and values. For example:\n\n`./asc-options.json`:\n\n```JSON\n[\n  \"--optimizeLevel\", \"3\",\n  \"--runtime\", \"none\",\n  \"--shrinkLevel\", \"2\"\n]\n```\n\n## Special Considerations\n\n### Third-party Packages\n\nThird-party packages must be authored as if they were using Zwitterion. Essentially this means they should be authored in standard JavaScript or TypeScript, and AssemblyScript, Rust, C, and C++ must be authored according to their WebAssembly documentation. Notable exceptions will be explained in this documentation. CommonJS (the require syntax), JSON, HTML, or CSS ES Module imports, and other non-standard features that bundlers commonly support are not suppored in source code.\n\n### Root File\n\nIt's important to note that Zwitterion assumes that the root file (the file found at `/`) of your web application is always an `index.html` file.\n\n### ES Module script elements\n\nZwitterion depends on native browser support for ES modules (import/export syntax). You must add the `type=\"module\"` attribute to script elements that reference modules, for example:\n\n```\n\u003cscript type=\"module\" src=\"amazing-module.ts\"\u003e\u003c/script\u003e\n```\n\n### Performance\n\nIt's important to note that Zwitterion does not bundle files nor engage in tree shaking. This may impact the performance of your application. HTTP2 and ES modules may help with performance, but at this point in time signs tend to point toward worse performance. Zwitterion has plans to improve performance by automatically generating HTTP2 server push information from the static build, and looking into tree shaking, but it is unclear what affect this will have. Stay tuned for more information about performance as Zwitterion matures.\n\nWith all of the above being said, the performance implications are unclear. Measure for yourself.\n\nRead the following for more information on bundling versus not bundling with HTTP2:\n\n* https://medium.com/@asyncmax/the-right-way-to-bundle-your-assets-for-faster-sites-over-http-2-437c37efe3ff\n* https://stackoverflow.com/questions/30861591/why-bundle-optimizations-are-no-longer-a-concern-in-http-2\n* http://engineering.khanacademy.org/posts/js-packaging-http2.htm\n* https://blog.newrelic.com/2016/02/09/http2-best-practices-web-performance/\n* https://mattwilcox.net/web-development/http2-for-front-end-web-developers\n* https://news.ycombinator.com/item?id=9137690\n* https://www.sitepoint.com/file-bundling-and-http2/\n* https://medium.freecodecamp.org/javascript-modules-part-2-module-bundling-5020383cf306\n* https://css-tricks.com/musings-on-http2-and-bundling/\n\n## Under the Hood\n\nZwitterion is simple. It is more or less a static file server, but it rewrites requested files in memory as necessary to return to the client. For example, if a TypeScript file is requested from the client, Zwitterion will retrieve the text of the file, compile it to JavaScript, and then return the compiled text to the client. The same thing is done for JavaScript files. In fact, nearly the same process will be used for any file extension that we want to support in the future. For example, in the future, if a C file is requested it will be read into memory, the text will be compiled to WebAssembly, and the WebAssembly will be returned to the client. All of this compilation is done server-side and hidden from the user. To the user, it's just a static file server.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flastmjs%2Fzwitterion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flastmjs%2Fzwitterion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flastmjs%2Fzwitterion/lists"}