Javascript Ember.js:如何在index.html中正确包含编译过的模板?

Javascript Ember.js:如何在index.html中正确包含编译过的模板?,javascript,templates,ember.js,Javascript,Templates,Ember.js,我是新加入ember.js的。我设法使用Grunt文件预编译模板。但是,当我将它们包含在index.html中时,会看到一个空页面,模板不会呈现。我做错了什么?如果我不编译模板并直接包含在index.html中,它就可以工作 我使用yeoman.io安装了所有东西(使用bower软件包grunt-ember模板、ember、webapp脚手架) My index.html: <!doctype html> <html> <head> <meta

我是新加入ember.js的。我设法使用Grunt文件预编译模板。但是,当我将它们包含在index.html中时,会看到一个空页面,模板不会呈现。我做错了什么?如果我不编译模板并直接包含在index.html中,它就可以工作

我使用yeoman.io安装了所有东西(使用bower软件包grunt-ember模板、ember、webapp脚手架)

My index.html:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>My New App</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">
    <link rel="shortcut icon" href="/favicon.ico">
    <link rel="stylesheet" href="css/style.css">
</head>
<body>

  <script src="bower_components/jquery/dist/jquery.js"></script>
  <script src="bower_components/handlebars/handlebars.js"></script>    
  <script src="bower_components/ember/ember.js"></script>
  <script src="scripts/templates.js"></script>
  <script src="scripts/app.js"></script>
</body>
</html>
模板:

编辑:application.hbs

    <h2>Welcome to Ember.js</h2>

    {{outlet}}
欢迎来到Ember.js
{{outlet}}
编辑:index.hbs

    <ul>
    {{#each item in model}}
      <li>{{item}}</li>
    {{/each}}
    </ul>
    {{{#模型中的每个项目}
  • {{item}}
  • {{/每个}}
templates.js中编译的模板:

define(["ember"], function(Ember){

Ember.TEMPLATES["application"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {};
  var buffer = '', stack1;


  data.buffer.push("<h2>Welcome to Ember.js</h2>\n\n");
  stack1 = helpers._triageMustache.call(depth0, "outlet", {hash:{},hashTypes:{},hashContexts:{},contexts:[depth0],types:["ID"],data:data});
  if(stack1 || stack1 === 0) { data.buffer.push(stack1); }
  return buffer;

});

Ember.TEMPLATES["index"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {};
  var buffer = '', stack1, self=this;

function program1(depth0,data) {

  var buffer = '', stack1;
  data.buffer.push("\n  <li>");
  stack1 = helpers._triageMustache.call(depth0, "item", {hash:{},hashTypes:{},hashContexts:{},contexts:[depth0],types:["ID"],data:data});
  if(stack1 || stack1 === 0) { data.buffer.push(stack1); }
  data.buffer.push("</li>\n ");
  return buffer;
  }

  data.buffer.push("\n<ul>\n    ");
  stack1 = helpers.each.call(depth0, "item", "in", "model", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0,depth0,depth0],types:["ID","ID","ID"],data:data});
  if(stack1 || stack1 === 0) { data.buffer.push(stack1); }
  data.buffer.push("\n</ul>\n");
  return buffer;

});

});
定义([“余烬”],函数(余烬){
Ember.TEMPLATES[“application”]=Ember.handlebar.template(匿名函数(handlebar、depth0、helpers、partials、data){
this.compilerInfo=[4',>=1.0.0'];
helpers=this.merge(helpers,Ember.handlebar.helpers);data=data |{};
变量缓冲区='',堆栈1;
data.buffer.push(“欢迎使用Ember.js\n\n”);
stack1=helpers.\u triageMustache.call(depth0,“outlet”,{hash:{},hashTypes:{},hashContexts:{},contexts:[depth0],types:[“ID”],data:data});
如果(stack1 | | stack1==0){data.buffer.push(stack1);}
返回缓冲区;
});
Ember.TEMPLATES[“index”]=Ember.handlebar.template(匿名函数(handlebar、depth0、helpers、partials、data){
this.compilerInfo=[4',>=1.0.0'];
helpers=this.merge(helpers,Ember.handlebar.helpers);data=data |{};
var buffer='',stack1,self=this;
功能程序1(深度0,数据){
变量缓冲区='',堆栈1;
data.buffer.push(“\n
  • ”); stack1=helpers.\u triageMustache.call(depth0,“item”,{hash:{},hashTypes:{},hashContexts:{},contexts:[depth0],types:[“ID”],data:data}); 如果(stack1 | | stack1==0){data.buffer.push(stack1);} data.buffer.push(“
  • \n”); 返回缓冲区; } data.buffer.push(“\n
      \n”); stack1=helpers.each.call(depth0,“item”,“in”,“model”,{hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(1,program1,data),contexts:[depth0,depth0,depth0],type:[“ID”,“ID”],data:data}); 如果(stack1 | | stack1==0){data.buffer.push(stack1);} data.buffer.push(“\n
    \n”); 返回缓冲区; }); });
    您不清楚如何编译模板。它们是来自*.hbs文件,还是您使用了不同的方法

    在我看来,您正在尝试将templates.html文件编译为单个模板,因为模板本身包含以下代码:

    data.buffer.push("\n<script type=\"text/x-handlebars\">\n 
    
    data.buffer.push(“\n\n”
    
    每个模板文件应该只包含模板的内容,而不是脚本标记本身

    通常,您会将每个.hbs文件放在一个单独的文件中,该文件与用于确定模板名称的文件一起使用

    我之前做过一个演示,我正在使用grunt对一个应用程序进行实时编码。这个屏幕显示了如何组织.hbs文件,而源代码显示了它们是如何遵守的。这显示了我的开发过程是如何进行的,以及使用grunt作为构建系统构建一个完整的应用程序

    该演示文稿在YouTube上发布: 源代码位于GitHub上:


    希望有帮助!

    我通过从grunt ember templates grunt配置中删除amd:true选项解决了这个问题。老实说,我在不知道它的功能的情况下添加了它

    为了完整起见,这里是我当前的grunt文件。该文件是由yeoman.io webapp generator自动生成的,我只添加了grunt ember模板配置(在emberTemplates下定义的配置)

    到今天为止,我在网上找到的所有指南都不完整或过时,这对我来说很有效

    // Generated on 2014-03-24 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);
    
        grunt.loadNpmTasks('grunt-ember-templates');
        // Define the configuration for all the tasks
        grunt.initConfig({
    
            // Project settings
            config: {
                // Configurable paths
                app: 'app',
                dist: 'dist'
            },
    
            emberTemplates: {
                compile: {
                    options: {
    
                        templateBasePath: /app\/templates\//
                    //templateName: function(sourceFile) {
                    //        console.log(sourceFile.replace(/app\/templates\//, ''));
                    //       return sourceFile.replace(/app\/templates\//, '');
                    //    }
                    },
                    files: {
                        '<%= config.app %>/scripts/templates.js': ['<%= config.app %>/templates/*.hbs']
                    }
                }
            },
            // Watches files for changes and runs tasks based on the changed files
            watch: {
                emberTemplates: {
                    files: '<%= config.app %>/templates/*.hbs',
                    tasks: ['emberTemplates', 'livereload']
                },
                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/{,*/}*.*'
                        ]
                    }]
                },
                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'
        ]);
    };
    
    //使用generator webapp 0.4.8于2014年3月24日生成
    "严格使用",;
    //#全球化
    //出于性能原因,我们只降低了一个级别:
    //'test/spec/{,*/}*.js'
    //如果要递归匹配所有子文件夹,请使用此选项:
    //“test/spec/***.js”
    module.exports=函数(grunt){
    //自动加载grunt任务
    要求('load-grunt-tasks')(grunt);
    //任务所需的时间。可以帮助优化构建时间
    要求(“时间咕噜”)(咕噜);
    grunt.loadNpmTasks('grunt-ember-templates');
    //定义所有任务的配置
    grunt.initConfig({
    //项目设置
    配置:{
    //可配置路径
    应用程序:“应用程序”,
    dist:“dist”
    },
    模板:{
    汇编:{
    选项:{
    templateBasePath:/app\/templates\//
    //templateName:函数(源文件){
    //console.log(sourceFile.replace(/app\/templates\/,“”));
    //返回sourceFile.replace(/app\/templates\/,“”);
    //    }
    },
    档案:{
    '/scripts/templates.js':['/templates/*.hbs']
    }
    }
    },
    //监视文件的更改,并基于更改的文件运行任务
    观察:{
    模板:{
    文件:'/templates/*.hbs',
    任务:['emberTemplates','livereload']
    },
    鲍尔:{
    文件:['bower.json'],
    任务:['bowerInstall']
    },
    js:{
    文件:['/scripts/{,*/}*.js'],
    任务:['jshint'],
    选项:{
    利弗雷罗德:没错
    }
    },
    jstest:{
    文件:['test/spec/{,*/}*.js'],
    任务:[“测试:监视”]
    },
    Grunfile:{
    文件:['grunfile.js']
    },
    风格:{
    文件:['/styles/{,*/}*.css'],
    任务:[“更新的:复制:样式”,“自动引用器”]
    },
    利弗雷罗德:{
    选项:{
    
    // Generated on 2014-03-24 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);
    
        grunt.loadNpmTasks('grunt-ember-templates');
        // Define the configuration for all the tasks
        grunt.initConfig({
    
            // Project settings
            config: {
                // Configurable paths
                app: 'app',
                dist: 'dist'
            },
    
            emberTemplates: {
                compile: {
                    options: {
    
                        templateBasePath: /app\/templates\//
                    //templateName: function(sourceFile) {
                    //        console.log(sourceFile.replace(/app\/templates\//, ''));
                    //       return sourceFile.replace(/app\/templates\//, '');
                    //    }
                    },
                    files: {
                        '<%= config.app %>/scripts/templates.js': ['<%= config.app %>/templates/*.hbs']
                    }
                }
            },
            // Watches files for changes and runs tasks based on the changed files
            watch: {
                emberTemplates: {
                    files: '<%= config.app %>/templates/*.hbs',
                    tasks: ['emberTemplates', 'livereload']
                },
                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/{,*/}*.*'
                        ]
                    }]
                },
                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'
        ]);
    };