Ember.js 应用的打包、部署与 Grunt.js 构建工具使用指南
1. JavaScript 应用的目录结构规划
在开发 JavaScript 应用时,合理的目录结构规划至关重要。虽然 JavaScript 社区正在逐步形成标准的项目目录结构定义方式,但目前我们仍需遵循一些合理的准则。以 Ember.js 应用为例,可将资源分离到以下目录:
- js/app :项目中所有自行编写的 JavaScript 文件。
- js/lib :所有第三方 JavaScript 文件,部分文件可能已被压缩。
- js/test :项目中的所有 JavaScript 单元测试文件。
- css :项目的所有 CSS 文件直接存放在此文件夹。
- images :项目的所有图片文件。
需要注意的是,部分构建工具可能要求或偏好特定的目录结构。使用 Grunt.js 时,可告知其文件的位置,你也能自由使用自己的目录结构风格。这种目录结构便于应用、开发者和构建工具后续查找资源,多数目录为扁平结构,但 js/app 目录可能并非如此。
2. 自定义源代码的结构设计
拥有合理的源代码结构极为重要。在 Ember.js 应用开发中,若仅将所有 JavaScript 代码存于单个 app.js 文件,对于小型概念验证或示例应用而言高效便捷,但对于需要长期维护和部署到生产环境的应用,就需将源代码分离到不同文件。在设计源代码结构时,有两种方式可供选择:
2.1 按对象类型组织
在 js/app 目录下创建不同的子目录,将相同类型的对象(如控制器、视图等)集中存放。例如,有 controllers 、 models 、 routes 和 views 等目录。在应用规模较小时,这种方式尚可管理,但从长远来看,维护难度较大。以 controllers 目录为例,难以快速区分各文件及其在应用中的职责,需查看文件内容才能确定。
2.2 按功能特性组织
将目录结构按照应用提供的功能特性进行划分。对于 Ember.js 应用,属于同一路由的代码存于同一文件夹,如 administration/accounts 或 chart 等文件夹,其中包含该路由的路由、控制器和视图文件。这种以功能为中心的目录结构具有以下优点:
- 将逻辑分离到小且易于维护的文件中。
- 为每个文件在 js/app 目录中提供可预测的位置。
- 反映应用的主要功能,便于未来维护,也让新开发者更易理解。
3. js/test 目录的结构设计
建议将 js/test 目录按照 js/app 目录的结构进行组织,例如 js/test/administration/account 和 js/test/administration/alerts 等目录。这样做能带来以下好处:
- 当测试失败时,可快速得知哪个功能特性的测试出现问题。
- 为测试文件在 js/test 目录中提供可预测的位置。
- 通过查看测试目录结构,可了解应用哪些部分测试较为完善,哪些部分需进一步关注。
4. 非 JavaScript 资产的组织
在完成 JavaScript 资产的结构设计后,还需对非 JavaScript 资产(如顶级目录内容和 Handlebars.js 模板)进行结构设计。
4.1 顶级目录的结构设计
顶级目录用于存放定义应用相关信息的文件,包括但不限于:
- index.html :定义应用的整体结构。
- 描述应用第三方依赖的文件。
- 告知构建工具如何组装和测试应用的构建文件。
4.2 模板的结构设计
建议将每个模板存于单独的文件,并使用自定义的 .hbs 扩展名(也可使用其他后缀,在组装应用时指定)。这些文件应根据应用的路由命名,能实现以下效果:
- 将每个模板分离到单独文件。
- 将相关模板分组到合理的目录结构中,与应用的功能特性相似。
- 通过目录名和文件名的组合,告知构建工具如何将模板编译为 JavaScript 代码,并自动命名模板。
以下是模板结构的 mermaid 流程图:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(templates):::process --> B(顶级路由模板文件):::process
A --> C(administration 路由模板文件):::process
A --> D(login 路由模板文件):::process
5. Ember.js 应用的组装过程
在将应用拆分为多个文件以方便开发和维护后,组装过程需将所有应用资产合并为单个文件。具体步骤如下:
5.1 源代码和模板的组装
- JavaScript 文件 :
1. 查找js/app目录下的每个文件。
2. 对每个文件进行常见 JavaScript 错误检查(lint)。
3. 与之前的文件进行拼接。
4. 对拼接后的文件进行压缩。 - 模板文件 :
1. 查找每个.hbs文件。
2. 将每个文件的内容赋值给Ember.TEMPLATES[dirname/filename] = Ember.Handlebars.compile(fileContents)。
3. 与之前的模板进行拼接。
5.2 CSS 文件的组装
- 查找每个
.css文件。 - 与之前的 CSS 文件进行拼接。
- 对拼接后的内容进行压缩。
以下是 Ember.js 应用组装过程的 mermaid 流程图:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(JavaScript 文件):::process --> B(查找 js/app 目录下的文件):::process
B --> C(进行 lint 检查):::process
C --> D(拼接文件):::process
D --> E(压缩文件到 app.js):::process
F(模板文件):::process --> G(查找 *.hbs 文件):::process
G --> H(编译到 Ember.TEMPLATES):::process
H --> I(拼接模板到 app.js):::process
J(CSS 文件):::process --> K(查找 *.css 文件):::process
K --> L(拼接 CSS 文件):::process
L --> M(压缩内容到 styles.css):::process
通过以上步骤,最终得到两个文件:一个 app.js 文件包含应用的所有自定义 JavaScript 代码,另一个 styles.css 文件包含应用的所有 CSS 代码。接下来,我们将探讨如何使用 Grunt.js 来构建和组装 Ember.js 应用。
6. 使用 Grunt.js 作为构建工具
Grunt.js 是一个 JavaScript 任务运行器,运行于 Node.js 环境中,主要用于自动化脚本压缩、代码检查、运行单元测试以及将应用资产合并为单个文件等任务。它基于管道概念构建,定义了应用的组装和测试流程。使用 Grunt.js 实现完整的应用组装管道包括以下步骤:
- 初始化 Grunt.js 构建系统。
- 将 JavaScript 文件合并为单个文件。
- 对合并后的文件进行代码检查。
- 将模板编译到合并后的文件中。
- 将合并后的文件压缩为可用于生产环境部署的文件。
Grunt.js 基于插件机制,要执行的任务由相应的插件完成。在组装 Montric 应用时,将按需安装所需插件。下面我们从初始化 Montric 的 Grunt.js 构建系统开始。
6.1 初始化 Montric 的 Grunt.js 构建
Grunt.js 期望在应用的顶级目录中找到两个文件:
- package.json :描述应用及其构建管道所需的依赖。
- Gruntfile.js :描述应用的组装方式。
首先,安装 Node 包管理器(NPM),可前往 http://nodejs.org 安装 Node.js,前往 http://npmjs.org 安装 NPM。
然后,添加 package.json 文件,初始内容如下:
{
"name": "Montric",
"version": "0.9.0",
"devDependencies": {
"grunt": "~0.4.1"
}
}
该文件告知 Grunt.js 项目名称、当前版本以及组装项目所需的开发依赖。后续在构建 Montric 组装管道时,会在 devDependencies 部分添加更多依赖。
接着,添加 Gruntfile.js 文件,初始内容如下:
module.exports = function(grunt) {
// 项目配置
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
});
// 默认任务
grunt.registerTask('default', []);
};
此时,Gruntfile 尚未执行任何任务,但已包含足够信息以执行 grunt 命令。在测试 Gruntfile.js 和 package.json 配置之前,需安装 Grunt.js 命令行界面(CLI),步骤如下:
1. 打开终端(Mac/Linux)或命令提示符(Windows)。
2. 输入以下命令:
npm install -g grunt-cli
NPM 会将 grunt-cli 安装到全局环境,使 grunt 命令可在系统的任何目录中执行。若首次构建已在 package.json 中指定依赖的应用,需先运行 npm install 安装这些依赖。
导航到项目目录,输入 grunt 命令,Grunt.js 将尝试使用之前创建的默认任务组装应用。
6.2 合并 JavaScript 代码
在完成应用构建管道的设置后,接下来安装 Grunt.js 的 concat 插件,通过以下命令实现:
npm install grunt-contrib-concat --save-dev
该命令会下载并安装最新版本的 grunt-contrib-concat 插件到项目目录, --save-dev 参数会将该插件版本信息添加到 package.json 文件中。安装后, package.json 文件内容如下:
{
"name": "Montric",
"version": "0.9.0",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-concat": "~0.3.0"
}
}
为将所有 JavaScript 代码合并为单个文件,需扩展 Gruntfile.js 文件,代码如下:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: '\n'
},
dist: {
src: ['js/app/**/*.js'],
dest: 'dist/<%= pkg.name %>.js'
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['concat']);
};
在 Gruntfile.js 中添加了 concat 对象,其中 options 对象指定在拼接 JavaScript 文件时在每个文件间添加换行符, dist 对象定义了插件查找要拼接的 JavaScript 文件的位置以及拼接结果的输出文件。 src 属性指定查找 js/app 目录下的所有 .js 文件, dest 属性指定将拼接结果输出到 dist 目录下以项目名称命名的文件(如 Montric.js )。
通过以上步骤,我们完成了使用 Grunt.js 合并 JavaScript 代码的操作。后续还将继续探讨如何对合并后的文件进行代码检查、模板编译和文件压缩等操作,以实现完整的 Ember.js 应用组装和部署。
Ember.js 应用的打包、部署与 Grunt.js 构建工具使用指南
7. 对合并后的 JavaScript 文件进行代码检查
在将 JavaScript 文件合并为单个文件后,需要对其进行代码检查(lint),以确保代码的质量和一致性。Grunt.js 提供了 grunt-contrib-jshint 插件来完成这项任务。
首先,安装 grunt-contrib-jshint 插件,在终端中执行以下命令:
npm install grunt-contrib-jshint --save-dev
该命令会下载并安装最新版本的 grunt-contrib-jshint 插件到项目目录,并将其版本信息添加到 package.json 文件中。安装后, package.json 文件会更新为如下内容:
{
"name": "Montric",
"version": "0.9.0",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-jshint": "~2.1.0"
}
}
然后,扩展 Gruntfile.js 文件以配置 jshint 任务,代码如下:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: '\n'
},
dist: {
src: ['js/app/**/*.js'],
dest: 'dist/<%= pkg.name %>.js'
}
},
jshint: {
all: ['dist/<%= pkg.name %>.js']
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('default', ['concat', 'jshint']);
};
在上述代码中, jshint 对象定义了要检查的文件, all 属性指定对合并后的 dist/Montric.js 文件进行代码检查。通过 grunt.loadNpmTasks 加载 grunt-contrib-jshint 插件,并将 jshint 任务添加到默认任务列表中。
以下是执行代码检查步骤的表格总结:
| 步骤 | 操作 | 命令 |
| ---- | ---- | ---- |
| 1 | 安装插件 | npm install grunt-contrib-jshint --save-dev |
| 2 | 配置 Gruntfile.js | 在 Gruntfile.js 中添加 jshint 任务配置 |
| 3 | 执行任务 | 运行 grunt 命令 |
8. 模板编译到合并后的文件中
Ember.js 应用使用 Handlebars.js 模板,需要将这些模板编译到合并后的 JavaScript 文件中。Grunt.js 提供了 grunt-ember-templates 插件来完成模板编译任务。
安装 grunt-ember-templates 插件,在终端中执行以下命令:
npm install grunt-ember-templates --save-dev
安装后, package.json 文件会更新为如下内容:
{
"name": "Montric",
"version": "0.9.0",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-jshint": "~2.1.0",
"grunt-ember-templates": "~1.2.0"
}
}
扩展 Gruntfile.js 文件以配置模板编译任务,代码如下:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: '\n'
},
dist: {
src: ['js/app/**/*.js'],
dest: 'dist/<%= pkg.name %>.js'
}
},
jshint: {
all: ['dist/<%= pkg.name %>.js']
},
ember_templates: {
options: {
templateBasePath: 'templates/'
},
dist: {
src: ['templates/**/*.hbs'],
dest: 'dist/<%= pkg.name %>_templates.js'
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-ember-templates');
grunt.registerTask('default', ['concat', 'jshint', 'ember_templates']);
};
在上述代码中, ember_templates 对象配置了模板编译任务。 options 中的 templateBasePath 指定模板文件的基础路径, dist 对象定义了要编译的模板文件路径和输出文件路径。
以下是模板编译步骤的 mermaid 流程图:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(模板文件):::process --> B(查找 templates 目录下的 *.hbs 文件):::process
B --> C(编译模板):::process
C --> D(输出到 dist/Montric_templates.js):::process
9. 文件压缩
为了减少应用在网络传输中的数据量,需要对合并后的 JavaScript 文件和 CSS 文件进行压缩。Grunt.js 提供了 grunt-contrib-uglify 插件用于压缩 JavaScript 文件, grunt-contrib-cssmin 插件用于压缩 CSS 文件。
首先,安装这两个插件,在终端中执行以下命令:
npm install grunt-contrib-uglify grunt-contrib-cssmin --save-dev
安装后, package.json 文件会更新为如下内容:
{
"name": "Montric",
"version": "0.9.0",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-jshint": "~2.1.0",
"grunt-ember-templates": "~1.2.0",
"grunt-contrib-uglify": "~5.2.1",
"grunt-contrib-cssmin": "~4.0.0"
}
}
扩展 Gruntfile.js 文件以配置文件压缩任务,代码如下:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: '\n'
},
dist: {
src: ['js/app/**/*.js'],
dest: 'dist/<%= pkg.name %>.js'
}
},
jshint: {
all: ['dist/<%= pkg.name %>.js']
},
ember_templates: {
options: {
templateBasePath: 'templates/'
},
dist: {
src: ['templates/**/*.hbs'],
dest: 'dist/<%= pkg.name %>_templates.js'
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
dist: {
files: {
'dist/<%= pkg.name %>.min.js': ['dist/<%= pkg.name %>.js', 'dist/<%= pkg.name %>_templates.js']
}
}
},
cssmin: {
target: {
files: {
'dist/styles.min.css': ['css/*.css']
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-ember-templates');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.registerTask('default', ['concat', 'jshint', 'ember_templates', 'uglify', 'cssmin']);
};
在上述代码中, uglify 对象配置了 JavaScript 文件的压缩任务, options 中的 banner 用于在压缩文件开头添加注释信息, dist 对象指定要压缩的文件和输出文件。 cssmin 对象配置了 CSS 文件的压缩任务,指定要压缩的 CSS 文件和输出文件。
以下是文件压缩步骤的表格总结:
| 步骤 | 操作 | 命令 |
| ---- | ---- | ---- |
| 1 | 安装插件 | npm install grunt-contrib-uglify grunt-contrib-cssmin --save-dev |
| 2 | 配置 Gruntfile.js | 在 Gruntfile.js 中添加 uglify 和 cssmin 任务配置 |
| 3 | 执行任务 | 运行 grunt 命令 |
10. 总结与注意事项
通过以上步骤,我们完成了 Ember.js 应用的打包、部署和使用 Grunt.js 进行构建的整个流程。从合理规划目录结构,到使用 Grunt.js 进行文件合并、代码检查、模板编译和文件压缩,最终实现了一个可用于生产环境部署的 Ember.js 应用。
在使用 Grunt.js 时,需要注意以下几点:
- 确保 Node.js 和 NPM 已正确安装,并且版本兼容。
- 安装插件时,使用 --save-dev 参数将插件版本信息添加到 package.json 文件中,方便团队协作和项目维护。
- 在配置 Gruntfile.js 时,仔细检查每个任务的配置参数,确保任务按预期执行。
以下是整个 Ember.js 应用组装和部署流程的 mermaid 流程图:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(初始化 Grunt.js):::process --> B(合并 JavaScript 文件):::process
B --> C(代码检查):::process
C --> D(模板编译):::process
D --> E(JavaScript 文件压缩):::process
E --> F(CSS 文件压缩):::process
F --> G(完成部署):::process
通过遵循这些步骤和注意事项,你可以高效地开发、打包和部署 Ember.js 应用,提高开发效率和应用性能。
超级会员免费看
48

被折叠的 条评论
为什么被折叠?



