定义:我的认为,前端自动化就是便捷地将开发代码迅速转化为发布代码的过程。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来描述的,半天反应不过来是指这样的东西。。
没留意里面贴出的代码段,也没想到竟然一个注释都能有这样的功能。。