Grunt usemin:在index.html文件中未替换连接的JavaScript文件

时间:2014-03-19 14:17:34

标签: javascript gruntjs bower grunt-usemin grunt-contrib-htmlmin

我从一个由yeoman生成的空项目开始,并尝试编辑Gruntfile.js以满足我的需求。

grunt构建任务读取我的index.html文件,并连接我的bower依赖项并生成.vendor.js文件。

我在工作流程中破坏了某些内容,现在usemin不会替换index.html文件中的标记,即使生成.vendor.js文件也是如此。

这是我的Gruntfile.js

    'use strict';

    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
        yeoman: {
          // configurable paths
          app: require('./bower.json').appPath || 'app',
          dist: 'dist',
        },
        express: {
          options: {
            port: process.env.PORT || 9000
          },
          dev: {
            options: {
              script: 'server.js',
              debug: true
            }
          },
          prod: {
            options: {
              script: 'dist/server.js',
              node_env: 'production'
            }
          }
        },
        open: {
          server: {
            url: 'http://localhost:<%= express.options.port %>'
          }
        },

        // Watches files for changes and runs tasks based on the changed files
        watch: {
          js: {
            files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
            tasks: ['newer:jshint:all'],
            options: {
              livereload: true
            }
          },
          jsTest: {
            files: ['test/spec/{,*/}*.js'],
            tasks: ['newer:jshint:test', 'karma']
          },
          compass: {
            files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
            tasks: ['compass:server', 'autoprefixer']
          },
          gruntfile: {
            files: ['Gruntfile.js']
          },
          livereload: {
            files: [
              '<%= yeoman.app %>/views/{,*//*}*.{html,handlebars}',
              '{.tmp,<%= yeoman.app %>}/styles/{,*//*}*.css',
              '{.tmp,<%= yeoman.app %>}/scripts/{,*//*}*.js',
              '<%= yeoman.app %>/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}',
              '<%= yeoman.app %>/data/{,*/}*.{png,jpg,jpeg,gif,webp,svg,json,pdf}'
            ],

            options: {
              livereload: true
            }
          },
          express: {
            files: [
              'server.js',
              'lib/**/*.{js,json}'
            ],
            tasks: ['newer:jshint:server', 'express:dev'],
            options: {
              livereload: true,
              nospawn: true //Without this option specified express won't be reloaded
            }
          }
        },

        // Make sure code styles are up to par and there are no obvious mistakes
        jshint: {
          options: {
            jshintrc: '.jshintrc',
            reporter: require('jshint-stylish')
          },
          server: {
            options: {
              jshintrc: 'lib/.jshintrc'
            },
            src: [ 'lib/{,*/}*.js']
          },
          all: [
            '<%= yeoman.app %>/scripts/{,*/}*.js'
          ],
          test: {
            options: {
              jshintrc: 'test/.jshintrc'
            },
            src: ['test/spec/{,*/}*.js']
          }
        },

        // Empties folders to start fresh
        clean: {
          dist: {
            files: [{
              dot: true,
              src: [
                '.tmp',
                '<%= yeoman.dist %>/views/*',
                '<%= yeoman.dist %>/public/*',
                '!<%= yeoman.dist %>/public/.git*',
              ]
            }]
          },
          heroku: {
            files: [{
              dot: true,
              src: [
                'heroku/*',
                '!heroku/.git*',
                '!heroku/Procfile'
              ]
            }]
          },
          server: '.tmp'
        },

        // 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 app
        'bower-install': {
          app: {
            html: '<%= yeoman.app %>/views/edit/index.html',
            ignorePath: '<%= yeoman.app %>/'
          }
        },

        // Compiles Sass to CSS and generates necessary files if requested
        compass: {
          options: {
            sassDir: '<%= yeoman.app %>/styles',
            cssDir: '.tmp/styles',
            generatedImagesDir: '.tmp/images/generated',
            imagesDir: '<%= yeoman.app %>/images',
            javascriptsDir: '<%= yeoman.app %>/scripts',
            fontsDir: '<%= yeoman.app %>/styles/fonts',
            importPath: '<%= yeoman.app %>/bower_components',
            httpImagesPath: '/images',
            httpGeneratedImagesPath: '/images/generated',
            httpFontsPath: '/styles/fonts',
            relativeAssets: false,
            assetCacheBuster: false,
            raw: 'Sass::Script::Number.precision = 10\n'
          },
          dist: {
            options: {
              generatedImagesDir: '<%= yeoman.dist %>/public/images/generated'
            }
          },
          server: {
            options: {
              debugInfo: true
            }
          }
        },

        // Renames files for browser caching purposes
        rev: {
          dist: {
            files: {
              src: [
                '<%= yeoman.dist %>/public/scripts/{,*/}*.js',
                '<%= yeoman.dist %>/public/styles/{,*/}*.css',
                //'<%= yeoman.dist %>/public/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
                '<%= yeoman.dist %>/public/styles/fonts/*'
              ]
            }
          }
        },

        // The following *-min tasks produce minified files in the dist folder
        imagemin: {
          dist: {
            files: [{
              expand: true,
              cwd: '<%= yeoman.app %>/images',
              src: '{,*/}*.{png,jpg,jpeg,gif}',
              dest: '<%= yeoman.dist %>/public/images'
            }]
          }
        },


        // 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 %>/views/edit/index.html'
                 //'<%= yeoman.app %>/../views/index.handlebars'
            ],
          options: {
            dest: '<%= yeoman.dist %>/public'
          }
        },

        // Performs rewrites based on rev and the useminPrepare configuration
        usemin: {
          html: ['<%= yeoman.dist %>/views/edit/index.html',
                 '<%= yeoman.dist %>/views/{,*/}*.handlebars'],
          css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
          options: {
            assetsDirs: ['<%= yeoman.dist %>/public', '<%= yeoman.dist %>/public/images']
          }
        },
        svgmin: {
          dist: {
            files: [{
              expand: true,
              cwd: '<%= yeoman.app %>/images',
              src: '{,*/}*.svg',
              dest: '<%= yeoman.dist %>/public/images'
            }]
          }
        },
        htmlmin: {
          dist: {
            options: {
              //collapseWhitespace: true,
              //collapseBooleanAttributes: true,
              //removeCommentsFromCDATA: true,
              //removeOptionalTags: true
            },
            files: {
              '<%= yeoman.dist %>/public/views/edit/index.html': '<%= yeoman.app %>/views/edit/index.html'
            }
            //files: [{
            //  expand: true,
            //  cwd: '<%= yeoman.app %>/views/edit',
            //  src: ['*.html', 'partials/*.html'],
            //  dest: '<%= yeoman.dist %>/public/views/edit'
            //}]
          }
        },

        // Allow the use of non-minsafe AngularJS files. Automatically makes it
        // minsafe compatible so Uglify does not destroy the ng references
        ngmin: {
          dist: {
            files: [{
              expand: true,
              cwd: '.tmp/concat/scripts',
              src: '*.js',
              dest: '.tmp/concat/scripts'
            }]
          }
        },

        // Replace Google CDN references
        cdnify: {
          dist: {
            html: ['<%= yeoman.dist %>/public/views/edit/*.html']
          }
        },

        // Copies remaining files to places other tasks can use
        copy: {
          dist: {
            files: [{
              expand: true,
              dot: true,
              cwd: '<%= yeoman.app %>',
              dest: '<%= yeoman.dist %>/public',
              src: [
                '*.{ico,png,txt}',
                '.htaccess',
                '*.html',
                //'views/edit/{,*/}*.html',
                //'templates/{,*/}*.html',
                'bower_components/**/*',
                'images/{,*/}*.{webp}',
                'data/{,*/}*.*',
                'fonts/**/*'
              ]
            },
            //{
            //  expand: true,
            //  dot: true,
            //  cwd: '<%= yeoman.app %>/views',
            //  dest: '<%= yeoman.dist %>/views',
            //  src: '**/*.handlebars'
            //},
            {
              expand: true,
              cwd: '.tmp/images',
              dest: '<%= yeoman.dist %>/public/images',
              src: ['generated/*']
      }, {
              expand: true,
              dest: '<%= yeoman.dist %>',
              src: [
                'package.json',
                'server.js',
                'lib/**/*'
              ]
            }]
          },
          styles: {
            expand: true,
            cwd: '<%= yeoman.app %>/styles',
            dest: '.tmp/styles/',
            src: '{,*/}*.css'
          }
        },

        // Run some tasks in parallel to speed up the build process
        concurrent: {
          server: [
            'compass:server'
          ],
          test: [
            'compass'
          ],
          dist: [
            'compass:dist',
            'imagemin',
            'svgmin',
            'htmlmin'
          ]
        },

        // 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 %>/styles/main.css': [
        //         '.tmp/styles/{,*/}*.css',
        //         '<%= yeoman.app %>/styles/{,*/}*.css'
        //       ]
        //     }
        //   }
        // },
        // uglify: {
        //   dist: {
        //     files: {
        //       '<%= yeoman.dist %>/scripts/scripts.js': [
        //         '<%= yeoman.dist %>/scripts/scripts.js'
        //       ]
        //     }
        //   }
        // },
        //concat: {
        //   dist: {}
        //},

        // Test settings
        karma: {
          unit: {
            configFile: 'karma.conf.js',
            singleRun: true
          }
        }
      });

      grunt.registerTask('express-keepalive', 'Keep grunt running', function() {
        this.async();
      });

      grunt.registerTask('serve', function (target) {
        if (target === 'dist') {
          return grunt.task.run(['build', 'express:prod', 'open', 'express-keepalive']);
        }

        grunt.task.run([
          'clean:server',
          'bower-install',
          'concurrent:server',
          'autoprefixer',
          'express:dev',
          'open',
          'watch'
        ]);
      });

      grunt.registerTask('server', function () {
        grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
        grunt.task.run(['serve']);
      });

      grunt.registerTask('test', [
        'clean:server',
        'concurrent:test',
        'autoprefixer',
        'karma'
      ]);

      grunt.registerTask('build', [
        'clean:dist',
        'bower-install',
        'useminPrepare',
        'concurrent:dist',
        'autoprefixer',
        'concat',
        'ngmin',
        'copy:dist',
        'cdnify',
        'cssmin',
        'uglify',
        'rev',
        'usemin'
      ]);


      grunt.registerTask('heroku', function () {
        grunt.log.warn('The `heroku` task has been deprecated. Use `grunt build` to build for deployment.');
        grunt.task.run(['build']);
      });

      grunt.registerTask('default', [
        'newer:jshint',
        'test',
        'build'
      ]);
    };

以下是我运行grunt时生成的内容:

    tree dist/public/scripts/
    dist/public/scripts/
    ├── 434e7b5e.scripts-edit.js
    └── ad5d9b7c.vendor-edit.js

的index.html:

    <!-- build:js(app) scripts/vendor-edit.js -->
    <!-- bower:js-->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap.js"></script>
    <script src="bower_components/angular-resource/angular-resource.js"></script>
    <script src="bower_components/angular-cookies/angular-cookies.js"></script>
    <script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
    <script src="bower_components/angular-route/angular-route.js"></script>
    <script src="bower_components/angular-animate/angular-animate.js"></script>
    <script src="bower_components/angular-http-auth/src/http-auth-interceptor.js"></script>
    <script src="bower_components/angular-translate/angular-translate.js"></script>
    <script src="bower_components/angular-translate-storage-cookie/angular-translate-storage-cookie.js"></script>
    <script src="bower_components/angular-translate-storage-local/angular-translate-storage-local.js"></script>
    <script src="bower_components/angular-ui-router/release/angular-ui-router.js"></script>
    <script src="bower_components/moment/moment.js"></script>
    <script src="bower_components/angular-moment/angular-moment.js"></script>
    <script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
    <script src="bower_components/AngularJS-Toaster/toaster.js"></script>
    <!-- endbower -->
    <!-- endbuild -->

最后,这是咕噜声的输出

        Running "compass:dist" (compass) task
        directory .tmp/styles/
           create .tmp/styles/edit.css (16.644s)
           create .tmp/styles/webicons.css (0.156s)
           create .tmp/styles/main.css (10.947s)
        Compilation took 27.77s

        Done, without errors.


        Execution Time (2014-03-19 13:47:21 UTC)
        compass:dist  29.1s  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 100%
        Total 29.2s

        Running "htmlmin:dist" (htmlmin) task
        File dist/public/views/edit/index.html created.

        Done, without errors.


        Execution Time (2014-03-19 13:47:51 UTC)
        loading tasks  13ms  ▇▇▇▇▇▇▇▇▇▇▇▇ 25%
        htmlmin         2ms  ▇▇ 4%
        htmlmin:dist   35ms  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 67%
        Total 52ms

    Running "autoprefixer:dist" (autoprefixer) task
    Prefixed file ".tmp/styles/edit.css" created.
    Prefixed file ".tmp/styles/main.css" created.
    Prefixed file ".tmp/styles/webicons.css" created.

    Running "concat:generated" (concat) task
    File ".tmp/concat/styles/edit.css" created.
    File ".tmp/concat/scripts/vendor-edit.js" created.
    File ".tmp/concat/scripts/scripts-edit.js" created.

    Running "ngmin:dist" (ngmin) task
    ngminifying .tmp/concat/scripts/scripts-edit.js, .tmp/concat/scripts/vendor-edit.js

    Running "copy:dist" (copy) task
    Created 125 directories, copied 907 files

    Running "cdnify:dist" (cdnify) task
    Going through dist/public/views/edit/index.html to update script refs

    Running "cssmin:generated" (cssmin) task
    File dist/public/styles/edit.css created.

    Running "uglify:generated" (uglify) task
    File "dist/public/scripts/vendor-edit.js" created.
    File "dist/public/scripts/scripts-edit.js" created.

    Running "rev:dist" (rev) task
    dist/public/scripts/scripts-edit.js >> 434e7b5e.scripts-edit.js
    dist/public/scripts/vendor-edit.js >> ad5d9b7c.vendor-edit.js
    dist/public/styles/edit.css >> 9d137efe.edit.css

    Running "usemin:html" (usemin) task

    Running "usemin:css" (usemin) task


    Execution Time (2014-03-19 13:46:43 UTC)
    concurrent:test   20.7s  ▇▇▇▇▇▇▇ 15%
    karma:unit         3.8s  ▇▇ 3%
    concurrent:dist   41.9s  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 31%
    ngmin:dist        44.5s  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 33%
    copy:dist          2.2s  ▇ 2%
    uglify:generated  18.1s  ▇▇▇▇▇▇ 14%
    Total 133.9s

理解这一点的任何帮助都将受到赞赏。

5 个答案:

答案 0 :(得分:10)

我会回答我自己的问题:

我的useminprepre配置和usemin配置之间存在差异。

useminprepare写信给<%= yeoman.dist %>/public/views/edit/index.html

并且usemin正在阅读<%= yeoman.dist %>/views/edit/index.html

答案 1 :(得分:4)

出于某种原因,我遇到了同样的问题。在grunt build index.html期间我的grunt usemin:html未更新(但main.css和main.js输出正常)。我尝试了usemin:html 和工作

所以我最终将grunt build移到{{1}}任务列表中的最后一个位置。

不知道为什么会这样,但它会让我到达我需要的地方。万一其他人可以发现这个有用。

答案 2 :(得分:1)

我有类似的问题。在我的情况下,除了凉亭里面的内容外,一切都按预期被替换:css或bower:js标签。看起来usemin无法取代凉亭评论所包围的内容。

答案 3 :(得分:1)

作为标准,请确保在sublime或IDE中选择Unix作为Line Endings。这可能是因为跨平台使用。

enter image description here

答案 4 :(得分:0)

我有同样的问题,grunt正在创建文件vendor.js和scripts.js,但它没有将它们插入index.html,最后它没有替换旧的脚本链接。它通过执行tk120404建议并修复构建过程来解决这个问题。