【grunt第三弹】grunt在前端实际项目中的应用
前言
经过前两次的学习,我们了解了grunt打包的一些基础知识,对于压缩几个文件有了初步认识
但是实际项目中的应用往往不是那么简单的,因为我们会有分支,我们也会有app版本Html5版本,更复杂的情况是我们有各个频道,而且各个频道是不同的团队在开发
那么统一的一套打包工具如何满足不同团队的需求呢?
然后,我们本地联调时候,仍然需要打包,但是打包的代码有些时候却不想要minify,这些功能都是实际项目重要用到的
我们这个时间化大力气学习grunt打包一块的知识是有绝对意义的,不然前端代码合并一块的难题仍然不可破,所以有心思在前端的朋友还是应该掌握一套前端自动化工具
我们继续几天的学习吧!!!
移动打包文件
其实,grunt本身具有这样的功能,但是我们实际项目重会出现这种可能:
我们核心框架会有一套压缩代码,并且会在对应目录生成文件用于发布,但是这个地方的权限对各个频道团队是不可见的
所以,我们在各个频道的公共文件夹内应该将刚刚的文件给复制过去,这块代码其实很简单,不需要任何新知识都能实现:
我们这里依旧采用昨天的require相关的代码,但是一有个不同的地方就是,我们要同时在D盘的common文件夹中生成该文件
这个代码其实比较简单,这里我们先介绍一个新的插件copy
grunt-contrib-copy
该插件用于复制文件到你想要的文件夹处
grunt.initConfig({ copy: {
main: {
flatten: true,
src: 'src/*.js',
dest: 'dest/'
}
}
});
这段代码就会将src中的js文件搞到dest里面,并且新建src文件夹:
$ grunt copy
Running "copy:main" (copy) task
Copied 7 files
若是不想复制文件夹只要文件应该这样干:
grunt.initConfig({ copy: {
main: {
flatten: true,
// filter: 'isFile',
expand: true,
src: 'src/**.js',
dest: 'dest/'
}
}
});
这块完了,我们就来移动打包文件至D盘了
移动打包文件
这个时候代码这样写就好(也许移动前我们还想将其文件夹里面的东西销毁,暂时不考虑了)
module.exports = function (grunt) { grunt.initConfig({ copy: {
main: {
// flatten: true,
// expand: true,
src: 'dest/**.js',
dest: 'd:/common/'
}
}
}); grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-requirejs'); grunt.registerTask('build', 'require demo', function () { //第一步,读取配置信息
var cfg = grunt.file.readJSON('cfg.json');
cfg = cfg.requirejs;
grunt.config.set('requirejs', { test: cfg }); //第二步,设置参数
grunt.log.debug('参数:' + JSON.stringify(grunt.config())); //第三步跑任务
grunt.task.run(['requirejs']); }); grunt.registerTask('default', 'test demo', ['build', 'copy']); }
Running "build" task Running "requirejs:test" (requirejs) task
>> Tracing dependencies for: d:/grunt/dest/libs.js
>> Uglifying file: d:/grunt/dest/libs.js
>> d:/grunt/dest/libs.js
>> ----------------
>> d:/grunt/src/zepto.js
>> d:/grunt/src/underscore.js
>> d:/grunt/src/backbone.js
>> d:/grunt/src/test01.js
>> d:/grunt/src/require.text.js
>> text!src/demo01.html Running "copy:main" (copy) task
Copied 8 files
关于移动相关的知识点暂时介绍到这里,我们进入下一话题
分支/频道处理
我们在实际项目重会遇到这种情况,我们一个主干分支上可能拉出很多分支完成不同的功能,而各个分支就有那么一点点不同,那么这个时候打包工具该怎么办呢?
我们一般是这样处理的:
① 首先全局只会有一个打包工具
② 其次每一个分支都会有一个gruntCfg.json的配置文件,存储相关的打包信息
③ 每次打包时候便把响应的分支打印到各自的dest目录里面
为了模拟这一情况我们将grunt打包相关的文件放到D盘的grunt目录里面,并在D盘新建gruntDemo目录
然后我们在gruntDemo中建立一个项目,并且为这个项目拉一个分支,比如现在项目是地demo01与demo02
现在文件结构如下:
D:\GRUNTDEMO
├─demo01
│ │ gruntCfg.json
│ │
│ └─src
│ backbone.js
│ require.js
│ require.text.js
│ test01.js
│ test02.js
│ underscore.js
│ zepto.js
│
└─demo02
│ gruntCfg.json
│
└─src
backbone.js
require.js
require.text.js
test01.js
test02.js
underscore.js
zepto.js
这个时候,要实现功能最好的方法就是写自定义任务了,其它方案不好使,这个时候起配置文件也需要有一定修改,比如其中的路径需要加入参数信息
{
"requirejs": {
"options": {
"baseUrl": "<%= config.srcDir %>",
"paths": {
"$": "src/zepto",
"_": "src/underscore",
"B": "src/backbone",
"test": "src/test01",
"text": "src/require.text" },
"include": [
"$",
"_",
"B",
"test",
"text!src/demo01.html"
],
"out": "<%= config.destDir %>/libs.js"
}
}
}
这个时候initConfig相关信息时候,首先得传入path依赖的文件目录,以及输出的文件目录
module.exports = function (grunt) { grunt.loadNpmTasks('grunt-contrib-requirejs'); //channel为频道名称,project为项目名称,这里对应gruntDemo,branch为其分支,默认与grunt目录为平行关系,佛则package.json里面应该有配置信息
grunt.registerTask('build', 'require demo', function (channel, project, branch) { var path = '../' + channel + '/' + project + branch;
grunt.log.debug('path: ' + path); //第一步,读取配置信息
var cfg = grunt.file.readJSON(path + '/gruntCfg.json');
cfg = cfg.requirejs; grunt.config.set('config', {
srcDir: path,
destDir: path + '/dest'
}); grunt.config.set('requirejs', { main: cfg }); //第二步,设置参数
grunt.log.debug('param: ' + JSON.stringify(grunt.config())); //第三步跑任务
grunt.task.run(['requirejs']); }); grunt.registerTask('default', 'test demo', ['build', 'copy']); }
于是我们第一步工作成功了:
$ grunt build:gruntDemo:demo:02 --debug
Running "build:gruntDemo:demo:02" (build) task
[D] Task source: d:\grunt\Gruntfile.js
[D] path: ../gruntDemo/demo02
[D] param: {"config":{"srcDir":"../gruntDemo/demo02","destDir":"../gruntDemo/dem
o02/dest"},"requirejs":{"main":{"options":{"baseUrl":"../gruntDemo/demo02","path
s":{"$":"src/zepto","_":"src/underscore","B":"src/backbone","test":"src/test01",
"text":"src/require.text"},"include":["$","_","B","test","text!src/demo01.html"]
,"out":"../gruntDemo/demo02/dest/libs.js"}}}} Running "requirejs:main" (requirejs) task
[D] Task source: d:\grunt\node_modules\grunt-contrib-requirejs\tasks\requirejs.j
s
>> Tracing dependencies for: d:/gruntDemo/demo02/dest/libs.js
>> Uglifying file: d:/gruntDemo/demo02/dest/libs.js
>> d:/gruntDemo/demo02/dest/libs.js
>> ----------------
>> d:/gruntDemo/demo02/src/zepto.js
>> d:/gruntDemo/demo02/src/underscore.js
>> d:/gruntDemo/demo02/src/backbone.js
>> d:/gruntDemo/demo02/src/test01.js
>> d:/gruntDemo/demo02/src/require.text.js
>> text!src/demo01.html
如果改变一下任务命令呢:
grunt build:gruntDemo:demo:01 --debug
结果证明也是没有问题的,这个地方我就不贴出来了,各位自己去试试,我们分支处理一块暂时到这里
频道处理其实我们这里已经做了,第一个参数是频道,第二个参数是项目,第三个参数为分支,所以频道相关我们暂时就不说了
native与HTML5打包
最后让我们来看看如何打包native文件,native文件的打包其实与打包HTML5的方式类似,只不过我们这里需要一点点配置,让一个项目可以打包成不同的效果
仍然以上面demo01为例,他的配置文件可能就需要做一定调整:
{
"requirejs": {
"options": {
"baseUrl": "<%= config.srcDir %>",
"paths": {
"$": "src/zepto",
"_": "src/underscore",
"B": "src/backbone",
"test": "src/test01",
"text": "src/require.text"
},
"web": {
"include": [
"$",
"_",
"B",
"test"
],
"out": "<%= config.destDir %>/libs.js"
},
"app": {
"include": [
"$",
"_",
"B",
"test",
"text!src/demo01.html"
],
"out": "<%= config.destDir %>/libs_app.js"
}
}
}
}
这里为了表现一点web与native的不同,我特意将web中少包含一个text文件,具体还得各位项目中去实践
如此一来,我们的代码需要做些许调整:
module.exports = function (grunt) { grunt.loadNpmTasks('grunt-contrib-requirejs'); //type 打包app包还是web包,channel为频道名称,project为项目名称,这里对应gruntDemo,branch为其分支,默认与grunt目录为平行关系,佛则package.json里面应该有配置信息
grunt.registerTask('build', 'require demo', function (type, channel, project, branch) { var path = '../' + channel + '/' + project + branch;
grunt.log.debug('path: ' + path); //第一步,读取配置信息
var cfg = grunt.file.readJSON(path + '/gruntCfg.json');
cfg = cfg.requirejs.options; grunt.config.set('config', {
srcDir: path,
destDir: path + '/dest'
}); grunt.log.debug('param: ' + JSON.stringify(cfg));
grunt.log.debug('param: ' + cfg[type]['include']); var taskCfg = {};
taskCfg.options = {};
taskCfg.options.baseUrl = cfg.baseUrl;
taskCfg.options.paths = cfg.paths;
taskCfg.options['include'] = cfg[type]['include'];
taskCfg.options.out = cfg[type].out; grunt.config.set('requirejs', { main: taskCfg }); //第二步,设置参数
grunt.log.debug('param: ' + JSON.stringify(grunt.config())); //第三步跑任务
grunt.task.run(['requirejs']); }); grunt.registerTask('default', 'test demo', ['build', 'copy']); }
于是便可以运行了!!!
$ grunt build:app:gruntDemo:demo:01 --debug
Running "build:app:gruntDemo:demo:01" (build) task
[D] Task source: d:\grunt\Gruntfile.js
[D] path: ../gruntDemo/demo01
[D] param: {"baseUrl":"<%= config.srcDir %>","paths":{"$":"src/zepto","_":"src/u
nderscore","B":"src/backbone","test":"src/test01","text":"src/require.text"},"we
b":{"include":["$","_","B","test"],"out":"<%= config.destDir %>/libs.js"},"app":
{"include":["$","_","B","test","text!src/demo01.html"],"out":"<%= config.destDir
%>/libs_app.js"}}
[D] param: $,_,B,test,text!src/demo01.html
[D] param: {"config":{"srcDir":"../gruntDemo/demo01","destDir":"../gruntDemo/dem
o01/dest"},"requirejs":{"main":{"options":{"baseUrl":"../gruntDemo/demo01","path
s":{"$":"src/zepto","_":"src/underscore","B":"src/backbone","test":"src/test01",
"text":"src/require.text"},"include":["$","_","B","test","text!src/demo01.html"]
,"out":"../gruntDemo/demo01/dest/libs_app.js"}}}} Running "requirejs:main" (requirejs) task
[D] Task source: d:\grunt\node_modules\grunt-contrib-requirejs\tasks\requirejs.j
s
>> Tracing dependencies for: d:/gruntDemo/demo01/dest/libs_app.js
>> Uglifying file: d:/gruntDemo/demo01/dest/libs_app.js
>> d:/gruntDemo/demo01/dest/libs_app.js
>> ----------------
>> d:/gruntDemo/demo01/src/zepto.js
>> d:/gruntDemo/demo01/src/underscore.js
>> d:/gruntDemo/demo01/src/backbone.js
>> d:/gruntDemo/demo01/src/test01.js
>> d:/gruntDemo/demo01/src/require.text.js
>> text!src/demo01.html
结语
我们这个星期花了三天时间一起学习了grunt打包相关的知识点,需要这些知识对您有用,搞这个东西还花费了不少心血呢!!!
若是文中有误请一并提出,后续若是这块有所得我们再一起总结吧
【grunt第三弹】grunt在前端实际项目中的应用的更多相关文章
- 「实践篇」解决微前端 single-spa 项目中 Vue 和 React 路由跳转问题
前言 本文介绍的是在做微前端 single-spa 项目过程中,遇到的 Vue 子应用和 React 子应用互相跳转路由时遇到的问题. 项目情况:single-spa 项目,基座用的是 React,目 ...
- 前端学习 第三弹: JavaScript语言的特性与发展
前端学习 第三弹: JavaScript语言的特性与发展 javascript的缺点 1.没有命名空间,没有多文件的规范,同名函数相互覆盖 导致js的模块化很差 2.标准库很小 3.null和unde ...
- Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用
Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用 Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.cs ...
- 『PyTorch』第三弹重置_Variable对象
『PyTorch』第三弹_自动求导 torch.autograd.Variable是Autograd的核心类,它封装了Tensor,并整合了反向传播的相关实现 Varibale包含三个属性: data ...
- ASP.NET5之客户端开发:Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用
Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.css预处理器的构建工具,它帮助开发者处理客户端开发中的一些烦操重复性的工作.Grun ...
- codechef营养题 第三弹
第三弾が始まる! codechef problems 第三弹 一.Motorbike Racing 题面 It's time for the annual exciting Motorbike Rac ...
- 好玩的WPF第三弹:颤抖吧,地球!消失吧,地球!
原文:好玩的WPF第三弹:颤抖吧,地球!消失吧,地球! 版权声明:转载请联系本人,感谢配合!本站地址:http://blog.csdn.net/nomasp https://blog.csdn.net ...
- 【深度森林第三弹】周志华等提出梯度提升决策树再胜DNN
[深度森林第三弹]周志华等提出梯度提升决策树再胜DNN 技术小能手 2018-06-04 14:39:46 浏览848 分布式 性能 神经网络 还记得周志华教授等人的“深度森林”论文吗?今天, ...
- Java并发必知必会第三弹:用积木讲解ABA原理
Java并发必知必会第三弹:用积木讲解ABA原理 可落地的 Spring Cloud项目:PassJava 本篇主要内容如下 一.背景 上一节我们讲了程序员深夜惨遭老婆鄙视,原因竟是CAS原理太简单? ...
随机推荐
- jquery颜色选择器
本站下载 第二种:纯JAVASCRIPT: <html> <head> <meta http-equiv="Content-Type" content ...
- C#设计模式系列:单一职责原则(Single Responsibility Principle)
1.单一职责原则的核心思想 一个类应该有且只有一个变化的原因. 2.为什么要引入单一职责原则 单一职责原则将不同的职责分离到单独的类,每一个职责都是一个变化的中心.当需求变化时,这个变化将通过更改职责 ...
- jQuery 2.0.3 源码分析 样式操作
根据API分类 CSS addClass() jQuery.cssHooks .hasClass() .removeClass() .toggleClass() .addClass() 对元素的样式操 ...
- Android 生成LayoutInflater的三种方式
通俗的说,inflate就相当于将一个xml中定义的布局找出来. 因为在一个Activity里如果直接用findViewById()的话,对应的是setConentView()的那个layout里的组 ...
- 前端学PHP之面向对象系列第一篇——类和对象
× 目录 [1]类 [2]成员属性[3]成员方法[4]对象[5]成员访问[6]this 前面的话 面向对象程序设计(OOP)是一种计算机编程架构.计算机程序由单个能够起到子程序作用的单元或对象组成,为 ...
- 深入理解脚本化CSS系列第三篇——脚本化CSS类
前面的话 在实际工作中,我们使用javascript操作CSS样式时,如果要改变大量样式,会使用脚本化CSS类的技术,本文将详细介绍脚本化CSS类 style 我们在改变元素的少部分样式时,一般会直接 ...
- codeforces Round #320 (Div. 2) C. A Problem about Polyline(数学) D. "Or" Game(暴力,数学)
解题思路:就是求数 n 对应的二进制数中有多少个 1 #include <iostream> #include<cstdio> using namespace std; int ...
- 一起学微软Power BI系列-官方文档-入门指南(4)Power BI的可视化
在前面的系列文章中,我们介绍了官方有关获取数据,以及建模的原始文档和基本介绍.今天继续给大家介绍官方文档中,有关可视化的内容.实际上获获取数据和建模更注重业务关系的处理,而可视化则关注对数据的解读.这 ...
- 细说gulp
一.概述&安装 Gulp,简而言之,就是前端自动化开发工具,利用它,我们可以提高开发效率. 比如: 1. 压缩js 2. 压缩css 3. 压缩less 4. 压缩图片 等等… 我们完 ...
- Hibernate学习之——搭建log4j日志环境
昨天讲了Hibernate开发环境的搭建以及实现一个Hibernate的基础示例,但是你会发现运行输出只有sql语句,很多输出信息都看不见.这是因为用到的是slf4j-nop-1.6.1.jar的实现 ...