Lustre's CLI and development tooling: zero-config dev server, bundling, and scaffolding.
at main 207 lines 8.5 kB view raw
1//// Lustre's Dev Tools is a CLI (Command Line Interface) that provides a set of commands 2//// for running and building Lustre projects. If you're familiar with frontend Web 3//// development, you could consider the Lustre Dev Tools as something similar to 4//// [vite](https://vitejs.dev) but built right into the framework! If you're not 5//// familiar with what these tools are used for... then read on. 6//// 7//// > **Note**: currently one of lustre_dev_tools' dependencies is not compatible 8//// > with the most recent version of `gleam_json`, making it impossible to install. 9//// > To fix this, add `gleam_json = "1.0.1"` as a dependency in your `gleam.toml` 10//// > file. 11//// 12//// Lustre Dev Tools is written in Gleam and requires **Erlang** to be installed even 13//// if you are only building a JavaScript project. Most methods of installing Gleam 14//// will guide you through installing Erlang too, but make sure you have it installed 15//// before you try to use the Lustre CLI! 16//// 17//// Because the CLI is written in Gleam, you will run it using the `gleam` command. 18//// As an example, starting a development server looks like this: 19//// 20//// ```sh 21//// gleam run -m lustre/dev start 22//// ``` 23//// 24//// <h2 id="add" class="member-name"> 25//// <a href="#add">lustre/dev add</a> 26//// </h2> 27//// 28//// This command lets you install development-specific binaries and tools from outside 29//// the Gleam ecosystem. Lustre tries to be smart about the executables it understands: 30//// if you try to build a project without esbuild it will grab it, if it finds a 31//// tailwind.config.js it will use tailwind, and so on. All binaries are added to 32//// `build/.lustre/bin` in case you need to execute them manually. 33//// 34//// ### `lustre/dev add esbuild` 35//// 36//// [Esbuild](https://esbuild.github.io) is a bundler and build tool for JavaScript 37//// projects. This is the backbone of a lot of Lustre's build tooling and will be 38//// installed automatically if you use `lustre build` or `lustre dev`. 39//// 40//// Example: 41//// 42//// ```sh 43//// gleam run -m lustre/dev add esbuild 44//// ``` 45//// 46//// ### `lustre add tailwind` 47//// 48//// [Tailwind CSS](https://tailwindcss.com) is a utility-first CSS framework popular 49//// among devs that want to quickly iterate on designs without touching CSS directly. 50//// This will be installed automatically if Lustre detects a `tailwind.config.js` file 51//// in your project. 52//// 53//// Example: 54//// 55//// ```sh 56//// gleam run -m lustre/dev add tailwind 57//// ``` 58//// 59//// <h2 id="build" class="member-name"> 60//// <a href="#build">lustre/dev build</a> 61//// </h2> 62//// 63//// Gleam projects can be compiled to JavaScript but this output is not always 64//// desirable for frontend projects where many individual modules can cause HTTP 65//// bottlenecks and slower load times. The `lustre build` command produces different 66//// _bundles_ that are single JavaScript files containing all the code needed for an 67//// application to run. 68//// 69//// If a `lustre build` subcommand is run without the necessary tooling installed, 70//// Lustre will attempt to install it automatically. 71//// 72//// ### `lustre/dev build app` 73//// 74//// Bundle a Gleam application into a single JavaScript file. This requires a Gleam 75//// module in your project with the same name as the project itself, and a public 76//// `main` function that will be called when the application starts. 77//// 78//// _This can be any Gleam program_, but if your `main` function returns an 79//// `App(Nil, model, msg)` then Lustre will automatically generate some boilerplate 80//// to mount the app onto an element with the id `"app"` and start it. 81//// 82//// In addition to bundling, Lustre's dev tools will apply the following 83//// transformations to the output: 84//// 85//// - FFI modules will be copied into Gleam's build directory even if they are 86//// not directly under the `src/` directory. This is a temporary patch until 87//// the Gleam compiler supports this itself. 88//// 89//// - FFI modules that have *relative* imports to `*.gleam` modules will have 90//// their imports rewritten to point to the compiled `*.mjs` files instead. 91//// 92//// Flags: 93//// 94//// - `--minify` - Reduce the size of the output bundle by removing whitespace and 95//// renaming variables. This is useful for production builds. 96//// 97//// Example: 98//// 99//// ```sh 100//// gleam run -m lustre/dev build app 101//// ``` 102//// 103//// ### `lustre/dev build component` 104//// 105//// Lustre components are based on standard Web Components. This means they should 106//// be usable outside of Lustre and Gleam! The `lustre build component` command takes 107//// a module and bundles it into a single JavaScript file that can be included in 108//// _any_ Web app to register a new Custom Element that can be used like native HTML 109//// elements. 110//// 111//// For a module to be bundled as a component, it must adhere to the following rules: 112//// 113//// - There must be a `pub const name` that is a string representing the name of the 114//// component to register. Remember that it must always contain a hyphen and follow 115//// [these rules](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define#valid_custom_element_names). 116//// 117//// - There must be a `pub fn` that has the type `fn() -> App(Nil, model, msg)`. It's 118//// name is not important but in cases where multiple functions in a module fit this 119//// type, the _first_ one will be used. 120//// 121//// In addition to bundling, Lustre's dev tools will apply the following 122//// transformations to the output: 123//// 124//// - FFI modules will be copied into Gleam's build directory even if they are 125//// not directly under the `src/` directory. This is a temporary patch until 126//// the Gleam compiler supports this itself. 127//// 128//// - FFI modules that have *relative* imports to `*.gleam` modules will have 129//// their imports rewritten to point to the compiled `*.mjs` files instead. 130//// 131//// Arguments: 132//// 133//// - `<module_path>` - The path to the Lustre component you want to bundle. This should 134//// be in the same format that you would write to import the module in a Gleam file, 135//// e.g. `ui/my_componnt` and **not** `src/ui/my_component.gleam`. 136//// 137//// Flags: 138//// 139//// - `--minify` - Reduce the size of the output bundle by removing whitespace and 140//// renaming variables. This is useful for production builds. 141//// 142//// Example: 143//// 144//// ```sh 145//// gleam run -m lustre/dev build component ui/counter 146//// ``` 147//// 148//// <h2 id="start" class="member-name"> 149//// <a href="#start">lustre/dev start</a> 150//// </h2> 151//// 152//// The `lustre/dev start` command starts a development server that builds and serves your 153//// project. This lets you focus on development without having to worry about a backend 154//// or additional tooling. The page will automatically reload when you make changes 155//// to your project. 156//// 157//// Flags: 158//// 159//// - `--port` - The port to serve the project on. Defaults to `1234`. 160//// 161//// Example: 162//// 163//// ```sh 164//// gleam run -m lustre/dev start --port=8080 165//// ``` 166//// 167//// ## Getting help 168//// 169//// Lustre Dev Tools is still an experimental work in progress. If you run in to issues 170//// or have ideas for how it could be improved we'd love to hear from you, either by 171//// [opening an issue](https://github.com/lustre-labs/dev-tools/issues) or reaching out 172//// on the [Gleam Discord server](https://discord.gg/Fm8Pwmy). 173//// 174 175// IMPORTS --------------------------------------------------------------------- 176 177import argv 178import glint 179import lustre_dev_tools/cli/add 180import lustre_dev_tools/cli/build 181import lustre_dev_tools/cli/start 182 183// MAIN ------------------------------------------------------------------------ 184 185/// The `main` function is used as the entry point for Lustre's dev tools. You 186/// shouldn't run this function in your code, but instead use `Gleam run` to run 187/// this module from the command line. To see what the dev tools can do, run: 188/// 189/// ``` 190/// gleam run -m lustre/dev -- --help 191/// ``` 192/// 193pub fn main() { 194 let args = argv.load().arguments 195 196 glint.new() 197 |> glint.as_module 198 |> glint.with_name("lustre/dev") 199 |> glint.path_help(["add"], add.description) 200 |> glint.add(at: ["add", "esbuild"], do: add.esbuild()) 201 |> glint.add(at: ["add", "tailwind"], do: add.tailwind()) 202 |> glint.add(at: ["build"], do: build.app()) 203 |> glint.add(at: ["build", "app"], do: build.app()) 204 |> glint.add(at: ["build", "component"], do: build.component()) 205 |> glint.add(at: ["start"], do: start.run()) 206 |> glint.run(args) 207}