☰
使用 brunch-with-chaplin-js 骨架:基于 Brunch 与 Chaplin 搭建 CommonJS 风格的 HTML5 单页应用
2026/10/6 12:28:45 网站建设 项目流程
  • 构建工具
  • 前端

【免费下载链接】brunch

🍴 Web applications made easy. Since 2011.

项目地址:https://gitcode.com/gh_mirrors/br/brunch
点击查看免费下载

本文围绕当前仓库中的 brunch-with-chaplin-js 骨架 展开,讲解如何用 Brunch 作为构建工具、以 Chaplin 作为 Backbone 之上的"元框架",快速搭建一个目录结构规整、路由清晰、视图可复用的 HTML5 单页应用。读完本文,你将掌握该骨架的安装运行流程、brunch-config.js的打包配置、各目录的职责划分,以及 Mediator、Controller、View 与 Region 等核心机制的源码级实现细节,可以直接以此骨架作为自己项目的基础工程。

骨架定位:Brunch 构建 + Chaplin 架构的样板工程

brunch-with-chaplin-js是 Brunch 官方仓库中提供的一个项目骨架(skeleton / boilerplate),其 README 开篇即说明了定位:这是一个基于 Brunch 构建、采用 Chaplin 架构的 HTML5 应用样板。它要求 Brunch 1.7+,但在当前仓库的 package.json 中实际锁定的是brunch ~2.3.0,即 2.x 时代的配置写法。

骨架的架构选型非常明确:

  • Brunch:负责文件的监听、编译、合并与产出(public/目录完全自动生成);
  • Backbone:作为底层 MVC/MVP 库;
  • Chaplin:作为运行在 Backbone 之上的"元框架",提供路由、控制器生命周期、视图管理与内存回收等约定;
  • CommonJS 模块化:与官方 Chaplin Boilerplate 使用 AMD 不同,本骨架改用 CommonJS,README 中给出的理由是"更容易使用与调试",这也与 Brunch 的require体系天然契合。

从 目录结构 可以看到,应用代码全部位于app/下,包含application.js、initialize.js、mediator.js、routes.js以及controllers/、models/、views/、lib/等子目录——这就是 Chaplin 约定的一套完整应用骨架。

快速开始:安装、依赖与运行

安装骨架

有两种方式获得该骨架:

  1. 手动克隆仓库,然后复制其中的app/、brunch-config.js、package.json、bower.json等文件到你的项目;
  2. 使用 Brunch 的 new 命令(推荐),直接以该骨架初始化项目:
brunch new gh:paulmillr/brunch-with-chaplin-js

brunch new是 Brunch 内置的脚手架命令,会从指定的 GitHub 路径拉取骨架并生成项目,这正是 Brunch 生态中"用骨架秒建项目"的标准用法。

前置环境与依赖安装

骨架 README 给出的环境要求如下:

  • Node.js:OS X 上可用brew install node安装;
  • Brunch:npm install -g brunch全局安装;
  • Bower:npm install -g bower全局安装;
  • 最后在项目目录内安装依赖:
npm install & bower install

npm install会拉取 Brunch 编译插件与应用运行库,bower install则负责前端静态依赖(本骨架的 bower.json 仅依赖h5bp-helpers,用于引入 HTML5 Boilerplate 的辅助样式)。

值得注意的是,当前仓库的 package.json 已经把所有关键运行库都放进了dependencies:chaplin ~1.1.0、exoskeleton ~0.6.0(Backbone 的轻量替代品)、jquery ~2.2.0、lodash ~2.2.0、console-polyfill ~0.1.0与normalize.css ~3.0.3;而devDependencies则集中了全部 Brunch 编译插件:javascript-brunch、css-brunch、stylus-brunch、handlebars-brunch、uglify-js-brunch、clean-css-brunch、auto-reload-brunch以及brunch ~2.3.0本体。也就是说,在现代 npm 环境下仅执行npm install即可完成全部依赖安装。

开发与生产构建

骨架 README 给出了两条核心命令:

# 开发模式:监听文件变化并持续增量重建,同时启动 HTTP 服务器 # 服务器自带 pushState 支持,适合 HTML5 History API 路由 brunch watch --server # 生产模式:产出压缩(minified)后的构建结果 brunch build --production
  • brunch watch --server会同时做两件事:一是持续监听app/目录,任何源码改动都会触发增量编译;二是启动一个内置 HTTP 服务器,并且支持 pushState,这正是 Chaplin 的 Rails 风格路由在浏览器端正常工作的前提——URL 的切换不再依赖 hash。
  • brunch build --production会走压缩管线:JavaScript 交给uglify-js-brunch、CSS 交给clean-css-brunch,产出可直接部署的生产包。

package.json的scripts中也预置了快捷方式:npm start等价于brunch watch --server,npm test则对应brunch test。

目录使用约定

骨架 README 强调了两条重要的开发约定:

  • public/目录完全自动生成并由 HTTP 服务器直接伺服,不要手动编辑它,你的代码一律写在app/目录;
  • app/assets/下的静态文件(图片、字体、以及index.html入口页)会在构建时原样复制到public/,用于存放不需要编译的资源。

配置解析:brunch-config.js 与打包策略

骨架的 brunch-config.js 是理解整个构建行为的关键,全文件内容如下:

exports.config = { files: { javascripts: { joinTo: { 'javascripts/app.js': /^app/, 'javascripts/vendor.js': /^(?!app)/ } }, stylesheets: { joinTo: 'stylesheets/app.css' }, templates: { joinTo: 'javascripts/app.js' } }, npm: { aliases: { backbone: 'exoskeleton' }, globals: { _cp: 'console-polyfill', $: 'jquery' }, styles: { 'normalize.css': ['normalize.css'] } } };

逐项说明其作用:

  • files.javascripts.joinTo:定义了 JS 的两份产物。
    • 路径匹配/^app/的源码(即app/下的业务代码)合并进public/javascripts/app.js;
    • 其余所有文件(node_modules 依赖等)合并进public/javascripts/vendor.js。
    • 这一"应用代码与第三方代码分离"的策略,既利于缓存(vendor 不常变),也便于调试时定位问题来源。
  • files.stylesheets.joinTo:所有 Stylus/CSS 统一合并为一个public/stylesheets/app.css。
  • files.templates.joinTo:Handlebars 模板经handlebars-brunch预编译后,以 CommonJS 模块的形式注入javascripts/app.js,这就是源码里可以直接require('./templates/site')拿到模板函数的原因。
  • npm.aliases:把backbone这一模块名映射到exoskeleton。由于 Chaplin 依赖 Backbone API,而骨架选用的 Backbone 兼容实现是 exoskeleton,通过 alias 可以让require('backbone')实际解析到 exoskeleton,无需改动任何业务代码。
  • npm.globals:把$暴露为全局的 jQuery、把_cp暴露为全局的 console-polyfill,供非模块化代码直接使用。
  • npm.styles:把normalize.css中的 CSS 文件纳入构建管线的样式合并。

这些配置共同构成了 Brunch 2.x 时代"一处配置、三线产出(app.js / vendor.js / app.css)"的典型打包方案。

应用启动链路:从 initialize 到路由分发

骨架的入口逻辑非常精简,但每一环都是 Chaplin 约定的关键点。

1. 启动入口 initialize.js

app/initialize.js 在 DOM ready 后实例化应用:

var Application = require('application'); var routes = require('routes'); $(function() { return new Application({ title: 'Brunch example application', controllerSuffix: '-controller', routes: routes }); });

这里传入三个关键配置:

  • title:应用标题,Chaplin 会据此自动更新document.title;
  • controllerSuffix:'-controller',它决定了路由home#index会被解析到名为home-controller的控制器模块——这是 Chaplin 的"约定优于配置"核心体现;
  • routes:路由表函数。

2. 应用对象 application.js

app/application.js 通过 CommonJS 引入 Chaplin 并派生应用类:

var Chaplin = require('chaplin'); module.exports = Application = Chaplin.Application.extend({ // start: function() { // // 这里可以在启动前预取数据,再调用 super 正式启动 // this.constructor.__super__.start.call(this); // } })

默认情况下无需覆写任何方法;注释中给出了一个常见扩展点:在start()中先异步拉取初始化数据,再调用super继续应用启动流程。

3. 中介者 mediator.js

app/mediator.js 只有一行:

var mediator = module.exports = Chaplin.mediator;

它将 Chaplin 全局中介者导出为应用内模块。Mediator 是 Chaplin 跨模块通信的枢纽,配合 Publish/Subscribe 模式,控制器、视图、模型之间不需要互相持有引用即可收发事件,这是骨架 README 明确列出的核心特性之一。

4. Rails 风格路由 routes.js

app/routes.js 定义了 URL 到控制器动作的映射:

module.exports = function(match) { return match('', 'home#index'); };

match('', 'home#index')表示根路径/交由home-controller的index动作处理。得益于controllerSuffix: '-controller',字符串'home'会自动解析为home-controller模块。新增页面时只需追加match('/xxx', 'controller#action')并在controllers/下新建对应文件即可,扩展路径非常直接。

控制器与视图协作:reuse、Region 与内存管理

控制器基类:跨页面复用的 Composition

app/controllers/base/controller.js 是所有控制器的基类:

var Chaplin = require('chaplin'); var SiteView = require('views/site-view'); module.exports = Chaplin.Controller.extend({ // 通过 Composition 在控制器之间持久化实例 beforeAction: function() { return this.reuse('site', SiteView); } });

这里的reuse('site', SiteView)是 Chaplin 的 Composition 机制:名为site的视图实例一旦创建,就会在后续控制器切换时被复用而不是重建,从而让"站点外壳"(页头、页脚、布局容器)跨页面保持状态。注释明确说明:"Compositions 会在控制器之间持久化内容,你也可以用同样的方式持久化模型等。"

具体控制器:挂载头部视图与主区域视图

app/controllers/home/home-controller.js 演示了完整的控制器写法:

var Controller = require('controllers/base/controller'); var HeaderView = require('views/home/header-view'); var HomePageView = require('views/home/home-page-view'); module.exports = Controller.extend({ beforeAction: function() { this.constructor.__super__.beforeAction.apply(this, arguments); this.reuse('header', HeaderView, {region: 'header'}); }, index: function() { this.view = new HomePageView({region: 'main'}); } });
  • beforeAction先调用父类以复用站点外壳,再把名为header的头部视图复用到header区域;
  • index动作创建HomePageView并挂载到main区域——动作结束时控制器将this.view交给 Chaplin 的 Dispatcher 管理,页面切换时旧视图会被自动 dispose。

站点视图与区域(Region)机制

app/views/site-view.js 是整个应用的"壳":

var View = require('views/base/view'); module.exports = View.extend({ container: 'body', id: 'site-container', regions: { header: '#header-container', main: '#page-container' }, template: require('./templates/site') });
  • container: 'body':视图渲染后插入body;
  • regions:声明header与main两个命名区域,分别指向页面中的#header-container和#page-container容器。控制器通过{region: 'header'}/{region: 'main'}把子视图挂到对应区域,这就是 Chaplin 的 Region 机制——视图只认区域名,不关心容器选择器,布局与业务彻底解耦。

配合 site.hbs 模板,该骨架实现了 README 中"与官方 Chaplin Boilerplate 相比新增了 Header"的差异点。

内存管理与对象回收

骨架 README 将"严格的内存管理与对象回收(Strict memory management and object disposal)"列为重要特性。它在源码中的体现是:

  • app/views/base/view.js 与 app/views/base/collection-view.js 均直接继承Chaplin.View/Chaplin.CollectionView。Chaplin 的视图基类内置了dispose()生命周期:解除 DOM 事件绑定、移除子视图监听、注销 mediator 订阅,页面切换时 Dispatcher 会自动调用,避免事件监听泄漏;
  • 所有基类(view / collection-view / model / collection)集中放在app/views/base/与app/models/base/,形成统一的继承入口,后续为"回收逻辑"添加自定义实现非常方便。

扩展基类与模板助手

应用级视图基类:模板注入

app/views/base/view.js 是业务视图的共同祖先:

var Chaplin = require('chaplin'); require('lib/view-helper'); module.exports = Chaplin.View.extend({ // 允许把 `template` 作为构造参数传入并保存为实例属性 optionNames: Chaplin.View.prototype.optionNames.concat(['template']), getTemplateFunction: function(){ return this.template; } });

它做了一件很关键的事:通过扩展optionNames,让template可以作为构造参数直接传入(如new HomePageView({region: 'main'})之外再传template),并由getTemplateFunction()返回。业务视图(例如 home-page-view.js)只需声明template: require('./templates/home')即可渲染,无需关心模板编译细节。

由于CollectionView不继承这个应用级 View,collection-view.js 特意从View.prototype借用getTemplateFunction,保证列表视图同样能用模板渲染条目。

模型与集合基类:同步状态机

app/models/base/model.js 与 app/models/base/collection.js 分别继承Chaplin.Model与Chaplin.Collection。源码中保留了一段被注释的样板代码:通过_.extend(this, Chaplin.SyncMachine)混入同步状态机,并监听request/sync/error事件驱动beginSync/finishSync/unsync——这是 Chaplin 文档推荐的模型同步状态管理方式,骨架将其作为现成的扩展点留给开发者按需启用。

同时,集合基类设置了model: Model,声明集合元素类型;README 中提到的"带额外操作方法的集合(更智能的 change 事件)"与"集合视图(简便智能的列表渲染)"正是Chaplin.Collection与Chaplin.CollectionView提供的内置能力。

Handlebars 全局助手

app/lib/view-helper.js 通过Handlebars.registerHelper注册了三个全局助手:

  • with:增强原生的with块——当上下文为空时渲染inverse分支,避免对空对象取值报错;
  • without:with的取反形态,空值渲染主分支;
  • url:调用 app/lib/utils.js 的reverse(routeName, params),按路由名反向生成 URL——模板里写{{url 'home'}}即可得到对应路径,彻底告别硬编码链接。

由于该文件在视图基类中被require,因此所有业务模板都能直接使用这三个助手。

骨架的边界与自定义方向

阅读 README 时需要注意几个事实层面的限制:

  • 不含测试环境:README 明确说明当前分支没有现成的测试环境,如需查看测试用法,应切换到with-testsgit 分支(本骨架还提供brunch test脚本,可配合测试插件自行搭建)。
  • 技术栈可替换:骨架默认使用 JavaScript + Stylus + Handlebars,README 说明"你可以改成任何你想要的组合",通过调整brunch-config.js中的插件与joinTo配置即可换用 CoffeeScript、Sass、Jade 等。
  • 认证支持:README 提到若需构建带登录鉴权的应用,可参考 chaplin-auth 提供的认证抽象,它与本骨架的 Chaplin 体系兼容。
  • 参考实现:README 以 Ost.io 作为基于该骨架构建的示例应用。
  • 浏览器支持:骨架宣称支持 IE8 及以上,并引入了console-polyfill以补齐老浏览器的控制台能力。

许可证

骨架采用 MIT 许可证,版权声明见 README.md 末尾:Copyright (c) 2012 Paul Miller,以及 Copyright (c) 2012 Moviepilot GmbH、9elements GmbH 等。完整许可文本允许自由使用、复制、修改、合并、出版、分发、再许可与销售,但需保留上述版权声明,软件按"AS IS"提供且不附带任何明示或默示担保。

结语

brunch-with-chaplin-js骨架的价值在于把 Brunch 的构建便利与 Chaplin 的架构纪律组合在一起:brunch watch --server提供秒级增量编译与 pushState 服务器,Chaplin 则用 Routes、Controller、Dispatcher、Mediator、Region 与 dispose 生命周期把单页应用的复杂度组织得井井有条。本文已从安装运行、构建配置、启动链路、控制器/视图协作到基类扩展逐层拆解,读者可直接以 骨架目录 为起点,替换模板与样式,添加自己的路由与控制器,快速进入业务开发。

  • 构建工具
  • 前端

【免费下载链接】brunch

🍴 Web applications made easy. Since 2011.

项目地址:https://gitcode.com/gh_mirrors/br/brunch
点击查看免费下载
上一篇:14 个 QuickLook 插件:用空格键预览 CSV、代码、APK 与压缩包
下一篇:Astron Agent 贡献指南:从开发环境搭建到提交合入的多语言协作规范

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询