直接grunt serve讀的css是.tmp/css/main.css 而這個文件不經過build生成出來是這樣:javascript
/* Encoding::CompatibilityError: incompatible character encodings: GBK and UTF-8 Backtrace: C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/util.rb:1185:in `absolute_path' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/util.rb:1185:in `absolute_path' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/importers/filesystem.rb:70:in `public_url' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/engine.rb:372:in `block in _render_with_sourcemap' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/util.rb:496:in `silence_warnings' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/engine.rb:370:in `_render_with_sourcemap' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/engine.rb:298:in `render_with_sourcemap' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/plugin/compiler.rb:492:in `update_stylesheet' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/plugin/compiler.rb:215:in `block in update_stylesheets' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/plugin/compiler.rb:209:in `each' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.4.23/lib/sass/plugin/compiler.rb:209:in `update_stylesheets' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/compass-1.0.3/lib/compass/sass_compiler.rb:40:in `compile!' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/compass-1.0.3/lib/compass/commands/update_project.rb:49:in `perform' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/compass-1.0.3/lib/compass/commands/base.rb:18:in `execute' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/compass-1.0.3/lib/compass/commands/project_base.rb:19:in `execute' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/compass-1.0.3/lib/compass/exec/sub_command_ui.rb:43:in `perform!' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/compass-1.0.3/lib/compass/exec/sub_command_ui.rb:15:in `run!' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/compass-1.0.3/bin/compass:30:in `block in <top (required)>' C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/compass-1.0.3/bin/compass:44:in `<top (required)>' C:/Ruby23-x64/bin/compass:22:in `load' C:/Ruby23-x64/bin/compass:22:in `<main>' */ body:before { white-space: pre; font-family: monospace; content: "Encoding::CompatibilityError: incompatible character encodings: GBK and UTF-8"; } /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm1haW4uY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBeUJFO0FBQ0Y7RUFDRSxpQkFBaUI7RUFDakIsdUJBQXVCO0VBQ3ZCLHlGQUF5RixFQUFFIiwiZmlsZSI6Im1haW4uY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuRW5jb2Rpbmc6OkNvbXBhdGliaWxpdHlFcnJvcjogaW5jb21wYXRpYmxlIGNoYXJhY3RlciBlbmNvZGluZ3M6IEdCSyBhbmQgVVRGLThcclxuXHJcbkJhY2t0cmFjZTpcclxuQzovUnVieTIzLXg2NC9saWIvcnVieS9nZW1zLzIuMy4wL2dlbXMvc2Fzcy0zLjQuMjMvbGliL3Nhc3MvdXRpbC5yYjoxMTg1OmluIGBhYnNvbHV0ZV9wYXRoJ1xyXG5DOi9SdWJ5MjMteDY0L2xpYi9ydWJ5L2dlbXMvMi4zLjAvZ2Vtcy9zYXNzLTMuNC4yMy9saWIvc2Fzcy91dGlsLnJiOjExODU6aW4gYGFic29sdXRlX3BhdGgnXHJcbkM6L1J1YnkyMy14NjQvbGliL3J1YnkvZ2Vtcy8yLjMuMC9nZW1zL3Nhc3MtMy40LjIzL2xpYi9zYXNzL2ltcG9ydGVycy9maWxlc3lzdGVtLnJiOjcwOmluIGBwdWJsaWNfdXJsJ1xyXG5DOi9SdWJ5MjMteDY0L2xpYi9ydWJ5L2dlbXMvMi4zLjAvZ2Vtcy9zYXNzLTMuNC4yMy9saWIvc2Fzcy9lbmdpbmUucmI6MzcyOmluIGBibG9jayBpbiBfcmVuZGVyX3dpdGhfc291cmNlbWFwJ1xyXG5DOi9SdWJ5MjMteDY0L2xpYi9ydWJ5L2dlbXMvMi4zLjAvZ2Vtcy9zYXNzLTMuNC4yMy9saWIvc2Fzcy91dGlsLnJiOjQ5NjppbiBgc2lsZW5jZV93YXJuaW5ncydcclxuQzovUnVieTIzLXg2NC9saWIvcnVieS9nZW1zLzIuMy4wL2dlbXMvc2Fzcy0zLjQuMjMvbGliL3Nhc3MvZW5naW5lLnJiOjM3MDppbiBgX3JlbmRlcl93aXRoX3NvdXJjZW1hcCdcclxuQzovUnVieTIzLXg2NC9saWIvcnVieS9nZW1zLzIuMy4wL2dlbXMvc2Fzcy0zLjQuMjMvbGliL3Nhc3MvZW5naW5lLnJiOjI5ODppbiBgcmVuZGVyX3dpdGhfc291cmNlbWFwJ1xyXG5DOi9SdWJ5MjMteDY0L2xpYi9ydWJ5L2dlbXMvMi4zLjAvZ2Vtcy9zYXNzLTMuNC4yMy9saWIvc2Fzcy9wbHVnaW4vY29tcGlsZXIucmI6NDkyOmluIGB1cGRhdGVfc3R5bGVzaGVldCdcclxuQzovUnVieTIzLXg2NC9saWIvcnVieS9nZW1zLzIuMy4wL2dlbXMvc2Fzcy0zLjQuMjMvbGliL3Nhc3MvcGx1Z2luL2NvbXBpbGVyLnJiOjIxNTppbiBgYmxvY2sgaW4gdXBkYXRlX3N0eWxlc2hlZXRzJ1xyXG5DOi9SdWJ5MjMteDY0L2xpYi9ydWJ5L2dlbXMvMi4zLjAvZ2Vtcy9zYXNzLTMuNC4yMy9saWIvc2Fzcy9wbHVnaW4vY29tcGlsZXIucmI6MjA5OmluIGBlYWNoJ1xyXG5DOi9SdWJ5MjMteDY0L2xpYi9ydWJ5L2dlbXMvMi4zLjAvZ2Vtcy9zYXNzLTMuNC4yMy9saWIvc2Fzcy9wbHVnaW4vY29tcGlsZXIucmI6MjA5OmluIGB1cGRhdGVfc3R5bGVzaGVldHMnXHJcbkM6L1J1YnkyMy14NjQvbGliL3J1YnkvZ2Vtcy8yLjMuMC9nZW1zL2NvbXBhc3MtMS4wLjMvbGliL2NvbXBhc3Mvc2Fzc19jb21waWxlci5yYjo0MDppbiBgY29tcGlsZSEnXHJcbkM6L1J1YnkyMy14NjQvbGliL3J1YnkvZ2Vtcy8yLjMuMC9nZW1zL2NvbXBhc3MtMS4wLjMvbGliL2NvbXBhc3MvY29tbWFuZHMvdXBkYXRlX3Byb2plY3QucmI6NDk6aW4gYHBlcmZvcm0nXHJcbkM6L1J1YnkyMy14NjQvbGliL3J1YnkvZ2Vtcy8yLjMuMC9nZW1zL2NvbXBhc3MtMS4wLjMvbGliL2NvbXBhc3MvY29tbWFuZHMvYmFzZS5yYjoxODppbiBgZXhlY3V0ZSdcclxuQzovUnVieTIzLXg2NC9saWIvcnVieS9nZW1zLzIuMy4wL2dlbXMvY29tcGFzcy0xLjAuMy9saWIvY29tcGFzcy9jb21tYW5kcy9wcm9qZWN0X2Jhc2UucmI6MTk6aW4gYGV4ZWN1dGUnXHJcbkM6L1J1YnkyMy14NjQvbGliL3J1YnkvZ2Vtcy8yLjMuMC9nZW1zL2NvbXBhc3MtMS4wLjMvbGliL2NvbXBhc3MvZXhlYy9zdWJfY29tbWFuZF91aS5yYjo0MzppbiBgcGVyZm9ybSEnXHJcbkM6L1J1YnkyMy14NjQvbGliL3J1YnkvZ2Vtcy8yLjMuMC9nZW1zL2NvbXBhc3MtMS4wLjMvbGliL2NvbXBhc3MvZXhlYy9zdWJfY29tbWFuZF91aS5yYjoxNTppbiBgcnVuISdcclxuQzovUnVieTIzLXg2NC9saWIvcnVieS9nZW1zLzIuMy4wL2dlbXMvY29tcGFzcy0xLjAuMy9iaW4vY29tcGFzczozMDppbiBgYmxvY2sgaW4gPHRvcCAocmVxdWlyZWQpPidcclxuQzovUnVieTIzLXg2NC9saWIvcnVieS9nZW1zLzIuMy4wL2dlbXMvY29tcGFzcy0xLjAuMy9iaW4vY29tcGFzczo0NDppbiBgPHRvcCAocmVxdWlyZWQpPidcclxuQzovUnVieTIzLXg2NC9iaW4vY29tcGFzczoyMjppbiBgbG9hZCdcclxuQzovUnVieTIzLXg2NC9iaW4vY29tcGFzczoyMjppbiBgPG1haW4+J1xyXG4qL1xyXG5ib2R5OmJlZm9yZSB7XHJcbiAgd2hpdGUtc3BhY2U6IHByZTtcclxuICBmb250LWZhbWlseTogbW9ub3NwYWNlO1xyXG4gIGNvbnRlbnQ6IFwiRW5jb2Rpbmc6OkNvbXBhdGliaWxpdHlFcnJvcjogaW5jb21wYXRpYmxlIGNoYXJhY3RlciBlbmNvZGluZ3M6IEdCSyBhbmQgVVRGLThcIjsgfVxyXG4iXX0= */
所以頁面上就不會有正常的樣式了,第一行的報錯異常醒目.css
去網上搜關於編碼的問題, 獲得的解答是在scss前面加上一句 @charset "utf-8";html
若是這樣還不能使得grunt server(或者grunt serve)在.tmp文件夾下生成正確的css,前端
從dist拷貝一個過來, 去掉時間戳卻是能夠救個急, 不是長久之計.html5
解決方案參考 https://github.com/imathis/octopress/issues/232java
試過改engin.ruby文件沒有效果:node
C:\Ruby\lib\ruby\gems\1.9.1\gems\sass-3.3.14\lib\sassjquery
在這個文件裏面engine.rb,添加一行代碼(同方法1)git
Encoding.default_external = Encoding.find('utf-8')
放在全部的require XXXX 以後便可, 還嘗試加過下面這兩行,也沒反應.github
//LANG=en_US.UTF-8
LANG=zh_CN.UTF-8
//LC_ALL=en_US.UTF-8
LC_ALL=zh_CN.UTF-8
最後仍是回頭去研究gruntfile.js, 這篇文章頗有啓發:http://blog.csdn.net/u012844719/article/details/23164939
聲明,如下相關全是前端的東西。 Yeoman 一個自動化工做流,說白了就是把一些你須要手動操做的東西,自動給你作好。 個人理解就是給你建立一個項目,而後裏面該有的東西都有了。 官網:http://www.yeoman.io/ Grunt 什麼?大G?,其實不是的。 一個相似maven的東西(不知道maven?,那總知道ant吧),可以對前端的文件進行壓縮,打包,還有部署,(應該不jiào部署,jiào整理,更合適一些)。 官網:http://gruntjs.com/ grunt的強大,在於能夠有不少第三方的插件能夠下載,例如less,coffeescripe等等,grunt能夠幫助你自動編譯這些文件。 Bower 一隻肥鳥,官方說法jiào作A package manager for the web,也就是包管理器。 自我感受不是很好用,好比你須要用jquery,它會把jquery相關的文件所有下載,例如jquery.cokkie.js等,不只浪費時間,還佔用空間。 下面來說解,這三樣東西的具體配置: 安裝Yeoman //首先,你能夠執行 sudo npm install -g yo grunt-cli bower 這樣能夠一下安裝3個文件,固然你也能夠選擇不裝。。 先得安裝Node.js,Git和Ruby,不要問爲何,官網說的。。。 npm install -g yo 建立一個project目錄,定位在該目錄下 而後安裝generator-webapp,這也東西使用來生成器的,也就是可以生成你app的程序 npm install -g generator-webapp -g 的意思是全局安裝,這樣的話你就能夠在任何地方使用yo命令了。 默認狀況下會讓你選擇webapp所用的框架,例如 能夠多選,也能夠單選,選擇後生成的相關配置文件也會根據你的選擇來改變,因此這一配置要慎重。 這樣,yeoman就裝好了。 讓你想執行bower命令時,發現報錯,由於你還沒裝bower。。 安裝Bower npm install -g bower 這個很簡單,先裝上再說,具體用法,下面會講。 安裝Grunt npm install -g grunt-cli cli並非grunt,只是一個可以讓你執行grunt命令的程序 接下來安裝grunt npm install -g grunt 回到你建的project目錄,裝完以後能夠看到 目錄下會有一個Gruntfile.js文件, 這個是grunt的核心文件,也是這三樣東西jiāo互的文件。 // Generated on 2014-04-08 using generator-webapp 0.4.8 'use strict'; // # Globbing // for performance reasons we're only matching one level down: // 'test/spec/{,*/}*.js' // use this if you want to recursively match all subfolders: // 'test/spec/**/*.js' module.exports = function (grunt) { // Load grunt tasks automatically require('load-grunt-tasks')(grunt); // Time how long tasks take. Can help when optimizing build times require('time-grunt')(grunt); // Define the configuration for all the tasks grunt.initConfig({ // Project settings config: { // Configurable paths app: 'app', dist: 'dist' }, // Watches files for changes and runs tasks based on the changed files watch: { bower: { files: ['bower.json'], tasks: ['bowerInstall'] }, js: { files: ['<%= config.app %>/scripts/{,*/}*.js'], tasks: ['jshint'], options: { livereload: true } }, jstest: { files: ['test/spec/{,*/}*.js'], tasks: ['test:watch'] }, gruntfile: { files: ['Gruntfile.js'] }, styles: { files: ['<%= config.app %>/styles/{,*/}*.css'], tasks: ['newer:copy:styles', 'autoprefixer'] }, livereload: { options: { livereload: '<%= connect.options.livereload %>' }, files: [ '<%= config.app %>/{,*/}*.html', '.tmp/styles/{,*/}*.css', '<%= config.app %>/images/{,*/}*' ] } }, // The actual grunt server settings connect: { options: { port: 9000, livereload: 35729, // Change this to '0.0.0.0' to access the server from outside hostname: 'localhost' }, livereload: { options: { open: true, base: [ '.tmp', '<%= config.app %>' ] } }, test: { options: { port: 9001, base: [ '.tmp', 'test', '<%= config.app %>' ] } }, dist: { options: { open: true, base: '<%= config.dist %>', livereload: false } } }, // Empties folders to start fresh clean: { dist: { files: [{ dot: true, src: [ '.tmp', '<%= config.dist %>/*', '!<%= config.dist %>/.git*' ] }] }, server: '.tmp' }, // Make sure code styles are up to par and there are no obvious mistakes jshint: { options: { jshintrc: '.jshintrc', reporter: require('jshint-stylish') }, all: [ 'Gruntfile.js', '<%= config.app %>/scripts/{,*/}*.js', '!<%= config.app %>/scripts/vendor/*', 'test/spec/{,*/}*.js' ] }, // Mocha testing framework configuration options mocha: { all: { options: { run: true, urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html'] } } }, // Add vendor prefixed styles autoprefixer: { options: { browsers: ['last 1 version'] }, dist: { files: [{ expand: true, cwd: '.tmp/styles/', src: '{,*/}*.css', dest: '.tmp/styles/' }] } }, // Automatically inject Bower components into the HTML file bowerInstall: { app: { src: ['<%= config.app %>/index.html'], ignorePath: '<%= config.app %>/' } }, // Renames files for browser caching purposes rev: { dist: { files: { src: [ '<%= config.dist %>/scripts/{,*/}*.js', '<%= config.dist %>/styles/{,*/}*.css', '<%= config.dist %>/images/{,*/}*.*', '<%= config.dist %>/styles/fonts/{,*/}*.*', '<%= config.dist %>/*.{ico,png}' ] } } }, // Reads HTML for usemin blocks to enable smart builds that automatically // concat, minify and revision files. Creates configurations in memory so // additional tasks can operate on them useminPrepare: { options: { dest: '<%= config.dist %>' }, html: '<%= config.app %>/index.html' }, // Performs rewrites based on rev and the useminPrepare configuration usemin: { options: { assetsDirs: ['<%= config.dist %>', '<%= config.dist %>/images'] }, html: ['<%= config.dist %>/{,*/}*.html'], css: ['<%= config.dist %>/styles/{,*/}*.css'] }, // The following *-min tasks produce minified files in the dist folder imagemin: { dist: { files: [{ expand: true, cwd: '<%= config.app %>/images', src: '{,*/}*.{gif,jpeg,jpg,png}', dest: '<%= config.dist %>/images' }] } }, svgmin: { dist: { files: [{ expand: true, cwd: '<%= config.app %>/images', src: '{,*/}*.svg', dest: '<%= config.dist %>/images' }] } }, htmlmin: { dist: { options: { collapseBooleanAttributes: true, collapseWhitespace: true, removeAttributeQuotes: true, removeCommentsFromCDATA: true, removeEmptyAttributes: true, removeOptionalTags: true, removeRedundantAttributes: true, useShortDoctype: true }, files: [{ expand: true, cwd: '<%= config.dist %>', src: '{,*/}*.html', dest: '<%= config.dist %>' }] } }, // By default, your `index.html`'s <!-- Usemin block --> will take care of // minification. These next options are pre-configured if you do not wish // to use the Usemin blocks. // cssmin: { // dist: { // files: { // '<%= config.dist %>/styles/main.css': [ // '.tmp/styles/{,*/}*.css', // '<%= config.app %>/styles/{,*/}*.css' // ] // } // } // }, // uglify: { // dist: { // files: { // '<%= config.dist %>/scripts/scripts.js': [ // '<%= config.dist %>/scripts/scripts.js' // ] // } // } // }, // concat: { // dist: {} // }, // Copies remaining files to places other tasks can use copy: { dist: { files: [{ expand: true, dot: true, cwd: '<%= config.app %>', dest: '<%= config.dist %>', src: [ '*.{ico,png,txt}', '.htaccess', 'images/{,*/}*.webp', '{,*/}*.html', 'styles/fonts/{,*/}*.*', 'bower_components/bootstrap/dist/fonts/*.*' ] }] }, styles: { expand: true, dot: true, cwd: '<%= config.app %>/styles', dest: '.tmp/styles/', src: '{,*/}*.css' } }, // Run some tasks in parallel to speed up build process concurrent: { server: [ 'copy:styles' ], test: [ 'copy:styles' ], dist: [ 'copy:styles', 'imagemin', 'svgmin' ] } }); grunt.registerTask('serve', function (target) { if (target === 'dist') { return grunt.task.run(['build', 'connect:dist:keepalive']); } grunt.task.run([ 'clean:server', 'concurrent:server', 'autoprefixer', 'connect:livereload', 'watch' ]); }); grunt.registerTask('server', function (target) { grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); grunt.task.run([target ? ('serve:' + target) : 'serve']); }); grunt.registerTask('test', function (target) { if (target !== 'watch') { grunt.task.run([ 'clean:server', 'concurrent:test', 'autoprefixer' ]); } grunt.task.run([ 'connect:test', 'mocha' ]); }); grunt.registerTask('build', [ 'clean:dist', 'useminPrepare', 'concurrent:dist', 'autoprefixer', 'concat', 'cssmin', 'uglify', 'copy:dist', 'rev', 'usemin', 'htmlmin' ]); grunt.registerTask('default', [ 'newer:jshint', 'test', 'build' ]); }; 這是系統默認生成的,當時我選擇的是bootstrap。 能夠看到,文件中的每一個配置項都是一個task,而且沒一個task都是須要下載grunt插件的。 require('load-grunt-tasks')(grunt); 這段代碼很重要,他會找到項目下的node_modules文件夾,把其中的grunt插件所有引入。 接下來即可以執行grunt serve命令了 grunt.registerTask('serve', function (target) { if (target === 'dist') { return grunt.task.run(['build', 'connect:dist:keepalive']); } grunt.task.run([ 'clean:server', 'concurrent:server', 'autoprefixer', 'connect:livereload', 'watch' ]); }); 能夠看到這個serve命令還接受一個參數target,若是執行grunt serve dist 就會執行build task還有connect下的dist下的 keeplive task。 若是不傳參數,正常執行if外面的命令,最後也個watch task很關鍵,會啓動一個臨時server來給你debug用,會監聽你的每一個文件是否改變來刷新你的瀏覽器(livereload task配置相 關),很智能吧。
後來我去掉了concurrent任務中的compass後面的server,直接運行本地compass就能夠正常打包css到.tmp目錄了.
// Generated on 2015-12-09 using generator-angular 0.14.0 'use strict'; // # Globbing // for performance reasons we're only matching one level down: // 'test/spec/{,*/}*.js' // use this if you want to recursively match all subfolders: // 'test/spec/**/*.js' module.exports = function (grunt) { // Time how long tasks take. Can help when optimizing build times require('time-grunt')(grunt); // Automatically load required Grunt tasks require('jit-grunt')(grunt, { useminPrepare: 'grunt-usemin', ngtemplates: 'grunt-angular-templates', cdnify: 'grunt-google-cdn' }); // Configurable paths for the application var appConfig = { app: require('./bower.json').appPath || 'app', dist: 'dist' }; // Define the configuration for all the tasks grunt.initConfig({ // Project settings yeoman: appConfig, // Watches files for changes and runs tasks based on the changed files watch: { bower: { files: ['bower.json'], tasks: ['wiredep'] }, js: { files: ['<%= yeoman.app %>/js/{,*/,*/*/}*.js'], tasks: ['newer:jshint:all', 'newer:jscs:all'], options: { livereload: '<%= connect.options.livereload %>' } }, jsTest: { files: ['test/spec/{,*/}*.js'], tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma'] }, compass: { files: ['<%= yeoman.app %>/css/{,*/,*/*/}*.{scss,sass}'], tasks: ['compass:server', 'postcss:server'] }, gruntfile: { files: ['Gruntfile.js'] }, livereload: { options: { livereload: '<%= connect.options.livereload %>' }, files: [ '<%= yeoman.app %>/{,*/,*/*/}*.html', '.tmp/css/{,*/}*.css', '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' ] } }, // The actual grunt server settings connect: { options: { port: 9000, // Change this to '0.0.0.0' to access the server from outside. hostname: 'localhost', livereload: 35729 }, livereload: { options: { open: true, middleware: function (connect) { return [ connect.static('.tmp'), connect().use( '/bower_components', connect.static('./bower_components') ), connect().use( '/app/css', connect.static('./app/css') ), connect.static(appConfig.app) ]; } } }, test: { options: { port: 9001, middleware: function (connect) { return [ connect.static('.tmp'), connect.static('test'), connect().use( '/bower_components', connect.static('./bower_components') ), connect.static(appConfig.app) ]; } } }, dist: { options: { open: true, base: '<%= yeoman.dist %>' } } }, // Make sure there are no obvious mistakes jshint: { options: { jshintrc: '.jshintrc', reporter: require('jshint-stylish') }, all: { src: [ 'Gruntfile.js', '<%= yeoman.app %>/js/{,*/}*.js' ] }, test: { options: { jshintrc: 'test/.jshintrc' }, src: ['test/spec/{,*/}*.js'] } }, // Make sure code styles are up to par jscs: { options: { config: '.jscsrc', verbose: true }, all: { src: [ 'Gruntfile.js', '<%= yeoman.app %>/js/{,*/}*.js' ] }, test: { src: ['test/spec/{,*/}*.js'] } }, // Empties folders to start fresh clean: { dist: { files: [{ dot: true, src: [ '.tmp', '<%= yeoman.dist %>/{,*/}*', '!<%= yeoman.dist %>/.git{,*/}*' ] }] }, server: '.tmp' }, // Add vendor prefixed styles postcss: { options: { processors: [ require('autoprefixer-core')({browsers: ['last 1 version']}) ] }, server: { options: { map: true }, files: [{ expand: true, cwd: '.tmp/css/', src: '{,*/}*.css', dest: '.tmp/css/' }] }, dist: { files: [{ expand: true, cwd: '.tmp/css/', src: '{,*/}*.css', dest: '.tmp/css/' }] } }, // Automatically inject Bower components into the app wiredep: { app: { src: ['<%= yeoman.app %>/index.html'], ignorePath: /\.\.\// }, test: { devDependencies: true, src: '<%= karma.unit.configFile %>', ignorePath: /\.\.\//, fileTypes:{ js: { block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi, detect: { js: /'(.*\.js)'/gi }, replace: { js: '\'{{filePath}}\',' } } } }, sass: { src: ['<%= yeoman.app %>/css/{,*/}*.{scss,sass}'], ignorePath: /(\.\.\/){1,2}bower_components\// } }, // Compiles Sass to CSS and generates necessary files if requested compass: { options: { sassDir: '<%= yeoman.app %>/css', cssDir: '.tmp/css', generatedImagesDir: '.tmp/images/generated', imagesDir: '<%= yeoman.app %>/images', javascriptsDir: '<%= yeoman.app %>/js', fontsDir: '<%= yeoman.app %>/css/fonts', importPath: './bower_components', httpImagesPath: '/images', httpGeneratedImagesPath: '/images/generated', httpFontsPath: '/css/fonts', relativeAssets: false, assetCacheBuster: false, raw: 'Sass::Script::Number.precision = 10\n' }, dist: { options: { generatedImagesDir: '<%= yeoman.dist %>/images/generated' } }, server: { options: { sourcemap: true } } }, // Renames files for browser caching purposes filerev: { dist: { src: [ '<%= yeoman.dist %>/js/{,*/}*.js', '<%= yeoman.dist %>/css/{,*/}*.css', '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', '<%= yeoman.dist %>/css/fonts/*' ] } }, // Reads HTML for usemin blocks to enable smart builds that automatically // concat, minify and revision files. Creates configurations in memory so // additional tasks can operate on them useminPrepare: { html: '<%= yeoman.app %>/index.html', options: { dest: '<%= yeoman.dist %>', flow: { html: { steps: { js: ['concat', 'uglifyjs'], css: ['cssmin'] }, post: {} } } } }, // Performs rewrites based on filerev and the useminPrepare configuration usemin: { html: ['<%= yeoman.dist %>/{,*/,*/*/}*.html'], css: ['<%= yeoman.dist %>/css/{,*/}*.css'], js: ['<%= yeoman.dist %>/js/{,*/}*.js'], options: { assetsDirs: [ '<%= yeoman.dist %>', '<%= yeoman.dist %>/images', '<%= yeoman.dist %>/css' ], patterns: { js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']] } } }, // The following *-min tasks will produce minified files in the dist folder // By default, your `index.html`'s <!-- Usemin block --> will take care of // minification. These next options are pre-configured if you do not wish // to use the Usemin blocks. cssmin: { dist: { files: { '<%= yeoman.dist %>/css/main.css': [ '.tmp/css/{,*/}*.css' ] } }, options: { rebase: false } }, uglify: { options: { mangle: false } }, concat: { dist: {} }, imagemin: { dist: { files: [{ expand: true, cwd: '<%= yeoman.app %>/images', src: '{,*/}*.{png,jpg,jpeg,gif}', dest: '<%= yeoman.dist %>/images' }] } }, svgmin: { dist: { files: [{ expand: true, cwd: '<%= yeoman.app %>/images', src: '{,*/}*.svg', dest: '<%= yeoman.dist %>/images' }] } }, htmlmin: { dist: { options: { collapseWhitespace: true, conservativeCollapse: true, collapseBooleanAttributes: true, removeCommentsFromCDATA: true }, files: [{ expand: true, cwd: '<%= yeoman.dist %>', src: ['{*,*/,*/*/}*.html'], dest: '<%= yeoman.dist %>' }] } }, ngtemplates: { dist: { options: { module: 'warrantyProcessApp', htmlmin: '<%= htmlmin.dist.options %>', usemin: 'js/scripts.js' }, cwd: '<%= yeoman.app %>', src: 'html/{,*/,*/*/}.html', dest: '.tmp/templateCache.js' } }, // ng-annotate tries to make the code safe for minification automatically // by using the Angular long form for dependency injection. ngAnnotate: { dist: { files: [{ expand: true, cwd: '.tmp/concat/js', src: '*.js', dest: '.tmp/concat/js' }] } }, // Replace Google CDN references cdnify: { dist: { html: ['<%= yeoman.dist %>/*.html'] } }, // Copies remaining files to places other tasks can use copy: { dist: { files: [{ expand: true, dot: true, cwd: '<%= yeoman.app %>', dest: '<%= yeoman.dist %>', src: [ '*.{ico,png,txt}', '*.html', 'html/{,*/,*/*/}*.html', 'images/{,*/}*.{webp}', 'css/fonts/{,*/}*.*', 'languages/{,*/}*.json', '.htaccess' ] }, { expand: true, cwd: '.tmp/images', dest: '<%= yeoman.dist %>/images', src: ['generated/*'] }, { expand: true, cwd: '.', src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*', dest: '<%= yeoman.dist %>' }] }, styles: { expand: true, cwd: '<%= yeoman.app %>/css', dest: '.tmp/css/', src: '{,*/}*.css' } }, // Run some tasks in parallel to speed up the build process concurrent: { server: [ 'compass:server' ], test: [ 'compass' ], dist: [ 'compass:dist', 'imagemin', 'svgmin' ] }, ngdocs: { options: { dest: 'docs', html5Mode: false, scripts: [ 'bower_components/angular/angular.js', 'bower_components/angular-animate/angular-animate.js' ] }, api: { src: ['app/**/*.js', '!app/**/*-spec.js'], title: 'Docs' } }, // Test settings karma: { unit: { configFile: 'test/karma.conf.js', singleRun: true } } }); grunt.registerTask('serve', 'Compile then start a connect web server', function (target) { if (target === 'dist') { return grunt.task.run(['build', 'connect:dist:keepalive']); } grunt.task.run([ 'clean:server', 'wiredep', 'concurrent:server', 'postcss:server', 'connect:livereload', 'watch' ]); }); grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) { grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); grunt.task.run(['serve:' + target]); }); grunt.registerTask('test', [ 'clean:server', 'wiredep', 'concurrent:test', 'postcss', 'connect:test', 'karma' ]); grunt.registerTask('build', [ 'clean:dist', 'wiredep', 'useminPrepare', 'concurrent:dist', 'postcss', 'ngtemplates', 'concat', 'ngAnnotate', 'copy:dist', 'cdnify', 'cssmin', 'uglify', 'filerev', 'usemin', 'htmlmin' ]); grunt.loadNpmTasks('grunt-html-validation'); grunt.registerTask('default', [ 'newer:jshint', 'newer:jscs', 'test', 'build', 'validation' ]); };
不知道爲何其餘人能夠直接server去打包,反正我是不能夠.