将现有 JavaScript 项目导入 Grunt/Brunch 项目
Posted
技术标签:
【中文标题】将现有 JavaScript 项目导入 Grunt/Brunch 项目【英文标题】:Import an Existing JavaScript Project into a Grunt/Brunch Project 【发布时间】:2012-07-09 10:29:20 【问题描述】:我观看了 Paul Irish 宣布 Yeoman (www.yeoman.io) 的演讲,我迷上了运行连续构建环境的概念。不满足于等待 Yeoman 邀请,我尝试了 Grunt 和 Brunch。两者都易于安装,而且我可以毫不费力地启动和运行新项目。
我不明白如何将现有项目迁移到任一平台。我的项目使用单个命名空间并为模块使用两种约定(一个用于实例化另一个用于实用程序),每个约定都包含在导出到实例或命名空间的自执行匿名函数中。
我至少有 200 个模块和更多简单的辅助函数导出到命名空间;因此,使用控制台在 grunt/brunch 项目中创建这些,然后单独手动导入每个模块,这根本不是有效的。此外,我使用了至少 15 种不同的 3rd-party javascript 工具。我不清楚如何把这些带进来。
将现有的大型项目迁移到 Grunt/Brunch 中的最有效方法是什么?重构最少并支持任意 3rd 方工具?
更新:在两者中,我发现早午餐更容易应付。如果您使用股票“骨架”(即“模板”-从命令行在您希望发生更改的文件夹中执行“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”文件夹中时,您会得到一个自动编译的、实时的、随编辑的代码版本;但它无法访问。早午餐混淆了窗口对象,因此我对 window.myNameSpace 的初始命名空间声明失败,并且所有后续对该命名空间的库调用也失败。这与早午餐的模块系统有关,我找不到任何文档。
我通过将命名空间类放在“供应商”文件夹中解决了这个问题,确保它附加到窗口对象;但是,现在有一个竞争条件:我的命名空间并不总是可用于我的所有模块。
现在的问题是这样的:
将所有内部和外部库复制到 Brunch 项目后,如何配置应用以合理的顺序加载它们?
【问题讨论】:
【参考方案1】:这是一个小作品,但我终于想通了。当我开始使用早午餐时,如何进行第一步并不明显:导入我的目录结构。在它变得明显之前,我花了几遍文档:
-
执行
brunch new MyAppName -s https://github.com/damassi/Javascript-App-Skeleton
,会生成骨架文件夹结构和config.coffee文件
对我来说,这个结构中唯一相关的文件夹是“app”(CSS、JS 和 html 的原始 src 内容)、“public”(编译内容的目标和服务 NodeJS 服务器的位置)和“vendor” '(存放第 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'
]
这个对象的“joinTo”属性让我很困惑,直到我意识到“javascripts”实际上只是“客户端代码”的掩码,而“apps.js”实际上是对“获取所有 *.文件夹“app”中的js文件,递归地'。
一旦清楚这一点,您所需要做的就是将您的内容放入“应用程序”中。我将 *.html 和 images 文件放入了“assets”子文件夹,并将所有 JavaScript 内容放入 lib。
此时,您可以运行 brunch build 和 brunch watch,您的项目已启动并运行,在您进行更改时实时编译,并在浏览器中实时重新加载。
虽然在易于使用第 6 步方面,Brunch 开箱即用比 Grunt 更好,但对我来说它失败的地方在于 Brunch 中编译的性质。每个 JavaScript 文件都包含在一个 CommonJS 模块中,模块名称基于相对路径和文件名(“lib/core/ajax”等)。 CommonJS 哲学不适合我,重构我的库以使用 CommonJS 所涉及的工作量很大。
那么,回到咕噜。一旦我了解了如何将项目导入早午餐,导入 Grunt 就变得轻而易举。我在 Windows 上,所以所有的 grunt 调用都使用 grunt.cmd。
-
致电
grunt init:jquery
(可以在任何地方,我将创建的目录结构移动到我现有的项目文件夹中)
与早午餐一样,您会获得一个自动生成的目录结构和配置文件 (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'
起初我觉得这有点陌生,但实际上它非常优雅。 'min' 属性定义了我的 web 应用程序将提供的最终、连接、linted 和缩小的文件。它的源值是 '',这是 Grunt 看 concat 对象的 dist dest 属性值的魔术,然后从 lint 的文件的属性值导出。因此,您可以在 lint 级别定义要进行 lint、连接、缩小和输出到目标的资源。
一旦这块就位,您必须做一些额外的工作才能使构建、监视和服务器部分就位。在 grunt 中,当服务器完成执行时,它会退出。这意味着如果您执行 grunt 服务器任务,它将启动服务器并且没有其他任务可做,退出。
我的第一个错误是通过设置 watch.task = 'server lint qunit' 将服务器任务与手表任务捆绑在一起。这适用于您对源所做的第一次更改,但第二次更改将尝试在同一端口上启动服务器的第二个实例并失败。相反,您可以注册一个任务 grunt.registerTask('dev', 'server watch qunit');
并调用 grunt dev 以让服务器运行实时、持续构建。
接下来,我的 HTML 内容依赖于服务器端包含来组装页面。我不知道如何让它在 Node 中工作,并且客户端包括使用 <object/>
不起作用,因为它们将内容(在我的情况下是各种 <script/>
和 <link/>
元素)插入到 Iframe ,这当然会破坏我的模块模式(我的命名空间与 iframe 的窗口对象位于不同的窗口对象中)。幸运的是,grunt 的 concat 对象是一个多任务,它可以连接任何东西。所以我将我的 HTML 文件添加到 concat,我的单页应用程序已准备就绪。
接下来,由于 Node 服务器运行在与我的 IIS 实例不同的端口上,因此您遇到了跨域 ajax 问题。这SO article 让我走上了正确的道路,但我最终需要对 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
最后,由于我使用 jQuery 作为我的默认 AJAX 处理程序,我需要将其添加到我的 ajax 选项中:xhrFields:
withCredentials: true
显然,这里存在安全隐患;但由于这只会影响我的开发环境,不会被推送到生产环境,我认为没关系。
最后但并非最不重要的一点是,我花了一个小时尝试通过 Uglify 调试缩小错误,which was conveniently answered by this SO post。由于 Visual Studio 坚持始终插入 BOM(“UTF-8 With Signature”是委婉说法),但UTF-8 Cast 很快就解决了这个问题。
一旦我弄清楚了所有这些,Grunt 似乎工作得很好。我还没有机会在这个新的持续构建环境中开始测试实际的开发过程;但这就是开始的必要条件。
【讨论】:
【参考方案2】:config.coffee
不是真正的 json 而不是真正的 js/coffeescript,但订单编辑应该可以工作。你能在 brunch bugtracker 中以准确的配置顺序打开一个问题吗?
我认为没有一种快速的方法可以重写您的应用程序以使用模块而不是全局 window
变量。顺便说一句,全球人被认为是一种糟糕的品味。但是你的解决方案可以工作,是的。
【讨论】:
我对早午餐的理解是它(至少似乎)需要 CommonJS 模块模式。我正在使用一个简单的(但在我的选择中,非常优雅的命名空间模式)[参见***.com/questions/9072834/… 和jsfiddle.net/2gxYJ/1/],这实际上使得转换到其他模块系统(RequireJS、CommonJS、AMD 等)变得非常简单,一旦图书馆变大了。所以,我改用了不施加设计约束的 Grunt。 由于 1.4 brunch 与模块系统无关,您甚至可以禁用模块。 这太棒了。唯一缺少的功能是 JSHint 支持。 Linting 作为构建/监视选项会很棒。 Grunt 的配置还为您提供了一个 jshint/uglifyjs 对象来显式配置它们的行为。无论如何,brunch 最大的问题是模块要求,所以我一定会再试一次。 惊喜! 1.4 有 linter 支持 ;)以上是关于将现有 JavaScript 项目导入 Grunt/Brunch 项目的主要内容,如果未能解决你的问题,请参考以下文章
将 JSON 文件导入运行在 Grunt 服务器上的 Angular 应用程序