前面的話
前端技術的發展真的很快,15年還在流行grunt,而現在隨著gulp的大量使用,以及webpack越來越流行,grunt基本上要被淘汰了。學習進度跟不上技術發展進度,實在是說不出的感覺。本文將介紹可能將過時的grunt
安裝
Grunt和Grunt插件是通過npm安裝并管理的。在學習Grunt前,需要先將Grunt命令行(CLI)安裝到全局環境中。安裝時可能需要使用sudo(針對OSX、*nix、BSD等系統中)權限或者作為管理員(對于Windows環境)來執行以下命令
npm install -g grunt-cli

上述命令執行完后,grunt
命令就被加入到系統路徑中了,以后就可以在任何目錄下執行此命令了
[注意]安裝grunt-cli
并不等于安裝了Grunt。Grunt CLI的任務很簡單:調用與Gruntfile
在同一目錄中的Grunt。這樣帶來的好處是,允許在同一個系統上同時安裝多個版本的Grunt
每次運行grunt
時,就利用node提供的require()
系統查找本地安裝的Grunt。正是由于這一機制,可以在項目的任意子目錄中運行grunt
。如果找到一份本地安裝的Grunt,CLI就將其加載,并傳遞Gruntfile
中的配置信息,然后執行所指定的任務
配套
一般需要在項目中添加兩份文件:package.json
和 Gruntfile
package.json: 此文件被npm用于存儲項目的元數據,以便將此項目發布為npm模塊。可以在此文件中列出項目依賴的grunt和Grunt插件,放置于devDependencies配置段內
Gruntfile: 此文件被命名為 Gruntfile.js
或 Gruntfile.coffee
,用來配置或定義任務(task)并加載Grunt插件
【package.json】
package.json
應當放置于項目的根目錄中,與Gruntfile
在同一目錄中,并且應該與項目的源代碼一起被提交。在上述目錄(package.json
所在目錄)中運行npm install
將依據package.json
文件中所列出的每個依賴來自動安裝適當版本的依賴
常用的package.json配置如下
{ "name": "my-project-name", "version": "0.1.0", "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-jshint": "~0.10.0", "grunt-contrib-nodeunit": "~0.4.1", "grunt-contrib-uglify": "~0.5.0" } }
向已經存在的package.json
文件中添加Grunt和grunt插件的最簡單方式是通過npm install <module> --save-dev
命令。此命令不光安裝了<module>
,還會自動將其添加到devDependencies 配置段中,如下所示
npm install grunt-contrib-jshint --save-dev
【Gruntfile】
Gruntfile.js
或 Gruntfile.coffee
文件是有效的 JavaScript 或 CoffeeScript 文件,應當放在項目根目錄中,和package.json
文件在同一目錄層級,并和項目源碼一起加入源碼管理器
Gruntfile由以下幾部分構成:
- "wrapper" 函數
- 項目與任務配置
- 加載grunt插件和任務
- 自定義任務
在下面列出的這個 Gruntfile
中,package.json
文件中的項目元數據(metadata)被導入到 Grunt 配置中, grunt-contrib-uglify 插件中的uglify
任務(task)被配置為壓縮(minify)源碼文件并依據上述元數據動態生成一個文件頭注釋。當在命令行中執行 grunt
命令時,uglify
任務將被默認執行
module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } }); // 加載包含 "uglify" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-uglify'); // 默認被執行的任務列表。 grunt.registerTask('default', ['uglify']); };
1、wrapper函數
每一份 Gruntfile
(和grunt插件)都遵循同樣的格式,所書寫的Grunt代碼必須放在wrapper函數內
module.exports = function(grunt) { // Do grunt-related things in here };
2、項目和任務配置
大部分的Grunt任務都依賴某些配置數據,這些數據被定義在一個object內,并傳遞給grunt.initConfig 方法
Grunt的task配置都是在 Gruntfile
中的grunt.initConfig
方法中指定的。此配置主要是以任務名稱命名的屬性,也可以包含其他任意數據。一旦這些代表任意數據的屬性與任務所需要的屬性相沖突,就將被忽略
grunt.initConfig({ concat: { // 這里是concat任務的配置信息。 }, uglify: { // 這里是uglify任務的配置信息 }, // 任意數據。 my_property: 'whatever', my_src_files: ['foo/*.js', 'bar/*.js'], });
在一個任務配置中,options
屬性可以用來指定覆蓋內置屬性的默認值。此外,每一個目標(target)中還可以擁有一個專門針對此目標(target)的options
屬性。目標(target)級的平options將會覆蓋任務級的options。options
對象是可選的,如果不需要,可以忽略
grunt.initConfig({ concat: { options: { // 這里是任務級的Options,覆蓋默認值 }, foo: { options: { // "foo" target options may go here, overriding task-level options. }, }, bar: { // No options specified; this target will use task-level options. }, }, });
在下面的案例中,grunt.file.readJSON('package.json')
將存儲在package.json
文件中的JSON元數據引入到grunt config中。 由于<% %>
模板字符串可以引用任意的配置屬性,因此可以通過這種方式來指定諸如文件路徑和文件列表類型的配置數據,從而減少一些重復的工作
與大多數task一樣,grunt-contrib-uglify插件中的uglify
任務要求它的配置被指定在一個同名屬性中。在這里有一個例子, 我們指定了一個banner
選項(用于在文件頂部生成一個注釋),緊接著是一個單一的名為build
的uglify目標,用于將一個js文件壓縮為一個目標文件
// Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } });
3、加載grunt插件和任務
像 concatenation、minification、grunt-contrib-uglify 和 linting這些常用的任務(task)都已經以grunt插件的形式被開發出來了。只要在 package.json
文件中被列為dependency(依賴)的包,并通過npm install
安裝之后,都可以在Gruntfile
中以簡單命令的形式使用:
// 加載能夠提供"uglify"任務的插件。 grunt.loadNpmTasks('grunt-contrib-uglify');
[注意] grunt --help
命令將列出所有可用的任務
4、自定義任務
通過定義 default
任務,可以讓Grunt默認執行一個或多個任務。在下面的這個案例中,執行 grunt
命令時如果不指定一個任務的話,將會執行uglify
任務。這和執行grunt uglify
或者 grunt default
的效果一樣。default
任務列表數組中可以指定任意數目的任務(可以帶參數)
// Default task(s). grunt.registerTask('default', ['uglify']);
合并
本節將介紹合并插件grunt-contrib-concat的實例應用
1、首先,建立項目結構。 根目錄為'project',存在一個'src'的文件夾,該文件夾下又包含'css'和'js'這兩個文件夾。其中,'css'文件夾有一個空的'concat'文件夾,一個'style1.css'文件,以及一個'style2.css'文件;類似地,'js'文件夾有一個空的'concat'文件夾,一個'script1.js'文件,以及一個'script2.js'文件


由于需要用到grunt來實現合并,所以需要在項目根目錄下,新建'package.json'和'Gruntfile.js'文件

最終的目錄結構如下所示

2、填充文件內容
合并的目的是把'style1.css'和'style2.css'的內容合并到'css/src/concat'文件夾下,把'script1.js'和'script2.js'的內容合并到'js/src/concat'文件夾下
style1.css的文件內容如下
body{margin: 0;}
style2.css的文件內容如下
ul{ margin: 0; padding: 0; list-style:none; }
script1.js的文件內容如下
console.log('a');
script2.js的文件內容如下
console.log('b');
3、設置Grunt的package.json及Gruntfile.js文件
由于需要用到grunt及grunt-contrib-concat插件,所以package.json的文件內容如下
{ "name": "project", "version": "1.0.0", "devDependencies": { "grunt": "^1.0.1", "grunt-contrib-concat": "^1.0.1" } }
Gruntfile.js的配置文件如下
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { options: { stripBanners: true, banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */' }, myCSSDist: { src: ['src/css/*.css'], dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css' }, myJSDist: { src: ['src/js/*.js'], dest: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js' }, }, }); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.registerTask('default', ['concat']); };
4、效果演示
通過在命令行中使用npm install命令來安裝插件
npm install
然后執行命令grunt

在'css/concat'文件夾下生成一個'project-1.0.0.css'的文件,內容如下
/*! project - v1.0.0 - 2017-05-27 */body{margin: 0;}
ul{ margin: 0; padding: 0; list-style:none; }
在'js/concat'文件夾下生成一個'project-1.0.0.js'的文件,內容如下
/*! project - v1.0.0 - 2017-05-27 */console.log('a');console.log('b');
壓縮
接下來,我們對合并后的project-1.0.0.css和project-1.0.0.js文件進行壓縮,壓縮名稱加一個'.min'前綴,并分別保存到'project'目錄下的'dist'目錄下'css'文件夾和'js'文件夾

由于需要用到grunt-contrib-cssmin和grunt-contrib-uglify插件,所以package.json的文件內容如下
{ "name": "project", "version": "1.0.0", "devDependencies": { "grunt": "^1.0.1", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-cssmin": "^2.2.0", "grunt-contrib-uglify": "^3.0.1" } }
Gruntfile.js的配置文件如下
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { options: { stripBanners: true, banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */' }, myCSSDist: { src: ['src/css/*.css'], dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css' }, myJSDist: { src: ['src/js/*.js'], dest: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js' }, }, cssmin:{ options: { stripBanners: true, banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */' }, build:{ src: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css', dest: 'dist/css/<%= pkg.name %>-<%= pkg.version %>.min.css' } }, uglify:{ options: { stripBanners: true, banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */' }, build:{ src: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js', dest: 'dist/js/<%= pkg.name %>-<%= pkg.version %>.min.js' } } }); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.registerTask('default', ['concat','cssmin','uglify']); };
通過在命令行中使用npm install命令來安裝插件

然后執行命令grunt

在'dist/css/'文件夾下生成一個'project-1.0.0.min.css'的文件,內容如下
/*! project - v1.0.0 - 2017-05-27 */body{margin:0}ul{margin:0;padding:0;list-style:none}
在'dist/js/'文件夾下生成一個'project-1.0.0.min.js'的文件,內容如下
/* 2017-05-27 */ console.log("a"),console.log("b");
檢查
前面的博文已經介紹過jshint和csslint。如果要使用grunt中的插件,則需要在根目錄下建立 .csslintrc 和 .jshintrc 文件,并設置它們的內容如下
//.csslintrc { "adjoining-classes":false, "box-sizing":false, "box-model":false, "compatible-vendor-prefixes": false, "floats":false, "font-sizes":false, "grandients":false, "important":false, "known-properties":false, "outline-none":false, "qualified-headings":false, "regex-selectors":false, "shorthand":false, "text-indent":false, "unique-headings":false, "universal-selector":false, "unqualified-attributes":false } //.jshintrc { "boss": false, "curly": true, "eqeqeq": true, "eqnull": true, "expr": true, "immed":true, "newcap":true, "noempty":true, "noarg":true, "undef":true, "regexp":true, "browser":false, "devel":true, "node":true }
由于需要用到grunt-contrib-csslint和grunt-contrib-jshint插件,所以package.json的文件內容如下
{ "name": "project", "version": "1.0.0", "devDependencies": { "grunt": "^1.0.1", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-cssmin": "^2.2.0", "grunt-contrib-uglify": "^3.0.1", "grunt-contrib-csslint": "^2.0.0", "grunt-contrib-jshint": "^1.1.0" } }
Gruntfile.js的配置文件如下
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { options: { stripBanners: true, banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */' }, myCSSDist: { src: ['src/css/*.css'], dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css' }, myJSDist: { src: ['src/js/*.js'], dest: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js' }, }, cssmin:{ options: { stripBanners: true, banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */' }, build:{ src: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css', dest: 'dist/css/<%= pkg.name %>-<%= pkg.version %>.min.css' } }, uglify:{ options: { stripBanners: true, banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */' }, build:{ src: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js', dest: 'dist/js/<%= pkg.name %>-<%= pkg.version %>.min.js' } }, jshint:{ options:{ jshintrc:'.jshintrc' }, build:['Gruntfile.js','src/js/*.js'] }, csslint:{ options:{ csslintrc:'.csslintrc' }, build:['src/css/*.css'] } }); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-csslint'); grunt.registerTask('default', ['jshint','csslint','concat','cssmin','uglify']); };
通過在命令行中使用npm install命令來安裝插件

然后執行命令grunt

可以看到'script1.js'文件中第1行缺少分號,修改后再執行命令grunt

監控
grunt構建工具的自動化主要體現在grunt-contrib-watch插件上,該插件主要用于監聽并執行對應的任務
package.json的文件內容如下
{ "name": "project", "version": "1.0.0", "devDependencies": { "grunt": "^1.0.1", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-csslint": "^2.0.0", "grunt-contrib-cssmin": "^2.2.0", "grunt-contrib-jshint": "^1.1.0", "grunt-contrib-uglify": "^3.0.1", "grunt-contrib-watch": "^1.0.0" } }
Gruntfile.js的配置文件如下
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { options: { stripBanners: true, banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */' }, myCSSDist: { src: ['src/css/*.css'], dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css' }, myJSDist: { src: ['src/js/*.js'], dest: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js' }, }, cssmin:{ options: { stripBanners: true, banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */' }, build:{ src: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css', dest: 'dist/css/<%= pkg.name %>-<%= pkg.version %>.min.css' } }, uglify:{ options: { stripBanners: true, banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */' }, build:{ src: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js', dest: 'dist/js/<%= pkg.name %>-<%= pkg.version %>.min.js' } }, jshint:{ options:{ jshintrc:'.jshintrc' }, build:['Gruntfile.js','src/js/*.js'] }, csslint:{ options:{ csslintrc:'.csslintrc' }, build:['src/css/*.css'] }, watch:{ build:{ files: ['src/js/*.js','src/css/*.css'], tasks: ['jshint','csslint','concat','cssmin','uglify'], options:{spawn:false} } } }); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-csslint'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.registerTask('default', ['jshint','csslint','concat','cssmin','uglify','watch']); };
通過在命令行中使用npm install命令來安裝插件

然后執行命令grunt

修改'scrpt1.js'文件內容后,命令行自動顯示如下

變動更新
contrib-watch插件會監聽需要處理的文件的變動,一旦有變動就會自動執行相應處理。但是它有一個問題,就是每當監聽到一處變動時,就會大費周章地把所有被監聽的文件都處理一遍
而newer插件的作用是處理contrib-watch插件的毛病,讓watch在監聽到某個文件變動時,僅僅對變動的文件進行事務處理
package.json的文件內容如下
{ "name": "project", "version": "1.0.0", "devDependencies": { "grunt": "^1.0.1", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-csslint": "^2.0.0", "grunt-contrib-cssmin": "^2.2.0", "grunt-contrib-jshint": "^1.1.0", "grunt-contrib-uglify": "^3.0.1", "grunt-contrib-watch": "^1.0.0", "grunt-contrib-requirejs": "^1.0.0", "grunt-newer":"^1.3.0" } }
Gruntfile.js的配置文件如下
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { options: { stripBanners: true, banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */' }, myCSSDist: { src: ['src/css/*.css'], dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css' }, myJSDist: { src: ['src/js/*.js'], dest: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js' }, }, cssmin:{ options: { stripBanners: true, banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */' }, build:{ src: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css', dest: 'dist/css/<%= pkg.name %>-<%= pkg.version %>.min.css' } }, uglify:{ options: { stripBanners: true, banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */' }, build:{ src: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js', dest: 'dist/js/<%= pkg.name %>-<%= pkg.version %>.min.js' } }, jshint:{ options:{ jshintrc:'.jshintrc' }, build:['Gruntfile.js','src/js/*.js'] }, csslint:{ options:{ csslintrc:'.csslintrc' }, build:['src/css/*.css'] }, watch:{ build:{ files: ['src/js/*.js','src/css/*.css'], tasks: ['newer:jshint','newer:csslint','newer:concat','newer:cssmin','newer:uglify'], options:{spawn:false} } } }); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-csslint'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-newer'); grunt.registerTask('default', ['newer:jshint','newer:csslint','newer:concat','newer:cssmin','newer:uglify','watch']); };
執行命令grunt
grunt
由于'script1.js'的內容發生了變化,所以重新合并了js文件,project-1.0.0.min.js的內容如下
/* 2017-06-09 */ console.log("a"),console.log("b");
由于css的內容沒有發生變化,所以project-1.0.0.min.css的內容如下
/*! project - v1.0.0 - 2017-05-29 */body{margin:0}ul{list-style:none;margin:0;padding:0}
模塊化
下面說明grunt如何與requireJS配合使用,需要使用contrib-requirejs插件
npm install grunt-contrib-requirejs
該插件的使用與r.js的使用類似,不需要建立單獨的build.js文件,而是在Gruntfile.js中配置
設置如下項目結構,src為開發環境,dist為上線環境

在r.js中,可以使用'dir'配置項,將項目目錄復制到一個新的地方。但是,在實際項目開發中,有許多文件與requirejs無關,也會被復制。所以,不應該使用'dir',而應該使用'out'配置項,只是將入口文件main.js打包到一個新的地方
一般地,jQuery并不打包到main.js文件中。如果使用相對路徑,打包前的main.js(開發環境)與jQuery存在路徑依賴關系。打包后的main.js已經處于新的環境(上線環境),但此時仍然與開發環境的jQuery存在路徑依賴關系,不符合邏輯
所以,jQuery應該是上線環境的地址。由于打包后,main.js的config也會打包進行,新的main.js的位置發生變化,jQuery的相對路徑也會變化。所以config應該寫在index.html頁面中。這樣,在jQuery或main.js的路徑發生變化時,可以進行改動
因此,script1.js和script2.js這兩個文件的內容如下
//script.js define(['jquery'],function (){ return $('div').height(); }) //s2.js define(['jquery'],function (){ return $('div').width(); })
main.js的內容如下
//main.js require(['module/script1','module/script2'], function(a,b){ console.log(a); console.log(b); });
index.html代碼如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div></div> <script data-main="main" src="dist/js/require.js"></script> <script> require.config({ baseUrl:'src/js', paths:{ 'jquery':'../../dist/js/jquery' } }); </script> </body> </html>
package.json的文件內容如下
{ "name": "project", "version": "1.0.0", "devDependencies": { "grunt": "^1.0.1", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-csslint": "^2.0.0", "grunt-contrib-cssmin": "^2.2.0", "grunt-contrib-jshint": "^1.1.0", "grunt-contrib-uglify": "^3.0.1", "grunt-contrib-watch": "^1.0.0", "grunt-contrib-requirejs": "^1.0.0", "grunt-newer":"^1.3.0" } }
【contrib-requirejs插件配置】
由于該插件打包后的文件,內容還是使用原來的路徑關系。但是,開發和線上的路徑并不一致。所以,要把可能會變化的路徑設置為'baseUrl',其他的路徑保持一致
[注意]contrib-requirejs插件不能與newer插件混用
requirejs: { compile: { options: { baseUrl: 'src/js', paths:{ jquery:'../../dist/js/jquery' }, name: 'main', out:'dist/js/main.js', exclude: ['jquery'] } } }
Gruntfile.js的配置文件如下
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { options: { stripBanners: true, banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */' }, myCSSDist: { src: ['src/css/*.css'], dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css' } }, cssmin:{ options: { stripBanners: true, banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */' }, build:{ src: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css', dest: 'dist/css/<%= pkg.name %>-<%= pkg.version %>.min.css' } }, jshint:{ options:{ jshintrc:'.jshintrc' }, build:['Gruntfile.js','src/js/*.js'] }, csslint:{ options:{ csslintrc:'.csslintrc' }, build:['src/css/*.css'] }, requirejs: { compile: { options: { baseUrl: 'src/js', paths:{ jquery:'../../dist/js/jquery' }, name: 'main', out:'dist/js/main.js', exclude: ['jquery'] } } }, watch:{ build:{ files: ['src/js/*.js','src/css/*.css'], tasks: ['newer:jshint','newer:csslint','newer:concat','newer:cssmin','newer:uglify','requirejs'], options:{spawn:false} } } }); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-csslint'); grunt.loadNpmTasks('grunt-contrib-requirejs'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-newer'); grunt.registerTask('default', ['newer:jshint','newer:csslint','newer:concat','newer:cssmin','requirejs','watch']); };
執行命令grunt

更改index.html頁面如下,依然能正常顯示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div></div> <script data-main="main" src="dist/js/require.js"></script> <script> require.config({ baseUrl:'dist/js', paths:{ 'jquery':'../../dist/js/jquery' } }); </script> </body> </html>
文章列表