精华内容
下载资源
问答
  • 前端时间自己过一篇gulp入门的流水账,算是自己gulp了一段时间后的自我总结,但上次文章最后也提到了还有一件要完成的事就是:怎样将生成后的JS及CSS文件带上如browser-sync-client.js?v=2.18.12版本号的形式。...
        

    自己个人博客上线一个月了,先庆祝一下。
    前端时间自己写过一篇gulp入门的流水账,算是自己gulp用了一段时间后的自我总结,但上次文章最后也提到了还有一件要完成的事就是:怎样将生成后的JS及CSS文件带上如browser-sync-client.js?v=2.18.12版本号的形式。这两天也翻阅了大量博客,方法有很多,但还是先明白我们为什么需要这么做。文章很长,很细,望耐心,毕竟是40度高温下烤出来的,我们不熟,我不会让你看。

    为什么需要给文件加版本号

    1.方便版本控制,比如A:app-12345.js或B:app.js?v=12345版本的样式,当文件更新后,我们能明显看到差异,但是A与B还是存在不同,A是在文件名上进行控制,B是在请求头上进行控制,不懂?不要急,后面会慢慢说。
    2.强制浏览器更新请求文件,也许你遇到过,当你的同事告诉你他改的样式文件已经上传到服务器更新了,但是你刷新后就是一股鬼火直冒,更新个屁,还是老样子。其实是浏览器的错,也不正确,还有你们网站建设自己的原因。

    • 先说浏览器,具体看下图图片
      因为http请求时,如果访问的路径不变,而客户端缓存中又有该文件时,浏览器会直接调用缓存中的文件,这样的话,即使服务器的css内容变化了,但是客户端仍然有可能显示的是旧文件。

    • 你自己网站建设原因,没有谁会去把服务器配成每一次请求都调用本地内存,现在前端优化304都嫌慢,更别说重新发起一次完整请求。所以解决办法就是在你的文件上加上你更新后的版本号,当你更新服务器文件后,即使你未删除老的文件,当用户(回头客,首次访问不会有问题)访问你的网站时,就知道要请求的文件本地没有缓存,需要发起一次完整请求。

    • A:app-12345.js和B:app.js?v=12345那种控制方式更好,要第一眼看当然是B方式看着更符合我们的审美啊。但是,确实A确实比B更严谨。因为部分代理缓存服务器不会缓存网址中包含
      "?" 的资源,所以B方法可能会导致你网站的缓存功能失效,每次都需要发起新的完整请求。但我就觉得B方式更符合我的审美,所以就是要用。。。。

    实现方式

    方法A在上一篇文章已经提过,这里直接说方法B,首先明白实现方法B我们需要干那些:

    1. 修改引用文件,让其带版本号,如在index.html中,需要将<link href="css/index.css" rel="stylesheet">改成带版本号的<link href="css/index.css?v=6bcd23aa12" rel="stylesheet">

    2. 将index.css文件名改成index.css?v=6bcd23aa12,真的吗?如果你这时没骂这傻逼,那么你和我曾经一样,还是too young to simple。不用改,你只需要将css/index.css的文件用最新的覆盖就好,文件名真不用改。为什么?因为文件类型后面的问号加版本号都起不到任何作用,它只是告诉浏览器这时一个新的请求。

    那这样的话,不就很简单了吗,只需要gulp rev()生成版本号之后,再将版本号改成带问号的形式存到rev-manifest.json,然后根据此对照替换index.html页面的相关引用。思路是对的,当不局限于此,这里说两种。

    第一种:

    参考文章,但是如果你和我一样,gulp-revCollector版本是1.2以后的,第一、二步可以,第三步,完了,什么鬼,源码不一样啊,当时就懵逼了,怎么办,要想学,还能咋办,看源码呗。gulp-revCollector部分源码:

        var defaults = {
            revSuffix: '-[0-9a-f]{8,10}-?',  //这个正则表达式下面会用到
            extMap: {
                '.scss': '.css',
                '.less': '.css',
                '.jsx': '.js'
            }
        };
        function revCollector(opts) { //函数入口
        opts = _.defaults((opts || {}), defaults);
    
        var manifest  = {};
        var mutables = [];
        return through.obj(function (file, enc, cb) {
            if (!file.isNull()) {
                var mData = _getManifestData.call(this, file, opts); //判断文件不为空后,干的第一件事就是调用 _getManifestData函数,似乎会返回一个值下面详解
                ....//中间略,不重要
         }  
        function _getManifestData(file, opts) {
        var data;
        var ext = path.extname(file.path);
        if (ext === '.json') {  //判断是不是json文件,也就是判断是不是rev-manifest.json文件
            var json = {};
            try {
                var content = file.contents.toString('utf8');
                if (content) {
                    json = JSON.parse(content); //将json字符串转JSON对象
                }
            } catch (x) {
                this.emit('error', new PluginError(PLUGIN_NAME,  x));
                return;
            }
            if (_.isObject(json)) {  //判断是不是对象,肯定是啦,往下走
                var isRev = 1;
                Object.keys(json).forEach(function (key) {
    
                    if (!_.isString(json[key])) {
                        isRev = 0;
                        return;
                    }
                    //下面这句很重要,原生语句的意图就是从index-7ef5d9ee29.css这样的字符串中替换掉前面加入的-revHash这一截字符串,就是得到index.css。
                  //  let cleanReplacement =  path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' );
                  let cleanReplacement =  path.basename(json[key]).split('?')[0];//最暴力的解决办法
                  //下面这条语句很好理解啦,看两个人是不是都有上面替换出的字符串,必须两个都有,前面做的所有工作,就是为了满足他
                    if (!~[
                            path.basename(key),
                            _mapExtnames(path.basename(key), opts)
                        ].indexOf(cleanReplacement)
                    ) {
                        isRev = 0;
                    }
                });
    
                        if (isRev) {
                            data = json;
                        }
                    }
            
                }
                return data;
            }

    所以这次修改的重点就是将 let cleanReplacement = path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' );替换为let cleanReplacement = path.basename(json[key]).split('?')[0];,当然,如果你读懂了,你会发现revCollector这个代码作者给你提供了配置revSuffix这个替换正则表达式的接口,所以你还可以这样就能达到第三步的效果:

    gulp.task("update",['revC'],function (cb) {
        gulp.src(['rev-manifest.json', 'index.html'])  
            .pipe(revCollector({
                revSuffix: '\\?v=[0-9a-f]{8,10}-?'
            }))              
            .pipe(rename("index.html"))
            .pipe(gulp.dest('dist'))
            .on('end', cb);
    });

    其实第一种方法个人不太赞同使用,因为涉及到修改插件包源码,所以无论通用性或移植性还是后期维护,都有不便。

    第二种

    参考文章,这篇其实与上篇相比就是有很大进步,不用修改源码,只用正则表达式和字符替换就干完了所有事,还是值得推荐,唯一不足的就是好像我们又要学更多的gulp插件,好烦。

    第三种(自研)

    其实第一种方法前面两条插件源码修改,只是为了获得一个结果:将index-7ef5d9ee29.css变换为index.css?v=7ef5d9ee29,然后再结合我们第一种方法的改进,就可以达到目的了。为完成第一步,我们可以直接对rev.manifest()中的字符流进行正则匹配替换得到类似index.css?v=7ef5d9ee29的样式,当然这涉及到一定的through2.obj方法调用(这个方法几乎在所有的gulp插件都有用,目的就是将文件转化成流,其他不需要懂,模仿就行),有点自己写gulp插件的意思,整个过程实现如下:

    function replaceSuffix() {
        const pattern =/-[0-9a-f]{8,10}-?\.[^"]*/gmi; //匹配出-7ef5d9ee29.css,用于后面做文章
        return through2.obj(function(file, encoding, done) {
            let content =String(file.contents).replace(pattern,function(match,pos,origin){
            const pat=/[0-9a-f]{8,10}-?/g;  //匹配出7ef5d9ee29,用于后面拼接
            if(pat.test(match)){
                return  RegExp["$'"].concat("?v=", RegExp["$&"]);//如果$'和$&这句话看不懂,红宝书第五章正则表达式部分该复习了;
            }else{
                return match;
            }   
            });  
            file.contents = new Buffer(content);
            this.push(file);
            done();
        });
    }
    gulp.task("cls",function () {
        return gulp.src([
            'dist'
        ]).pipe(clean());
    });
    
    gulp.task('revC',['cls'],function(){  
        return gulp.src('css/*.css')
        .pipe(contact('index.css'))
        .pipe(minifyCss())
        .pipe(gulp.dest('dist'))
        .pipe(rev())
        .pipe(rev.manifest({merge:true}))
        .pipe(replaceSuffix())  //利用上面写的方法替换得到类似index.css?v=7ef5d9ee29的样式          
        .pipe(gulp.dest("dist"));
    });  
    gulp.task("update",['revC'],function (cb) {
        gulp.src(['dist/rev-manifest.json', 'index.html'])  
            .pipe(revCollector({
                revSuffix: '\\?v=[0-9a-f]{8,10}-?'  //利用revCollector的可配置,去满足我们需要的模式;
            }))                  
            .pipe(rename("index.html"))
            .pipe(gulp.dest('dist'))
            .on('end', cb);
    }); 

    相比于第一种和第二种,是不是有一种超脱的感觉,不过记得在写上面那个方法前,需要先引入 through2 这个插件;三种方法就这多么多分析,想选哪一款,自己琢磨。

    坑位提醒

    js,css生成md5文件号到rev-manifest.json同一个相互覆盖

    我们常常是分别压缩所有的js和css然后生成md5码,然后保存在rev-manifest.json文件中,但有时错误的配置rev.manifest({option})中的option,就有可能导致各种错误的发生;作品RD中有配置的详细说明,提醒一句善用merge,慎用base,具体原因等有大量时间截图来证实。有时虽然你option已经配置了{merge:true},但生成的rev-manifest.json还是缺少某一项,特别你是要用这个文件去更新你的HTNL的时候,这时你要怀疑的是你写task的方式,请看个人博客中的文章

    gulp-uglify压缩js报错:

    GulpUglifyError: unable to minify JavaScript,造成这个的原因有很多种,但我遇到的是uglify暂且不支持对es6编写的代码的压缩,就算你只用let或者const声明了变量,不行,反正就是不行。
    解决办法:babel这时就是救世主,不然它的存在就没有意义,就是说使用gulp-babel转化成ES5再压缩,源码:

        gulp.task('ug',()=>{
            return gulp.src('js/component/resizeWindow.js')
            .pipe(babel({  
                    presets: ['es2015']  
                }))
            .pipe(uglify().on('error',function(err){
                    gutil.log(err); /关于gulp-gutil的都可以删除
                    this.emit('end');        
            }))
            .pipe(gulp.dest('dist'));
        })
    
    展开全文
  • JS创建map结构以及map中的方法

    万次阅读 多人点赞 2018-06-22 16:30:00
    js新的数据结构创建map的时候网上有很多,但是有时候你会发现很多方法都不能使用,这里我简单常用的以及怎样去查看map的哪些方法,靠人不如靠己,博客抄来抄去,看起来还浪费时间一般我创建的时候就两种就...

    js新的数据结构创建map的时候网上有很多,但是有时候你会发现很多方法都不能使用,这里我简单写一写常用的以及怎样去查看map的哪些方法,靠人不如靠己,博客抄来抄去,看起来还浪费时间

    一般我创建的时候就用这两种就够了

    创建:


    遍历:


    长度:


    删除:


    新增:



    像我一样的Java程序员就没必要去翻博客翻API去找来找去的真的浪费时间,可以直接创建一个map对象,然后再页面进行debug查看该数据结构的原型链,原型链里就包含他的方法等一系列东西,如图:


    遍历取值等等都在里面,可能有些方法你还是不知道是什么意思,但是这时候你可以有针对性的去查找了,不至于像一开始那样到处乱翻了

    展开全文
  • 庆幸的是,如果在使用函数的这些列中包含了字符型数据,可以这样一种方法修改查询语句,以达到强制性使用索引,更有效地运行查询。这篇文章介绍了涉及的技术,并说明了在两种典型情况下怎样实现。 大小混合情况...
  • 时间的流逝可以下面几种方法模拟:(a)按键盘,每按一次可认为过一个时间单位;(b) 响应WM_TIMER;  将一批进程对磁盘的请求的情况存磁盘文件,以后可以读出并重放;  使用两种方式产生进程对磁盘的请求:(a...
  • ·attribute(改进了.attr()的性能)、jQuery()核心函数、CSS(.css()性能有倍提升)、特效和事件、DOM操作等也有显著改进 1.5 美国时间1月31日John Resig在jQuery官方博客发表文章,宣布jQuery 1.5正式版已经...
  • 你需要什么技术基础 在本书中所用到的计算机语言只有两种:汇编和 C语言。所以只要你具备汇编和 C语言的经验,就可以阅读本书。除对操作系统常识性的了解(比如知道中断、进程等概念)之外,本书不假定读者具备其他...
  • 你需要什么技术基础 在本书中所用到的计算机语言只有两种:汇编和 C语言。所以只要你具备汇编和 C语言的经验,就可以阅读本书。除对操作系统常识性的了解(比如知道中断、进程等概念)之外,本书不假定读者具备其他...
  • 17-18专业课

    2019-10-07 06:56:13
    2017考生回忆的要点 ...二叉排序树的2种优化方法,并且介绍这两种方法怎样优化二叉排序树的。 计算机原理:Amdahl 硬件优化趋势流水线是怎样提高性能的,会遇到什么问题,解决方法是什么。软件优化...

    2017考生回忆的要点

    数据结构:
    向量相对于数组有什么优缺点?
    二叉树计算叶子节点算法,时间复杂度。(可使用任一程序设计语言或伪代码,建议先用自然语言描述算法)
    几乎逆序的数组排序用什么排序算法?写出算法,时间复杂度。
    二叉排序树的2种优化方法,并且介绍这两种方法是怎样优化二叉排序树的。

    计算机原理:
    Amdahl 硬件优化趋势
    流水线是怎样提高性能的,会遇到什么问题,解决方法是什么。
    软件优化至关重要,软件优化一般有哪些方法?
    高速缓存
    性能分析定律
    存储结构是怎样提高性能的,它和局部性的关系是什么。
    虚拟内存的作用,通过什么方式提高虚拟内存的性能。

    软件工程:
    瀑布过程的特点
    开闭原则
    敏捷宣言是什么
    一个场景(学生毕业申请系统),画出UML图、画出流程图0、画出流程图1
    结合传感器说明简述软件测试的作用。
    是不是用例越多越好?为什么说明原因。
    白盒测试和黑盒测试在用例设计上的区别。


    2018考生回忆的要点

    数据结构
    1.栈用单链表和数组哪个更好,说理由。
    2.给了个LNode的类,里面是链表的定义,来实现栈的pop函数功能
    3希尔排序,说明为什么会不稳定?
    4.哈希冲突的2种解决方法,一种在表内,一种在表外
    5.哈夫曼树,哈夫曼编码的算法,压缩率

    计算机系统
    1. amahle优化原理,关于优化程序性能,常用优化方法
    2. memery + disk和memery+cache两种存储系统的设计差异
    3.流水线设计的优点,为什么能提高性能,可能会影响的因素,怎么解决处理这些影响因素
    4.缺失率

    软工
    1.超市系统的用例图
    2.选课系统的数据流程图
    3.图书馆的类图,关于读者,老师,学生,临时读者,图书信息,图书拷贝,借书还书记录。
    4. 面向对象设计选择,依赖倒置原则,接口隔离原则。

    转载于:https://www.cnblogs.com/Ph-one/p/9816264.html

    展开全文
  • +专业课考点参考

    2017-09-18 16:26:00
    二叉排序树的2种优化方法,并且介绍这两种方法怎样优化二叉排序树的。 计算机原理:Amanda 硬件优化趋势流水线是怎样提高性能的,会遇到什么问题,解决方法是什么。软件优化至关重要,软件优化一般有哪些方法?...

    数据结构:
    向量相对于数组有什么优缺点?
    二叉树计算叶子节点算法,时间复杂度。(可使用任一程序设计语言或伪代码,建议先用自然语言描述算法)
    几乎逆序的数组排序用什么排序算法?写出算法,时间复杂度。
    二叉排序树的2种优化方法,并且介绍这两种方法是怎样优化二叉排序树的。

    计算机原理:
    Amanda 硬件优化趋势
    流水线是怎样提高性能的,会遇到什么问题,解决方法是什么。
    软件优化至关重要,软件优化一般有哪些方法?
    高速缓存
    性能分析定律
    存储结构是怎样提高性能的,它和局部性的关系是什么。
    虚拟内存的作用,通过什么方式提高虚拟内存的性能。

    软件工程:
    瀑布过程的特点
    开闭原则
    敏捷宣言是什么
    一个场景(学生毕业申请系统),画出UML图、画出流程图0、画出流程图1
    结合传感器说明简述软件测试的作用。
    是不是用例越多越好?为什么说明原因。
    白盒测试和黑盒测试在用例设计上的区别

     

    向量和数组(10分)
    向量vs数组的优缺点

    二叉树(20分)
    设计一个递归程序计算一个二叉树的叶子节点数目,并给出时间复杂度。
    (可使用任一程序设计语言或伪代码,先用自然语言描述算法)

    排序(15分)
    将一列几乎逆序的数组(XXXXX)用算法排序(XXXXX)
    二叉排序树(10分)

     

    软件测试(10分)
    软件测试的主要目标
    软件测试中测试用例越多越好吗?为什么?
    白盒测试与黑盒测试主要区别是什么?

    软件需求(18分)
    一段背景描述,要求画UML类图、数据流图

    小题(各4分)
    瀑布模型的主要特点、开闭原则。。。

     

    存储系统(20分)
    存储系统层次结构…、高速缓存…、虚拟存储…

    性能优化(20分)
    性能分析定律…、流水线…、优化程序…、程序性能…

     

    展开全文
  • mysql 的输入行编辑器 54 3.2.4 批处理模式连接 55 3.2.5 总结 56 3.3 有关数据库的操作 56 3.3.1 SHOW显示已有的数据库 56 3.3.2 Create Dabase 创建数据库 57 3.3.3 DROP DATABASE删除...
  • mysql 的输入行编辑器 54 3.2.4 批处理模式连接 55 3.2.5 总结 56 3.3 有关数据库的操作 56 3.3.1 SHOW显示已有的数据库 56 3.3.2 Create Dabase 创建数据库 57 3.3.3 DROP DATABASE删除...
  • 7.14 怎样用指向函数的指针作函数的参数? 7.15 数组的大小可以在程序运行时定义吗? 7.16 用malloc()函数更好还是用calloc()函数更好? 7.17 怎样说明一个大于64KB的数组? 7.18 far和near之间有什么区别? ...
  • C语言编程要点

    2017-09-18 00:10:37
    10.4. 移位和乘以2这两种方式中哪一种更好? 151 10.5. 什么是高位字节和低位字节? 151 10.6. 16位和32位的数是怎样存储的? 151 第11章 调 试 152 11.1. 如果我运行的程序挂起了,应该怎么办? 152 11.2. 如何检测内存...
  • 4.6 网络通信的两种基本方法 29 4.7 LINIX中提供的基本I/O功能 29 4.8 将Linux I/O用于TCP/IP 30 4.9 小结 31 深入研究 31 习题 31 第5章 套接字API 32 5.1 引言 32 5.2 Berkeley套接字 32 5.3 指明一个...
  • 记录

    2012-10-20 19:35:00
    看到这个我觉得真的很惭愧,而且看过里面那篇关于面试的文章(怎样时间去面试一个人)也有相见恨晚的感觉。 里面提到了一些关于学习的方法,比如使用github,博客记录这样的方法。github虽然早就听说了,...
  • 凹凸电子面试题目

    2011-11-15 21:26:36
    1,请最少空间和最省时间两种方法对数组Data[N]排序。 void sort1(int Data[N],int num) void sort2(int Data[N],int num) 2,怎样使一个Windows中的Button变成灰色,不能选中? 3,在Windows中如何打开串口...
  • 一个上述银行业务的事件驱动模拟系统,通过模拟方法求出客户在银行内逗留的平均时间。 【基本要求】 利用动态存储结构实现模拟。 【测试数据】 一天营业开始时银行拥有的款额为10000(元),营业时间为600(分钟)...
  • 你必须知道的495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    怎样用引用方式传入一个常数?调用f(&5);似乎不行。 4.11 C语言可以“按引用传参”吗? 其他指针问题 4.12 我看到了用指针调用函数的不同语法形式。到底怎么回事? 4.13 通用指针类型是什么?当我把函数...
  • 一个上述银行业务的事件驱动模拟系统,通过模拟方法求出客户在银行内逗留的平均时间。 【基本要求】 利用动态存储结构实现模拟。 【测试数据】 一天营业开始时银行拥有的款额为10000(元),营业时间为600(分钟...
  • 注意测定两种极端的情况:一是两个到达事件之间的间隔时间很短,而客户的交易时 间很长,另一个恰好相反,设置两个到达事件的间隔时间很长,而客户的交易时间很短。 [实现提示] 事件有两类;到达银行和离开银行。韧...
  • 注意测定两种极端的情况:一是两个到达事件之间的间隔时间很短,而客户的交易时 间很长,另一个恰好相反,设置两个到达事件的间隔时间很长,而客户的交易时间很短。 [实现提示] 事件有两类;到达银行和离开银行。韧...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 247
精华内容 98
关键字:

怎样用两种方法写时间