7

我观看了 Paul Irish 宣布 Yeoman (www.yeoman.io) 的演讲,我迷上了运行连续构建环境的概念。不满足于等待 Yeoman 邀请,我尝试了 Grunt 和 Brunch。两者都易于安装,我可以轻松启动和运行新项目。

我不明白如何将现有项目迁移到任一平台。我的项目使用单个命名空间并为模块使用两种约定(一个用于实例化另一个用于实用程序),每个约定都包含在导出到实例或命名空间的自执行匿名函数中。

我至少有 200 个模块和更多简单的辅助函数导出到命名空间;因此,使用控制台在 grunt/brunch 项目中创建这些,然后单独手动导入每个模块,这根本不是有效的。此外,我使用了至少 15 种不同的 3rd-party JavaScript 工具。我不清楚如何把这些带进来。

以最少的重构量和对任意 3rd 方工具的支持,将现有的大型项目迁移到 Grunt/Brunch 的最有效方法是什么?

更新:在两者中,我发现早午餐更容易应付。如果您使用股票“骨架”(即“模板”-从命令行{在您希望更改发生的文件夹中}执行“brunch new [project_name] --skeleton git://github.com/brunch /simple-js-skeleton.git") 对于纯 JS,你会得到一个新的文件夹结构,它实际上是非常敏感的。您放入“app”(您自己的代码)或“vendor”(第 3 方)文件夹的任何内容都会在文件编辑时自动为您重新编译(当您运行“brunch watch”时)。

这很棒,除了。根据文档,您可以控制从 Brunch config.coffee 文件(JSON 文本文件)编译和连接供应商脚本的顺序。对此文件的更改似乎没有任何效果,因此您最终会遇到来自期望其他插件的插件的第 3 方竞争条件。

此外,当您将自己的代码放入自动创建的“app”文件夹中时,您确实会得到一个自动编译的、实时的、随编辑的代码版本;但它无法访问。Brunch 混淆了 window 对象,因此我对 window.myNameSpace 的初始命名空间声明失败,并且对命名空间的所有后续库调用也失败。这与早午餐的模块系统有关,我找不到任何文档。

我通过将命名空间类放在“供应商”文件夹中解决了这个问题,确保它附加到窗口对象;但是,现在有一个竞争条件:我的命名空间并不总是可用于我的所有模块。

现在的问题是这样的:

将所有内部和外部库复制到 Brunch 项目后,如何配置应用程序以合理的顺序加载它们?

4

2 回答 2

7

这是一个小作品,但我终于想通了。当我开始使用早午餐时,如何进行第一步并不明显:导入我的目录结构。在它变得明显之前,我花了几遍文档:

  1. Execute brunch new MyAppName -s https://github.com/damassi/Javascript-App-Skeleton,这将生成一个骨架文件夹结构和 config.coffee 文件
  2. 对我来说,这个结构中唯一相关的文件夹是“app”(CSS、JS 和 HTML 的原始 src 内容)、“public”(编译内容的目标和服务 NodeJS 服务器的位置)和“vendor”(存放第 3 方文件的地方)。
  3. Brunch 在目录结构的根目录创建了一个 config.coffee 文件,内容如下:files: javascripts: defaultExtension: 'js' joinTo: 'javascripts/app.js': /^app/ 'javascripts/vendor.js': /^vendor/ order: before: [ 'vendor/scripts/console-helper.js', 'vendor/scripts/jquery-1.7.1.min.js' ]
  4. 这个对象的“joinTo”属性让我很困惑,直到我意识到“javascripts”实际上只是“客户端代码”的掩码,而“apps.js”实际上是对“获取所有 *.js 文件的调用”文件夹“app”,递归地'。
  5. 一旦清楚这一点,您需要做的就是将您的内容放入“应用程序”。我将 *.html 和图像文件放入“assets”子文件夹,并将所有 JavaScript 内容放入 lib。
  6. 此时,您可以运行 brunch build 和 brunch watch,您的项目已启动并运行,在您进行更改时实时编译,在浏览器中实时重新加载。

虽然在使用步骤 6 时,Brunch 开箱即用比 Grunt 更好,但对我来说它失败的地方是 Brunch 中编译的性质。每个 JavaScript 文件都包含在一个 CommonJS 模块中,模块名称基于相对路径和文件名(“lib/core/ajax”等)。CommonJS 哲学不适合我,重构我的库以使用 CommonJS 所涉及的工作量很大。

所以,回到咕噜。一旦我了解了如何将项目导入早午餐,导入 Grunt 就变得轻而易举。我在 Windows 上,所以所有 grunt 调用都使用 grunt.cmd。

  1. 调用grunt init:jquery(这可以在任何地方,我将创建的目录结构移动到我现有的项目文件夹中)
  2. 与早午餐一样,您会获得一个自动生成的目录结构和配置文件 (grunt.js),但它要薄得多。Grunt 的配置如下所示:concat: { dist: { src: ['<config:lint.files>'], dest: 'dist/<%= pkg.name %>.js' } }, min: { dist: { src: ['<banner:meta.banner>', '<config:concat.dist.dest>'], dest: 'dist/<%= pkg.name %>.min.js' } }, qunit: { files: ['test/**/*.html'] }, lint: { files: ['grunt.js', 'src/**/*.js', 'test/**/*.js'] }, watch: { files: '<config:lint.files>', tasks: 'lint qunit' }
  3. 起初这在我看来有点陌生,但实际上它非常优雅。'min' 属性定义了我的 web 应用程序将提供的最终、连接、linted 和缩小的文件。它的源值是 '',这是 Grunt 看 concat 对象的 dist dest 属性值的魔法,然后从 lint 的文件的属性值导出。因此,您可以在 lint 级别定义要检查、连接、缩小和输出到目的地的资源。
  4. 一旦这部分就位,您必须做一些额外的工作才能使构建、监视和服务器部分就位。在 grunt 中,当服务器完成执行时,它会退出。这意味着如果您执行 grunt 服务器任务,它将启动服务器并且没有其他任务可做,退出。
  5. 我的第一个错误是通过设置 watch.task = 'server lint qunit' 将服务器任务与手表任务捆绑在一起。这适用于您对源进行的第一次更改,但第二次更改将尝试在同一端口上启动服务器的第二个实例并失败。相反,您可以注册一个任务grunt.registerTask('dev', 'server watch qunit');并调用 grunt dev 来让服务器运行实时、持续构建。
  6. 接下来,我的 HTML 内容依赖于服务器端包含来组装页面。我不知道如何让它在 Node 中工作,并且客户端包括使用<object/>不起作用,因为它们将内容(在我的情况下是各种<script/>元素<link/>)插入到 iframe 中,这当然会破坏我的模块模式(我的命名空间与 iframe 的窗口对象位于不同的窗口对象中)。幸运的是,grunt 的 concat 对象是一个多任务,它可以连接任何东西。所以我将我的 HTML 文件添加到 concat 中,我的单页应用程序已准备就绪。
  7. 接下来,由于节点服务器运行在与我的 IIS 实例不同的端口上,因此您遇到了跨域 ajax 问题。这篇SO 文章让我走上了正确的道路,但最终我需要对 IIS 默认内容标头进行以下更改:Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: X-Requested-With, X-Prototype-Version, Content-Type, Origin, Allow Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS Access-Control-Allow-Origin: http://localhost:88
  8. 最后,由于我使用 jQuery 作为我的默认 AJAX 处理程序,我需要将其添加到我的 ajax 选项中:xhrFields: { withCredentials: true }
  9. 显然,这里存在安全隐患;但由于这只会影响我的开发环境,不会被推送到生产环境,我认为没关系。
  10. 最后但并非最不重要的一点是,我花了一个小时尝试通过 Uglify 调试缩小错误,这篇 SO 帖子很方便地回答了这个错误。由于 Visual Studio 坚持始终插入 BOM(“带有签名的 UTF-8”是委婉说法),但UTF-8 Cast可以快速修复此问题。

一旦我弄清楚了所有这些,Grunt 似乎工作得很好。我还没有机会在这个新的持续构建环境中开始测试实际的开发过程;但这就是开始的过程。

于 2012-07-15T02:58:56.840 回答
3

config.coffee不是真正的 json 而不是真正的 js/coffeescript,但订单编辑应该可以工作。你能在 brunch bugtracker 中用准确的配置顺序打开一个问题吗?

我认为没有一种快速的方法可以重写您的应用程序以使用模块而不是全局window变量。顺便说一句,全球人被认为是一种糟糕的品味。但是你的解决方案可以工作,是的。

于 2012-07-13T08:50:50.727 回答