nuxt-bun-compile 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ {
2
+ "recommendations": [
3
+ "dprint.dprint",
4
+ "nuxtr.nuxtr-vscode",
5
+ "usernamehw.errorlens",
6
+ "oderwat.indent-rainbow",
7
+ "ms-vscode.vscode-typescript-next",
8
+ "davidanson.vscode-markdownlint",
9
+ "pkief.material-icon-theme",
10
+ "yoavbls.pretty-ts-errors",
11
+ "pflannery.vscode-versionlens",
12
+ "fab1o.dark-plus-with-italics"
13
+ ]
14
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "dprint.path": "./node_modules/.bin/dprint",
3
+ "editor.formatOnSave": true,
4
+ "editor.formatOnSaveMode": "modificationsIfAvailable",
5
+ "files.trimTrailingWhitespace": true,
6
+ "explorer.fileNesting.enabled": true,
7
+ "editor.defaultFormatter": "dprint.dprint",
8
+ "editor.gotoLocation.multipleDefinitions": "goto",
9
+ "editor.gotoLocation.multipleTypeDefinitions": "goto",
10
+ "editor.rulers": [
11
+ 80,
12
+ 100,
13
+ 120
14
+ ]
15
+ }
package/README.md ADDED
@@ -0,0 +1,243 @@
1
+ # nuxt-bun-compile
2
+
3
+ > πŸš€ Nuxt module that automatically configures Nitro for `bun build --compile`, generating a **standalone executable binary** from your Nuxt app β€” zero runtime dependencies needed.
4
+
5
+ [Leia em PortuguΓͺs](README.ptBR.md)
6
+
7
+ ---
8
+
9
+ > **⚠️ IMPORTANT: Use `bun run -b build` to generate the binary**
10
+ >
11
+ > The following commands **DO NOT** trigger binary compilation:
12
+ > ```bash
13
+ > bun run build # ❌ does not generate the binary
14
+ > npm run build # ❌ does not generate the binary
15
+ > pnpm run build # ❌ does not generate the binary
16
+ > ```
17
+ >
18
+ > The correct command is:
19
+ > ```bash
20
+ > bun run -b build # βœ… generates the binary (nuxtbin or the name set in outfile)
21
+ > ```
22
+ >
23
+ > [Why is `-b` required?](https://github.com/jprando/nuxt-bun-compile?tab=readme-ov-file#why-is--b-required)
24
+
25
+ ---
26
+
27
+ ## ⚑ Quick Start
28
+
29
+ ```bash
30
+ # Install directly from GitHub
31
+ bun add -D github:jprando/nuxt-bun-compile
32
+
33
+ # Or link locally for development
34
+ git clone https://github.com/jprando/nuxt-bun-compile.git
35
+ cd nuxt-bun-compile && bun install && bun link
36
+ cd your-nuxt-app && bun link nuxt-bun-compile
37
+ ```
38
+
39
+ Add to your `nuxt.config.ts`:
40
+
41
+ ```ts
42
+ export default defineNuxtConfig({
43
+ modules: ["nuxt-bun-compile"],
44
+ bunCompile: {
45
+ outfile: "myapp",
46
+ },
47
+ })
48
+ ```
49
+
50
+ Build and run:
51
+
52
+ ```bash
53
+ NODE_OPTIONS="--max-old-space-size=8192" bun run -b build
54
+ ./myapp
55
+ ```
56
+
57
+ That's it. One binary. No `node_modules`. No runtime. Just your app.
58
+
59
+ ---
60
+
61
+ ## 🎯 What It Does
62
+
63
+ The module hooks into Nuxt's build pipeline and handles **everything** automatically:
64
+
65
+ 1. **Configures Nitro** with the optimal settings for binary compilation
66
+ 2. **Externalizes problematic packages** that break with full bundling
67
+ 3. **Runs `bun build --compile`** after the build to produce a standalone executable
68
+
69
+ ### Nitro Configuration (auto-applied)
70
+
71
+ | Setting | Value | Why |
72
+ |---|---|---|
73
+ | `preset` | `"bun"` | Target the Bun runtime |
74
+ | `noExternals` | `true` | Bundle everything into the output |
75
+ | `inlineDynamicImports` | `true` | Flatten dynamic imports for single-file output |
76
+ | `serveStatic` | `"inline"` | Embed static assets in the binary |
77
+ | `esbuild.options.target` | `"esnext"` | Use latest JS features for maximum performance |
78
+
79
+ ---
80
+
81
+ ## βš™οΈ Options
82
+
83
+ | Option | Type | Default | Description |
84
+ |---|---|---|---|
85
+ | `enabled` | `boolean` | `true` | Enable/disable the module |
86
+ | `outfile` | `string` | `"nuxtbin"` | Output binary filename |
87
+ | `bunPath` | `string` | `undefined` | Path to the bun executable. Can be a directory (e.g., `/opt/bun/`) or a direct path to the binary (e.g., `/opt/bun/bun`). If it's a directory, '/bun' will be appended. Defaults to 'bun' from the system's PATH. |
88
+ | `extraExternals` | `(string \| RegExp)[]` | `[]` | Additional packages to mark as external |
89
+ | `autoCompile` | `boolean` | `true` | Run `bun build --compile` automatically after build |
90
+
91
+ ---
92
+
93
+ ## πŸ“¦ Default External Packages
94
+
95
+ These packages are known to break with `noExternals: true` and are excluded by default:
96
+
97
+ | Package | Pattern |
98
+ |---|---|
99
+ | sharp | `sharp` |
100
+ | @img | `@img/*` |
101
+ | css-tree | `css-tree`, `css-tree/*` |
102
+ | csso | `csso`, `csso/*` |
103
+ | svgo | `svgo` |
104
+ | mdn-data | `mdn-data`, `mdn-data/*` |
105
+
106
+ Need to add more? Use `extraExternals`:
107
+
108
+ ```ts
109
+ bunCompile: {
110
+ extraExternals: ["problematic-package", /^@scope\//],
111
+ }
112
+ ```
113
+
114
+ > **⚠️ Important:** Libraries listed in `extraExternals` (as well as the default externals) are **not embedded in the binary**. For the `nuxtbin` binary to run correctly, these dependencies must be available in a `node_modules` folder alongside the generated binary.
115
+
116
+ ---
117
+
118
+ ## πŸ—οΈ Architecture
119
+
120
+ ```
121
+ src/
122
+ module.ts # Main module β€” configures Nitro + auto-compiles
123
+ package.json
124
+ tsconfig.json
125
+ dprint.json # Code formatter config
126
+ ```
127
+
128
+ The module uses a **hook-based architecture**:
129
+
130
+ - **`nitro:config`** β€” Adjusts Nitro settings (preset, externals, bundling)
131
+ - **`nitro:compiled`** β€” Triggers `bun build --compile` after Nitro finishes building the server
132
+
133
+ ### How It Works
134
+
135
+ ```
136
+ bun run -b build
137
+ β”‚
138
+ β”œβ”€ nitro:config hook ──▢ Configure preset, bundling, externals
139
+ β”‚
140
+ β”œβ”€ Nuxt/Nitro build pipeline runs normally
141
+ β”‚
142
+ └─ nitro compiled hook ──▢ bun build .output/server/index.mjs --compile --outfile <name>
143
+ β”‚
144
+ └──▢ πŸŽ‰ Standalone binary ready!
145
+ ```
146
+
147
+ ### Why is `-b` required?
148
+
149
+ When you run `bun run build`, Bun acts as a **task runner** and may delegate script execution to Node.js. In that scenario, `globalThis.Bun` and `process.versions.bun` **do not exist**, and the module cannot detect the Bun runtime:
150
+
151
+ ```ts
152
+ const isBun = typeof globalThis.Bun !== "undefined"
153
+ || process.versions.bun !== undefined;
154
+ ```
155
+ [src/module.ts:L70-L76](https://github.com/jprando/nuxt-bun-compile/blob/main/src/module.ts#L70-L76)
156
+
157
+ The **`-b`** (or `--bun`) flag forces Bun to be the runtime that executes the script. With it, the variables above become available and the `bun build --compile` step runs correctly.
158
+
159
+ ---
160
+
161
+ ## πŸ› οΈ Tech Stack
162
+
163
+ | | Technology | Details |
164
+ |---|---|---|
165
+ | πŸ”€ | **TypeScript** | ESNext target, strict mode, bundler resolution |
166
+ | 🐰 | **Bun** | Runtime 1.3.9+, package manager |
167
+ | πŸ’š | **Nuxt** | 3.x / 4.x via `@nuxt/kit` + `@nuxt/schema` |
168
+ | πŸ“ | **dprint** | Code formatter (TS, JSON, MD, TOML, YAML, and more) |
169
+ | πŸ“¦ | **ESM** | Pure ES modules (`"type": "module"`) |
170
+
171
+ ---
172
+
173
+ ## πŸ§‘β€πŸ’» Development
174
+
175
+ ### Commands
176
+
177
+ ```bash
178
+ # Install dependencies
179
+ bun install
180
+
181
+ # Format code
182
+ bun run format
183
+
184
+ # Link for local testing
185
+ bun link
186
+ ```
187
+
188
+ ### Code Style
189
+
190
+ - **Formatter:** dprint β€” always run `bun run format` before committing
191
+ - **Strings:** Double quotes
192
+ - **Semicolons:** Yes
193
+ - **Constants:** `UPPER_SNAKE_CASE` for module-level (`DEFAULT_EXTERNALS`)
194
+ - **Types:** `interface` for public APIs, `import type` for type-only imports
195
+ - **Node built-ins:** Use `node:` prefix (e.g. `node:child_process`)
196
+
197
+ ### Testing Locally in a Nuxt App
198
+
199
+ ```bash
200
+ # 1. Link the module
201
+ cd nuxt-bun-compile && bun link
202
+
203
+ # 2. Use it in your Nuxt app
204
+ cd your-nuxt-app && bun link nuxt-bun-compile
205
+
206
+ # 3. Add to nuxt.config.ts modules array
207
+
208
+ # 4. Build
209
+ NODE_OPTIONS="--max-old-space-size=8192" bun run -b build
210
+
211
+ # 5. Run the binary
212
+ ./nuxtbin
213
+ ```
214
+
215
+ ---
216
+
217
+ ## βœ… Requirements
218
+
219
+ - [Bun](https://bun.sh) 1.3.9+ (for the `--compile` step)
220
+ - Nuxt 3.x / 4.x
221
+ - Node 24+ (when not using Bun as runtime)
222
+
223
+ ---
224
+
225
+ ## πŸ“ Notes
226
+
227
+ ### Why `NODE_OPTIONS="--max-old-space-size=8192"`?
228
+
229
+ The Nuxt build process with `noExternals: true` and `inlineDynamicImports: true` causes Rollup/esbuild to bundle **all** dependencies into a single output. In projects with many dependencies, this can consume more memory than the default V8 heap limit (approximately 1.5–2 GB), resulting in the error:
230
+
231
+ ```
232
+ FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
233
+ ```
234
+
235
+ The `NODE_OPTIONS="--max-old-space-size=8192"` variable increases the V8 heap memory limit to 8 GB, providing enough headroom for the bundling process to complete. The value of `8192` (MB) is a safe reference for most projects β€” adjust as needed for larger projects or machines with less RAM.
236
+
237
+ > **Note:** This variable affects the Node.js/V8 process that runs the Nuxt build, not the final binary generated by `bun build --compile`.
238
+
239
+ ---
240
+
241
+ ## πŸ“„ License
242
+
243
+ MIT
package/README.ptBR.md ADDED
@@ -0,0 +1,243 @@
1
+ # nuxt-bun-compile
2
+
3
+ > πŸš€ Modulo Nuxt que configura automaticamente o Nitro para `bun build --compile`, gerando um **binario executavel standalone** a partir da sua aplicacao Nuxt β€” sem dependencias de runtime.
4
+
5
+ [Read in English](README.md)
6
+
7
+ ---
8
+
9
+ > **⚠️ IMPORTANTE: Use `bun run -b build` para gerar o binario**
10
+ >
11
+ > Os comandos abaixo **NAO** acionam a compilacao do binario:
12
+ > ```bash
13
+ > bun run build # ❌ nao gera o binario
14
+ > npm run build # ❌ nao gera o binario
15
+ > pnpm run build # ❌ nao gera o binario
16
+ > ```
17
+ >
18
+ > O comando correto eh:
19
+ > ```bash
20
+ > bun run -b build # βœ… gera o binario (nuxtbin ou o nome definido em outfile)
21
+ > ```
22
+ >
23
+ > [Por que Γ© necessΓ‘rio o parΓ’metro `-b`?](https://github.com/jprando/nuxt-bun-compile/blob/main/README.ptBR.md#por-que-o--b-eh-obrigatorio)
24
+
25
+ ---
26
+
27
+ ## ⚑ Inicio Rapido
28
+
29
+ ```bash
30
+ # Instalar diretamente do GitHub
31
+ bun add -D github:jprando/nuxt-bun-compile
32
+
33
+ # Ou linkar localmente para desenvolvimento
34
+ git clone https://github.com/jprando/nuxt-bun-compile.git
35
+ cd nuxt-bun-compile && bun install && bun link
36
+ cd sua-app-nuxt && bun link nuxt-bun-compile
37
+ ```
38
+
39
+ Adicione ao seu `nuxt.config.ts`:
40
+
41
+ ```ts
42
+ export default defineNuxtConfig({
43
+ modules: ["nuxt-bun-compile"],
44
+ bunCompile: {
45
+ outfile: "myapp",
46
+ },
47
+ })
48
+ ```
49
+
50
+ Build e execucao:
51
+
52
+ ```bash
53
+ NODE_OPTIONS="--max-old-space-size=8192" bun run -b build
54
+ ./myapp
55
+ ```
56
+
57
+ So isso. Um binario. Sem `node_modules`. Sem runtime. Apenas sua aplicacao.
58
+
59
+ ---
60
+
61
+ ## 🎯 O que faz
62
+
63
+ O modulo se conecta ao pipeline de build do Nuxt e cuida de **tudo** automaticamente:
64
+
65
+ 1. **Configura o Nitro** com as configuracoes otimas para compilacao em binario
66
+ 2. **Externaliza pacotes problematicos** que quebram com bundling completo
67
+ 3. **Executa `bun build --compile`** apos o build para produzir um executavel standalone
68
+
69
+ ### Configuracao do Nitro (aplicada automaticamente)
70
+
71
+ | Configuracao | Valor | Motivo |
72
+ |---|---|---|
73
+ | `preset` | `"bun"` | Usar o runtime Bun como alvo |
74
+ | `noExternals` | `true` | Empacotar tudo no output |
75
+ | `inlineDynamicImports` | `true` | Achatar imports dinamicos para output em arquivo unico |
76
+ | `serveStatic` | `"inline"` | Embutir assets estaticos no binario |
77
+ | `esbuild.options.target` | `"esnext"` | Usar as features JS mais recentes para maximo desempenho |
78
+
79
+ ---
80
+
81
+ ## βš™οΈ Opcoes
82
+
83
+ | Opcao | Tipo | Padrao | Descricao |
84
+ |---|---|---|---|
85
+ | `enabled` | `boolean` | `true` | Habilitar/desabilitar o modulo |
86
+ | `outfile` | `string` | `"nuxtbin"` | Nome do arquivo binario de saida |
87
+ | `bunPath` | `string` | `undefined` | Caminho para o executΓ‘vel do bun. Pode ser um diretΓ³rio (ex: `/opt/bun/`) ou o caminho direto para o binΓ‘rio (ex: `/opt/bun/bun`). Se for um diretΓ³rio, '/bun' serΓ‘ anexado. O padrΓ£o Γ© 'bun' do PATH do sistema. |
88
+ | `extraExternals` | `(string \| RegExp)[]` | `[]` | Pacotes adicionais para marcar como external |
89
+ | `autoCompile` | `boolean` | `true` | Executar `bun build --compile` automaticamente apos o build |
90
+
91
+ ---
92
+
93
+ ## πŸ“¦ Pacotes External Padrao
94
+
95
+ Estes pacotes sao conhecidos por quebrar com `noExternals: true` e sao excluidos por padrao:
96
+
97
+ | Pacote | Pattern |
98
+ |---|---|
99
+ | sharp | `sharp` |
100
+ | @img | `@img/*` |
101
+ | css-tree | `css-tree`, `css-tree/*` |
102
+ | csso | `csso`, `csso/*` |
103
+ | svgo | `svgo` |
104
+ | mdn-data | `mdn-data`, `mdn-data/*` |
105
+
106
+ Precisa adicionar mais? Use `extraExternals`:
107
+
108
+ ```ts
109
+ bunCompile: {
110
+ extraExternals: ["problematic-package", /^@scope\//],
111
+ }
112
+ ```
113
+
114
+ > **⚠️ Importante:** As bibliotecas listadas em `extraExternals` (assim como as externals padrao) **nao sao embutidas no binario**. Para que o binario `nuxtbin` execute corretamente, essas dependencias precisam estar disponiveis em uma pasta `node_modules` ao lado do binario gerado.
115
+
116
+ ---
117
+
118
+ ## πŸ—οΈ Arquitetura
119
+
120
+ ```
121
+ src/
122
+ module.ts # Modulo principal β€” configura o Nitro + auto-compila
123
+ package.json
124
+ tsconfig.json
125
+ dprint.json # Configuracao do formatador de codigo
126
+ ```
127
+
128
+ O modulo usa uma **arquitetura baseada em hooks**:
129
+
130
+ - **`nitro:config`** β€” Ajusta configuracoes do Nitro (preset, externals, bundling)
131
+ - **`nitro:compiled`** β€” Aciona `bun build --compile` apos o Nitro terminar o build do servidor
132
+
133
+ ### Como Funciona
134
+
135
+ ```
136
+ bun run -b build
137
+ β”‚
138
+ β”œβ”€ hook nitro:config ──▢ Configura preset, bundling, externals
139
+ β”‚
140
+ β”œβ”€ Pipeline de build Nuxt/Nitro executa normalmente
141
+ β”‚
142
+ └─ hook nitro compiled ──▢ bun build .output/server/index.mjs --compile --outfile <nome>
143
+ β”‚
144
+ └──▢ πŸŽ‰ Binario standalone pronto!
145
+ ```
146
+
147
+ ### Por que o `-b` eh obrigatorio?
148
+
149
+ Quando voce executa `bun run build`, o Bun age como um **gerenciador de tarefas** e pode delegar a execucao do script ao Node.js. Nesse cenario, as variaveis `globalThis.Bun` e `process.versions.bun` **nao existem**, e o modulo nao consegue detectar o runtime Bun:
150
+
151
+ ```ts
152
+ const isBun = typeof globalThis.Bun !== "undefined"
153
+ || process.versions.bun !== undefined;
154
+ ```
155
+ [src/module.ts:L70-L76](https://github.com/jprando/nuxt-bun-compile/blob/main/src/module.ts#L70-L76)
156
+
157
+ O parametro **`-b`** (ou `--bun`) forca o Bun a ser o runtime que executa o script. Com ele, as variaveis acima ficam disponiveis e a etapa de `bun build --compile` eh executada corretamente.
158
+
159
+ ---
160
+
161
+ ## πŸ› οΈ Tech Stack
162
+
163
+ | | Tecnologia | Detalhes |
164
+ |---|---|---|
165
+ | πŸ”€ | **TypeScript** | Target ESNext, strict mode, bundler resolution |
166
+ | 🐰 | **Bun** | Runtime 1.3.9+, gerenciador de pacotes |
167
+ | πŸ’š | **Nuxt** | 3.x / 4.x via `@nuxt/kit` + `@nuxt/schema` |
168
+ | πŸ“ | **dprint** | Formatador de codigo (TS, JSON, MD, TOML, YAML e mais) |
169
+ | πŸ“¦ | **ESM** | ES modules puro (`"type": "module"`) |
170
+
171
+ ---
172
+
173
+ ## πŸ§‘β€πŸ’» Desenvolvimento
174
+
175
+ ### Comandos
176
+
177
+ ```bash
178
+ # Instalar dependencias
179
+ bun install
180
+
181
+ # Formatar codigo
182
+ bun run format
183
+
184
+ # Linkar para testes locais
185
+ bun link
186
+ ```
187
+
188
+ ### Estilo de Codigo
189
+
190
+ - **Formatador:** dprint β€” sempre execute `bun run format` antes de commitar
191
+ - **Strings:** Aspas duplas
192
+ - **Ponto e virgula:** Sim
193
+ - **Constantes:** `UPPER_SNAKE_CASE` para nivel de modulo (`DEFAULT_EXTERNALS`)
194
+ - **Tipos:** `interface` para APIs publicas, `import type` para imports somente de tipo
195
+ - **Built-ins do Node:** Use prefixo `node:` (ex: `node:child_process`)
196
+
197
+ ### Testando Localmente em uma App Nuxt
198
+
199
+ ```bash
200
+ # 1. Linkar o modulo
201
+ cd nuxt-bun-compile && bun link
202
+
203
+ # 2. Usar na sua app Nuxt
204
+ cd sua-app-nuxt && bun link nuxt-bun-compile
205
+
206
+ # 3. Adicionar ao array modules no nuxt.config.ts
207
+
208
+ # 4. Build
209
+ NODE_OPTIONS="--max-old-space-size=8192" bun run -b build
210
+
211
+ # 5. Executar o binario
212
+ ./nuxtbin
213
+ ```
214
+
215
+ ---
216
+
217
+ ## βœ… Requisitos
218
+
219
+ - [Bun](https://bun.sh) 1.3.9+ (para a etapa de `--compile`)
220
+ - Nuxt 3.x / 4.x
221
+ - Node 24+ (quando nao usar Bun como runtime)
222
+
223
+ ---
224
+
225
+ ## πŸ“ Notas
226
+
227
+ ### Por que `NODE_OPTIONS="--max-old-space-size=8192"`?
228
+
229
+ O processo de build do Nuxt com `noExternals: true` e `inlineDynamicImports: true` faz com que o Rollup/esbuild tente empacotar **todas** as dependencias em um unico bundle. Em projetos com muitas dependencias, isso pode consumir mais memoria do que o limite padrao do V8 (aproximadamente 1.5–2 GB), causando o erro:
230
+
231
+ ```
232
+ FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
233
+ ```
234
+
235
+ A variavel `NODE_OPTIONS="--max-old-space-size=8192"` aumenta o limite de memoria heap do V8 para 8 GB, dando margem suficiente para que o bundling termine sem estourar a memoria. O valor de `8192` (MB) eh uma referencia segura para a maioria dos projetos β€” ajuste conforme necessario para projetos maiores ou maquinas com menos RAM.
236
+
237
+ > **Nota:** Essa variavel afeta o processo do Node.js/V8 que roda o build do Nuxt, e nao o binario final gerado pelo `bun build --compile`.
238
+
239
+ ---
240
+
241
+ ## πŸ“„ Licenca
242
+
243
+ MIT