- 编程语言
- 编译器
- 语言运行时
【免费下载链接】imba
🐤 The friendly full-stack language
导读:本篇文章以imba仓库内 packages/create-imba/PLAN.md 为核心骨架,完整拆解「用npm create imba一键创建 Imba 项目」这一能力从设计、实现到验证的全过程。你将掌握该独立脚手架包的目标定位、CLI 全部参数、四种内置模板的差异、交互式与非交互式两条流程的底层源码逻辑,以及基于 esbuild + Imba 编译器构建零运行时依赖发布物的完整工程方案。
一、背景:imba create被移除后留下的断档
create-imba这个包诞生的直接原因是一个真实的兼容性事故:官方文档(快速上手、首页、基础语法等页面)长期以来引导用户执行npx imba create,但该命令在主包中被提交6afea2e1(2026-05-30,提交信息为 "Remove imba create")删除后,没有任何替代命令,导致用户执行时报错Could not resolve "create"。
PLAN.md 明确给出了修复目标:
make
npm create imba(andnpx create-imba) work again by building a small standalone scaffolder package in this monorepo, and re-add a thinimba createalias in the main CLI that delegates to it.
即:在本 monorepo 中新建一个独立脚手架包,同时在主 CLI 中恢复一个只做委托的薄别名imba create,让两种入口都重新可用。
围绕这个目标,PLAN.md 记录了一批已经核实的仓库事实(核对日期 2026-08-13),它们是后续所有设计决策的依据:
| 事实 | 内容 |
|---|---|
| 旧实现可恢复 | git show 6afea2e1^:packages/imba/bin/create.imba可还原出约 170 行的旧源码,包含prompts交互流程、haikunator 随机项目名、_gitignore→.gitignore重命名、noCopy排除列表 |
| 旧 CLI 接线 | 旧版bin/imba.imba(约 296 行处)注册过create [name],带-t, --template、-y, --yes、--fast三个选项 |
| 四个模板仍存在 | packages/imba/templates/{default,express,module,cli}在 HEAD 依然完好,且templates仍在packages/imba/package.json的files数组(约 50 行)中,随每个 imba tarball 发布,但因命令被删而完全不可达 |
| npm 名称未被占用 | create-imba在 npm 上未注册(404),可安全使用;已发布的imba为2.0.0-alpha.253,与仓库版本一致 |
| 工程约束 | monorepo 使用 lerna(lerna.json当前只列packages/imba)+ npm workspaces;imba 要求 node>=20.19.0;主 CLI 二进制为packages/imba/bin/imba→ 预编译的bin/imba.imba.js |
| 旧依赖清单 | 旧 create 实现依赖prompts、cross-spawn、haikunator,在还原源码前需确认这些依赖是否仍存在于packages/imba/package.json |
二、总体设计:七个已拍板的决策
PLAN.md 明确标注这些决策「已定案,不再反复讨论」(settled — don't relitigate),构成整个方案的设计基线:
- 新建独立包
packages/create-imba,npm 名为create-imba,bin 名为create-imba。这是npm create imba/pnpm create imba/bun create imba能被解析的根本原因。版本0.1.0,MIT 许可,engines node>=18。 - 迁移模板:把模板从
packages/imba/templates/通过git mv移入packages/create-imba/templates/,并从 imba 的files数组中移除"templates"。模板随 create-imba 包发布(体积很小),v1 不做网络拉取 / degit。 - 移植而非重写:以还原出的
create.imba为起点,保留 prompts 流程、haikunator 默认名、_gitignore重命名、noCopy列表及三个 CLI 选项,同时更新过期内容(模板描述、脚本与依赖需对照 cli.md 校准)。 - 源码用 Imba 写、bin 是编译后的 JS:
npx create-imba直接用 node 执行 bin,因此 bin 不能是.imba文件。源码放在src/create.imba,构建脚本产出单个自包含的bin/create-imba.js,把依赖全部打包进发布物,使发布包零运行时依赖。 - 模板刷新:脚手架出的
package.json应写入所选项目名,并把"imba": "*"替换为"imba": "^2.0.0-alpha.253"(或从packages/imba/package.json构建时读取的当前版本),同时保证dev/build脚本可用;还要验证 express 模板的服务器入口与当前imba的 serve 方式一致。 - 主 CLI 恢复
imba create别名:在packages/imba/bin/imba.imba中加一个只做委托的create命令——spawnnpx create-imba@latest并透传参数(win32 下用shell: true),主包不携带任何脚手架逻辑。 - 工作区接线:把
packages/create-imba加入根package.json的workspaces与lerna.json的 packages 列表。
三、包形态:package.json 与发布物构成
当前仓库中 packages/create-imba/package.json 的实态如下(与 PLAN 决策一致):
{ "name": "create-imba", "version": "0.1.0", "description": "Scaffold a new Imba project", "license": "MIT", "bin": { "create-imba": "./bin/create-imba.js" }, "files": [ "bin", "templates" ], "engines": { "node": ">=18" }, "scripts": { "build": "node scripts/build.js", "prepack": "npm run build" }, "devDependencies": { "cross-spawn": "^7.0.6", "esbuild": "^0.24.2", "haikunator": "^2.1.2", "prompts": "^2.4.2" } }几个值得注意的设计要点:
files只含bin与templates:发布物就是「可执行文件 + 四套模板」,src/与scripts/不随包分发。prepack钩子保证npm pack前自动执行构建,因此即使没有 CI,也能直接发布。- 依赖全部放在
devDependencies:prompts、cross-spawn、haikunator、esbuild都只是构建期依赖,运行时被打进单个 bundle,实现了 PLAN 决策 4 的「零运行时依赖」目标。 - engines 只要求 node
>=18:这比 imba 主包(>=20.19.0)更宽松,降低脚手架工具本身的使用门槛;源码中另外对旧版 node 给出了黄色警告(见下文源码分析)。
仓库根目录下的packages/create-imba/实际文件布局为:
packages/create-imba/ ├── PLAN.md ├── README.md ├── package.json ├── scripts/ │ └── build.js # esbuild + imba 编译器,产出 bin/create-imba.js ├── src/ │ ├── colors.imba # 终端着色 │ ├── create.imba # 脚手架主逻辑(Imba 源码) │ └── runtime-shim.js # 打包时替换 imba/runtime 的最小运行时 ├── bin/ │ └── create-imba.js # 预编译产物(构建生成) └── templates/ ├── default/ ├── express/ ├── module/ └── cli/四、CLI 用法与全部参数
packages/create-imba/README.md 给出了最简用法与参数表:
npm create imba@latest同一入口也适用于pnpm create imba、bun create imba,或直接npx create-imba。命令形式为create-imba [name] [options]:不带参数进入交互式安装向导;传入项目名则直接使用(用.表示当前目录)。
| 选项 | 说明 |
|---|---|
-t, --template [template] | 指定模板:default、express、module、cli |
-y, --yes | 对所有确认提示一律回答 yes |
--fast | 随机项目名 + 全部默认答案,只打印生成目录名(供 shell 脚本使用) |
-v, --version | 打印 create-imba 版本号 |
-h, --help | 显示帮助信息 |
这五个选项在源码src/create.imba的parseArgv中逐项解析:-t/--template消费下一个参数作为模板名,-y/--yes、--fast、-h/--help、-v/--version均为布尔开关;遇到未知-开头参数输出Unknown option: ...并退出,位置参数超过一个则报Unexpected argument。run入口按help→version→main的顺序分发。
五、四种内置模板详解
PLAN 决策 2 把模板从 imba 主包迁入 create-imba 后,四套模板当前都在 packages/create-imba/templates/ 下。其定位与package.json实态如下:
1. default —— 纯客户端应用
描述:Client only application。包含index.html、src/main.imba、_gitignore。核心脚本:
"scripts": { "dev": "imba -w index.html", "build": "imba build index.html" }, "devDependencies": { "imba": "*" }src/main.imba演示了一个最精简的 Imba 单页组件:global css设置页面级样式(body c:warm2 bg:warm8 ff:Arial inset:0 d:vcc),tag app声明组件与响应式状态count = 0,<%counter @click=count++>绑定点击事件,内联 CSS 使用e:250ms us:none、@hover:indigo5等 Imba 风格语法,最后imba.mount <app>挂载。
2. express —— Express 全栈应用
描述:Full stack application with an Express server。在 default 基础上多出server.imba与express运行时依赖:
"scripts": { "dev": "imba -w server.imba", "build": "imba build server.imba", "preview": "node dist/server.js", "prod": "npx pm2 start dist/server.js" }, "dependencies": { "express": "*" }, "devDependencies": { "imba": "*" }server.imba展示了 Imba 的imba.serve用法:
import index from './index.html' import express from 'express' const app = express! const port = process.env.PORT or 3000 app.get '/' do(req, res) res.send index.body imba.serve app.listen(port)注意imba -w server.imba会同时编译并监听服务器代码,preview直接运行编译产物dist/server.js,prod则交给 pm2 托管——这是 PLAN 决策 5 中「verify the express template's server entry still matches how imba serves today」要重点校验的部分。
3. module —— 可被任意 JS 项目使用的模块
描述:A module that can be used in any JavaScript project。ESM 形态、面向库作者:
"type": "module", "files": ["dist"], "main": "./dist/main.mjs", "module": "./dist/main.mjs", "exports": { ".": "./dist/main.mjs" }, "scripts": { "dev": "imba -w index.html", "build": "imba build src/main.imba --esm", "watch": "imba build -w src/main.imba --esm" }模板特意将产物声明为.mjs并通过exports字段暴露,还配套watch脚本做增量构建。
4. cli —— 可发布到 npm 的 CLI 工具
描述:A CLI tool ready for npm publishing。自带bin映射、版本管理与打包检查脚本:
"bin": { "imba-project": "bin" }, "version": "0.0.0", "scripts": { "test": "./bin blue! -c blue", "dev": "imba build -w main.imba", "build": "imba build main.imba", "sync": "npm i && npm run build && npm link", "prepack": "npm i && npm run build", "check": "npm pack --dry-run" }, "dependencies": { "commander": "*" }main.imba给出了用commander写 CLI 的范式:global.E统一错误出口、import { program } from 'commander'定义name/description/argument/option,--version从./package.json注入,showHelpAfterError!让出错时自动打印帮助。
说明:以上四个模板的
package.json中"imba": "*"是迁移前的旧态。按 PLAN 决策 5,脚手架时create.imba会通过npm pkg set把它改写为形如^2.0.0-alpha.253的固定版本(详见第七节),这正是「模板刷新」要落地的内容之一。
六、源码实现:交互流程与关键机制
核心逻辑全部在 packages/create-imba/src/create.imba(约 220 行),完整覆盖 PLAN 要求的「移植而非重写」范围。下面按执行顺序拆解其关键机制。
1. 环境与常量注入
const cwd = process.cwd! const swd = __dirname require './colors' const prompt = require 'prompts' const spawn = require 'cross-spawn' const Haikunator = require 'haikunator' # Injected by scripts/build.js via esbuild define const imbaVersion = typeof IMBA_VERSION == 'string' ? IMBA_VERSION : '*' const ownVersion = typeof PKG_VERSION == 'string' ? PKG_VERSION : '0.0.0'imbaVersion与ownVersion由构建脚本通过 esbuild 的define在编译期注入(IMBA_VERSION被定义为^2.0.0-alpha.253之类的值),运行期不可改——这是「版本固定」机制的源头。
主流程开头还有一段 Node 版本兜底检查:主版本号< 20时打印黄色警告Detected Node {...}, imba requires v20.19 or higher.,但不阻止继续运行(create-imba 自身只要求 node 18)。
2. 名称校验toValidRepoName
def toValidRepoName name return unless typeof name == 'string' return name if name == '.' name = name.replaceAll(/[^\s\w.-]/g,'').trim!.replaceAll(/\s+/g,'-') if not name or name == '.' throw 'Project name can only contain a-z A-Z 0-9 _ . -' if name == '..' throw "Project name cannot be '..'" if fs.existsSync(name) throw "Project name '{name}' already exists in current directory" name规则可以归纳为:.表示当前目录;非法字符(非字母数字下划线点横线)被剔除、空白折叠为-;空名 /../ 已存在的目录都会抛出明确错误。该函数同时作为 prompts 文本输入的format与validate使用,保证交互与非交互两条路径校验一致。
3. noCopy 排除表与_gitignore重命名
const noCopy = [ '.git' 'dist' 'node_modules' 'package-lock.json' ] def copy src, dest return if noCopy.includes path.basename(src) if path.basename(dest) == '_gitignore' dest = path.join(path.dirname(dest), '.gitignore') if fs.statSync(src).isDirectory! fs.mkdirSync(dest,recursive:yes) for file in fs.readdirSync(src) copy path.resolve(src,file), path.resolve(dest,file) else fs.copyFileSync(src,dest)递归复制器承担两项职责:排除.git、dist、node_modules、package-lock.json(后两个留给用户自行npm install生成);以及把_gitignore重命名为.gitignore——这是模板文件与 npm 打包规则博弈的经典技巧:.gitignore无法作为文件名安全发布,模板用下划线前缀存储,复制时还原。四个模板目录中的_gitignore文件正是为此存在。
4. 模板选择与确认
模板清单以对象形式硬编码(path指向 templates 目录子目录,name/desc用于展示):
default:Default —— Client only applicationexpress:Express —— Full stack application with an Express servermodule:Module —— A module that can be used in any JavaScript projectcli:CLI Tool —— A CLI tool ready for npm publishing
交互路径下,未指定-t时用prompts的select类型弹出模板选择;随后再用confirm类型确认创建信息:Create <Template> project named '<name>' in './dir'?。而--fast会跳过所有提示:模板缺省时直接回退templates.default。
5. 依赖安装与版本固定(核心差异点)
process.chdir(dest) unless projectName == '.' spawn.sync 'npm', ['pkg', 'set', "name={packageName}", "devDependencies.imba={imbaVersion}"] spawn.sync 'npm', ['up', '-S'], stdio:(!opts.fast and 'inherit')这两行实现了 PLAN 决策 5 的「模板刷新」:npm pkg set把脚手架出的package.json的name改为项目名,同时把devDependencies.imba从模板中的"*"改写为注入的imbaVersion(如^2.0.0-alpha.253),避免新项目永远漂移在最新 alpha 上;随后npm up -S安装依赖。--fast模式下安装过程不继承 stdio(静默执行)。若安装失败,仅打印红色错误而不中断退出。
6.--fast模式与 haikunator
projectName = if opts.fast haikunator.haikunate(tokenLength: 0) else try toValidRepoName name catch e console.error(e.red)--fast是面向脚本的设计:用haikunator(形容词-名词式随机命名,如wandering-sunset)生成项目名,跳过所有 prompts,全程不输出过程日志,最终只打印生成的目录名——配合$(npm create imba -- --fast)即可在 shell 脚本里拿到新项目路径。
7. 完成提示
非--fast路径下,结束时打印下一步指引:安装 VS Code 扩展(提示语来自 CLI 输出)、加入 Imba Discord 社区、然后cd <name>执行npm run dev。成功创建与复制失败分别以绿色/红色信息区分。
七、构建管线:esbuild + Imba 编译器产出零依赖单文件
packages/create-imba/scripts/build.js 是整个发布策略的工程核心,实现了 PLAN 决策 4 与「commit the built bin so the package is publishable without CI」:
- 读取同仓 imba 编译器:
require(packages/imba/dist/compiler.cjs),即用 monorepo 内兄弟包的预编译编译器来编译 Imba 源码; - 注册
.imba加载器:esbuild 插件的onLoad钩子把每个.imba文件交给编译器,以platform: 'node'、format: 'esm'编译后以jsloader 返回,编译错误透传为 esbuild 错误; - 单文件打包:入口
src/create.imba,输出bin/create-imba.js,bundle: true把prompts、cross-spawn、haikunator全部打进产物,platform: 'node'、format: 'cjs'、target: 'node18'; - 运行时替换:
alias把imba/runtime指向包内src/runtime-shim.js(轻量运行时垫片,避免引入完整 imba 运行时); - 版本注入:
define把IMBA_VERSION注入为'^' + imbaVersion(从packages/imba/package.json的version读取,无需硬编码)、PKG_VERSION注入为 create-imba 自身版本——这正是第六节提到的常量来源; - 可执行化:banner 写入
#!/usr/bin/env node,构建后chmod 755,确保npx create-imba可直接运行。
最终产物bin/create-imba.js是提交进仓库的预编译文件,配合prepack钩子,意味着「零 CI 也可发布」。
八、主 CLI 恢复imba create委托别名
PLAN 决策 6 给出了主 CLI 侧的恢复方案:在packages/imba/bin/imba.imba重新注册create命令,但只做委托——spawnnpx create-imba@latest并透传全部参数;若cross-spawn可用则用它,否则在 win32 上回退child_process.spawn加shell: true。主包内不引入任何脚手架逻辑,避免重蹈旧版(170 行脚手架代码内嵌主包)的覆辙。
同时 PLAN 特别提示了一个工程细节:bin/imba.imba.js是预编译产物,需确认其重建方式(如packages/imba/scripts/build.js)并同步重建;若重建成本过高,则把别名留作后续跟进并在文档中说明。
配套的文档恢复动作(PLAN 实施步骤 8)包括:
- cli.md 新增
## imba create小节,说明委托关系,并以npm create imba为主推形式; - start.md、home/examples.md、basic-syntax.md 统一改用
npm create imba@latest作为规范命令,npx imba create作为别名提及; - 在 DOCS-IMPROVEMENTS.md 的 §1 勾掉「
imba create不存在」的发现项并附完成说明; - 最后执行
cd apps/imba.io && npm run build-content && npm run build-site,两者必须通过。
九、工作区与 monorepo 接线
PLAN 决策 7 要求把新包接入现有工程结构:
- 根
package.json的workspaces(当前列imba-language-core、imba-language-server、imba-typescript-plugin、vscode-imba-next)新增packages/create-imba; lerna.json(当前只列packages/imba)的 packages 数组同样加入该路径。
同时按 PLAN 决策 2,迁移模板后需从packages/imba/package.json的files数组移除"templates",使模板不再随 imba tarball 发布(此前它们「发布着但不可达」)。
十、验证清单与完成定义
PLAN.md 的 Verification 与 Definition of done 是方案收尾的硬性标准,原文要求逐条执行:
- 在临时目录执行
node <repo>/packages/create-imba/bin/create-imba.js my-test-app --template default --yes(以及--fast),非交互脚手架必须成功; - 在脚手架出的应用中
npm install(或用npm link/file:依赖指向 workspace 的 imba),然后npm run build——脚手架项目必须能用当前 imba 构建;express 模板同样重复一遍; - 交互路径:不带参数运行、回答 prompts(至少验证 prompt 定义能正常渲染;完整 TTY 交互可能无法脚本化,需说明哪些验证过、哪些没有);
- 若别名已实现:
node packages/imba/bin/imba create --help应显示委托生效; npm pack检查 tarball 文件列表:bin+templates齐全、无冗余内容。
完成定义(Definition of done)汇总为:至少default与express两个模板能从构建后的 bin 端到端本地脚手架成功;脚手架出的应用能用 workspace 的 imba 构建;模板不再随 imba tarball 发布;文档更新且站点构建通过;追踪文档对应项已勾选。
十一、范围外事项
PLAN.md 也明确划定了本方案不触碰的边界,避免范围蔓延:
- npm 实际发布(create-imba 的
npm publish与下一版 imba 的别名发布)由维护者执行; - GitHub 模板仓库的创建/重构(基于 degit 的网络拉取可作为后续替代内嵌模板的方案);
- CI 接线。
这三个「out of scope」点决定了本方案的交付形态:一切工作收敛在仓库内可构建、可验证、可本地端到端运行,发布动作留给维护者的发布流程。
小结:create-imba是 Imba monorepo 中一个「小而完整」的工程样本——它演示了独立脚手架包如何用 Imba 编写源码、用 esbuild 打包成零运行时依赖的单文件 bin、用_gitignore规避 npm 打包限制、用--fast服务脚本化调用,并通过薄别名恢复主 CLI 兼容性。无论是想为语言项目搭建npm create xxx入口,还是想理解 Imba 源码 + esbuild 的打包流水线,PLAN.md 与其落地的 src/create.imba、scripts/build.js 都是一份可完整对照参考的实现蓝本。
- 编程语言
- 编译器
- 语言运行时
【免费下载链接】imba
🐤 The friendly full-stack language
相关推荐
Imba 命令行完全指南:imba / imba build / imba serve / npm create imba 实战详解
Imba 命令行完全指南:imba / imba build / imba serve / npm create imba 实战详解 Imba 是一款友好的全栈
编程语言编译器语言运行时tsParticles create-particles 脚手架包深度解析:从 `npm create particles` 到模板化项目生成
tsParticles create particles 脚手架包深度解析:从 npm create particles 到模板化项目生成 导读 本文以 tsP
前端Imba编译原理:从.imba文件到高性能JavaScript的转换过程
Imba编译原理:从.imba文件到高性能JavaScript的转换过程 Imba是一种友好的全栈编程语言,其独特的 编译原理 使得开发者能够编写简洁优雅的代码
编程语言编译器语言运行时
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考