Grunt实现前端自动化

定义:我的认为,前端自动化就是便捷地将开发代码迅速转化为发布代码的过程。javascript

 

意义:通常来讲,开发代码不会直接部署上线运行,小型项目倒问题不大,但对于大型项目来讲,要考虑到服务器的压力以及保密的等缘由,须要将代码的体积最小化,减小请求数量,对代码进行混淆和压缩,若是手动完成这个过程,会比较繁琐。css

 

主要用到的技术:Grunt(首先要安装Node.js环境,安装好Node.js环境至关于安装好了npm,在项目建设过程当中就是用npm下载各个JS库的)html

 

范例步骤:前端

1、先看看整个项目文件结构(假定咱们已经实现了src以及image文件夹下的全部内容java

这个项目实现的功能是随机显示一个颜色做为网页背景,并随机显示一个0~100的数字。node

传统的网页项目只会有名为src和image文件夹下的内容(忽略名为concat的两个文件夹以及文件夹下的内容,这两个文件夹只是在生成过程当中的一个副产品^_^),真正部署时用到的是名为dist以及image的文件夹。jquery

个人HTML文件是这样的,引用了两个js文件和一个css文件:npm

<!DOCTYPE html>
<html>
<head>
    <title>Grunt--前端自动化</title>
    <!-- build:css css/App.min.css -->
    <link rel="stylesheet" type="text/css" href="css/index.css">
    <!-- endbuild -->
</head>
<body>
    <a>Grunt--前端自动化</a>
    <!-- build:js js/App.min.js -->
    <script type="text/javascript" src="node_modules/jquery/dist/jquery.min.js"></script>
    <script type="text/javascript" src="js/index.js"></script>
    <!-- endbuild -->
</body>
</html>

 

 

2、定义项目相关信息(package.json)json

{
  "name": "App",
  "version": "1.0.0",
  "description": "Grunt Page",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Mandy","devDependencies": {
    "grunt": "^1.0.1",
    "grunt-contrib-clean": "^1.1.0",
    "grunt-contrib-concat": "^1.0.1",
    "grunt-contrib-copy": "^1.0.0",
    "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-usemin": "^3.1.1",
    "jquery": "^3.2.1"
  },
  "dependencies": {
    "grunt": "^1.0.1",
    "grunt-contrib-clean": "^1.1.0",
    "grunt-contrib-concat": "^1.0.1",
    "grunt-contrib-copy": "^1.0.0",
    "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-usemin": "^3.1.1",
"jquery": "^3.2.1"
 } }

package.json文件会描述这个npm包的全部相关信息,包括做者、简介、包依赖、构建等信息,格式是严格的JSON格式。segmentfault

所展现的这个文件依次定义了npm包名、版本号、描述、入口文件、脚本说明对象、做者、只在开发时须要的依赖包、当前包所需的依赖包,固然这个文件还可有别的参数,具体能够参考这里或者这里

ps:之因此到处与npm相关,是由于基于grunt其实等于基于npm,而npm自己就是为了开发者开发各类JS库所诞生的“包管理工具”。

若是一开始项目没有这个文件,能够经过控制台执行npm init,而后根据提示一步一步生成这个文件。

其中dependencies下的条目其实都不是手打的,实际上是能够自动生成的,具体看下一步。

 

3、安装依赖包(我所理解的JS库,或许理解有误,正确称呼应为依赖包)

安装Grunt:控制台执行npm install grunt --save-dev

后面这个--save-dev参数就是生成前面dependencies下内容的关键,若是是--save-dev,就会保存到devDependencies,若是是--save,就会保存到dependencies。

依此类推,安装clean(清空文件夹)、concat(合并文件)、csslint(CSS语法检查)、jshint(JS语法检查)、cssmin(压缩CSS)、uglify(混淆压缩JS)、copy(复制文件)、useminPrepare(usemin的准备)、usemin(使用压缩后的文件)、watch(检测文件变化)。

npm install grunt-contrib-concat --save-dev
npm install grunt-contrib-csslint --save-dev
npm install grunt-contrib-cssmin --save-dev
npm install grunt-contrib-jshint --save-dev
npm install grunt-contrib-uglify --save-dev
npm install grunt-contrib-watch --save-dev
npm install grunt-usemin --save-dev
npm install grunt-contrib-copy --save-dev
npm install grunt-contrib-clean --save-dev

 安装完以后node_modules文件夹下就会出现截图中所出现的依赖包了。

 

4、建立Gruntfile.js文件

module.exports = function(grunt){
    //初始化grunt 配置
    grunt.initConfig({
 
        //获取package.json的信息,也就是后面pkg变量的来源
        pkg: grunt.file.readJSON('package.json'),

        // 各插件的配置信息
        clean:{
            src:"dist/"
        },

        concat: {
            options:{
                stripBanners:true, // 合并时容许输出头部信息
                banner:'/*!<%= pkg.name %> - <%= pkg.version %>-'+'<%=grunt.template.today("yyyy-mm-dd") %> */'
            },
            cssConcat:{
                src:['src/css/*.css'],
                dest:'src/css/concat/<%= pkg.name %> - <%= pkg.version %>.css' // dest 是目的地输出
            },
            jsConcat:{
                src:[
                    'node_modules/jquery/dist/jquery.min.js',
                    'src/js/index.js'
                ],
                dest:'src/js/concat/<%=pkg.name %> - <%= pkg.version %>.js'
            }
        },
 
        csslint:{
            options:{
                csslintrc:'.csslint'
            },
            build:['src/css/*.css']
 
        },

        jshint:{
            options:{
                jshintrc:'.jshint'
            },
            build:['Gruntfile.js','src/js/*.js']
        },

        cssmin:{
            options:{
                stripBanners:true, // 合并时容许输出头部信息
                banner:'/*!<%= pkg.name %> - <%= pkg.version %>-'+'<%=grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            build:{
                src:'src/css/concat/<%=pkg.name %> - <%=pkg.version %>.css',// 压缩是要压缩合并了的
                dest:'dist/css/<%= pkg.name %>.min.css' // dest 是目的地输出
            }
        },
        uglify:{
            options:{
                stripBanners:true, // 合并时容许输出头部信息
                banner:'/*!<%= pkg.name %> - <%= pkg.version %>-'+'<%=grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            build:{
                src:'src/js/concat/<%=pkg.name %> - <%=pkg.version %>.js',// 压缩是要压缩合并了的
                dest:'dist/js/<%= pkg.name %>.min.js' // dest 是目的地输出
            }
        },
        copy:{
            html:{
                src:'src/index.html',
                dest:'dist/index.html'
            }
        },
        useminPrepare:{
            html:'index.html',
            options:{
                dest:'dist'
            }
        },
        usemin:{
            html:['dist/index.html'],
            js:['dist/js/20170711 - 1.0.0.min.js'],
            css:['dist/css/20170711 - 1.0.0.min.css']
        },

        //watch自动化
        watch:{
            build:{
                files:['src/js/*.js','src/css/*.css'],
                tasks:['concat','cssmin','uglify'],
                options:{spawn:false}
            }
        }
 
    });
    // 告诉grunt咱们将使用插件
    grunt.loadNpmTasks('grunt-contrib-clean');
    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-contrib-copy');
    grunt.loadNpmTasks('grunt-usemin');
    // 告诉grunt当咱们在终端输入grunt时须要作些什么
    // 先进行语法检查,若是没有问题,再合并,再压缩
    grunt.registerTask('default',
        [
        'clean',
        'concat',
        // 'csslint',
        // 'jshint',
        'cssmin',
        'uglify',
        'copy',
        'useminPrepare',
        'usemin',
        'watch'
        ]
    );
};

这个文件的存在是为了定义当咱们在控制台执行grunt的时候所要执行的操做。

initConfig是针对各个功能模块的具体配置

loadNpmTasks是加载完成任务所需的模块

registerTask是定义一个任务的执行过程(固然它不只仅只能这样作,还能够有更多功能和更多写法,暂且这样认为吧)

 

5、执行

在控制台中执行grunt命令,执行到如下效果时,说明代码已经生成完毕了。

此时咱们能够看到dist文件夹出如今了项目中,接下来咱们就只须要将dist文件夹和image文件夹拷贝到服务器上就能够运行了。

生成后的项目只依赖于一个css文件和一个js文件(image文件夹其实我并无用到),而打开这两个文件,咱们会发现css和js代码都已经被压缩成了一行。

HTML文件也变成了这样:

<!DOCTYPE html>
<html>
<head>
    <title>Grunt--前端自动化</title>
    <link rel="stylesheet" href="css/App.min.css">
</head>
<body>
    <a>Grunt--前端自动化</a>
    <script src="js/App.min.js"></script>
</body>
</html>

本来依赖的两个js也自动合并成了一个js —— 这里要隆重地说一说这个卡住我很久的问题!!!

一开始个人HTML并无变化,说明usemin并无起到效果?因而我为了解决这个问题找了不少资料,期间查找无果搁置了一段时间。

这几天才知道,原来是HTML文件中相应的JS或者CSS引用应该用<!-- build:js js/App.min.js --><!-- endbuild -->和<!-- build:css css/App.min.css --><!-- endbuild -->这样的一个注释括起来,以后usemin才能够正常运做。

其实官方文档已经提到过这个,可是因为是用英文Blocks来描述的,半天反应不过来是指这样的东西。。

没留意里面贴出的代码段,也没想到竟然一个注释都能有这样的功能。。

相关文章
相关标签/搜索