zoukankan      html  css  js  c++  java
  • NodeJs前端构建工具 ——————之Grunt篇

    为何使用grunt?

    一句话:自动化。对于需要反复重复的任务,例如压缩(minification)、编译、单元测试、linting等,自动化工具可以减轻你的劳动,简化你的工作。

    Grunt生态系统非常庞大,并且一直在增长。由于拥有数量庞大的插件可供选择,因此,你可以利用Grunt自动完成任何事,并且花费最少的代价。

    常用插件

    1. grunt-contrib-uglifyby
      Js压缩插件
    2. grunt-contrib-cssminby
      Css压缩插件
    3. grunt-contrib-jshintby
      Js代码检测插件:检测标注javascript代码中的出错和规范问题
    4. grunt-contrib-watch
      监控文件插件:每当文件发生修改,自动运行grunt任务,如自动检测代码
    5. grunt-jsdoc
      文档生成插件:根据项目自动生成js文档
    6. grunt-browserify
      javascript模块管理,browserify使用node comnonjs规范,让前端也能使用15万个node插件
    7. grunt-karma
      单元测试框架
    8. jasmine-core
      单元测试内核
    9. phantomjs
      单元测试模拟环境

    如何搭建grunt?

    安装准备:

    1.下载安装NodeJs

    2.将NodeJs资源提取路径 从NPM移到CNPM,CNPM下载点在国内,速度更快。

    npm install -g cnpm --registry=https://registry.npm.taobao.org

    3.在任意位置新建文件夹demo

    开始安装Grunt:

    cnpm install -g grunt-cli

    先将Grunt命令行(CLI)安装到全局环境中。安装时可能需要使用sudo(针对OSX、*nix、BSD等系统中)权限或者作为管理员(对于Windows环境)来执行以下命令。

    注意:安装grunt-cli并不等于安装了 Grunt!Grunt CLI的任务很简单:调用与Gruntfile在同一目录中 Grunt。这样带来的好处是,允许你在同一个系统上同时安装多个版本的 Grunt。

    添加 Grunt 项目配置文件夹

    在demo文件夹中添加两份文件:package.json 和 Gruntfile。

    package.json: 此文件被npm用于存储项目的元数据,以便将此项目发布为npm模块。你可以在此文件中列出项目依赖的grunt和Grunt插件,放置于devDependencies配置段内。

    {
         "name": "my-project-name",
         "version": "0.1.0",
         "devDependencies": {
         }
     }

    Gruntfile.js: 此文件被命名为 Gruntfile.js 或 Gruntfile.coffee,用来配置或定义任务(task)并加载Grunt插件的。

    安装Grunt

    cnpm install grunt --save-dev

    进入下一章节

    开始第一个grunt项目 基础(一)合并js文件

    安装grunt插件:grunt-contrib-concat

    cnpm install grunt-contrib-concat --save-dev

    创建代码开发(src)和构建(build)文档

    —demo
      |-build
      |-src
      |-Gruntfile.js
      |-package.js

    配置grunt配置文件Gruntfile.js

    module.exports = function(grunt) {
        // Grunt 配置.
        grunt.initConfig({
            concat: {
                options: {
                //定义一个字符串插入每个文件之间用于连接输出
                    separator: ';'
                },
                dist: {
                    src: ['src/*.js'],
                    dest: 'build/main.total.js',
                }
            }
        });
        // 加载包含 "uglify" 任务的插件。grunt.loadNpmTasks('grunt-contrib-concat');
        // 默认被执行的任务列表。
        grunt.registerTask('default', ['concat']);
    };

    运行grunt,构建代码

    grunt

    进入下一章节

    开始第一个grunt项目 基础()压缩js

    安装grunt插件:grunt-contrib-uglify

    cnpm install grunt-contrib-uglify --save-dev

    配置grunt配置文件Gruntfile.js

    module.exports = function(grunt) {
        //Grunt 配置.
        grunt.initConfig({
            pkg: grunt.file.readJSON('package.json'),
            //合并js
            concat: {
                options: {
                    //定义一个字符串插入每个文件之间用于连接输出
                    separator: ';'
                },
                dist: {
                    src: ['src/*.js'],
                    dest: 'build/main.total.js',
                }
            },
            //压缩js
            uglify: {
                options: {
                    banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */
    '
                },
                build: {
                    src: 'build/<%= pkg.name %>.js',
                    dest: 'build/<%= pkg.name %>.min.js'
                }
            },
        });
        // 加载包含 "concat" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-concat');
        // 加载包含 "uglify" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-uglify');
        // 默认被执行的任务列表。
        grunt.registerTask('default', ['concat','uglify']);
    };

    运行grunt,构建代码

    grunt

    进入下一章节

    开始第一个grunt项目 基础()代码规范检测

    安装grunt插件:grunt-contrib-jshint

    cnpm install grunt-contrib-jshint --save-dev

    配置grunt配置文件Gruntfile.js

    module.exports = function(grunt) {
        // Project configuration.
        grunt.initConfig({pkg: grunt.file.readJSON('package.json'),
            //合并js
            concat: {
                options: {
                    //定义一个字符串插入每个文件之间用于连接输出
                    separator: ';'
                },
                dist: {
                    src: ['src/*.js'],
                    dest: 'build/main.total.js',
                }
            },
            //压缩js
            uglify: {
                options: {
                    banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */
    '
                },
                build: {
                    src: 'build/<%= pkg.name %>.js',
                    dest: 'build/<%= pkg.name %>.min.js'
                }
            },
            //代码检测
            jshint: {
                files: ['src/*.js'],
                options: {
                    "strict": true,
                    "globalstrict"  : true,
                    "node":true,
                    "browser":true,
                    globals: {
                        exports: true
                    }
                }
            }
        });
        // 加载 "concat" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-concat');
        // 加载 "uglify" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-uglify');
        // 加载包含 "jshint" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-jshint');
        // 默认被执行的任务列表。
        grunt.registerTask('default', ['concat','uglify','jshint']);
    };

    运行grunt,构建代码

    grunt

    开始第一个grunt项目 基础()开启自动检测

    安装grunt插件:grunt-contrib-watch

    cnpm install grunt-contrib-watch --save-dev

    配置grunt配置文件Gruntfile.js

    module.exports = function(grunt) {
        // Project configuration.
        grunt.initConfig({pkg: grunt.file.readJSON('package.json'),
            //合并js
            concat: {
                options: {
                    //定义一个字符串插入每个文件之间用于连接输出
                    separator: ';'
                },
                dist: {
                    src: ['src/*.js'],
                    dest: 'build/main.total.js',
                }
            },
            //压缩js
            uglify: {
                options: {
                    banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */
    '
                },
                build: {
                    src: 'build/<%= pkg.name %>.js',
                    dest: 'build/<%= pkg.name %>.min.js'
                }
            },
            //代码检测
            jshint: {
                files: ['src/*.js'],
                options: {
                    "strict": true,
                    "globalstrict"  : true,
                    "node":true,
                    "browser":true,
                    globals: {
                        exports: true
                    }
                }
            },
            watch: {
                scripts: {
                    files: ['<%= jshint.files %>'],
                    tasks: ['jshint'],
                    options: {
                        spawn: false,
                    },
                },
            },
        });
        // 加载包含 "concat" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-concat');
        // 加载包含 "uglify" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-uglify');
        // 加载包含 "jshint" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-jshint');
        // 加载包含 "watch" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-watch');//grunt watch
        // 默认被执行的任务列表。
        grunt.registerTask('default', ['concat','uglify','jshint']);
    };

    开启自动检测

    grunt watch

    这时候修改src文件夹中内容,则会自动检测代码

    开始第一个grunt项目 提高()Js模块化之browserify

    安装grunt插件:grunt-browserify

    cnpm install grunt-browserify --save-dev

    配置grunt配置文件Gruntfile.js

    module.exports = function(grunt) {
        // Project configuration.
        grunt.initConfig({pkg: grunt.file.readJSON('package.json'),
            //合并js
            concat: {
                options: {
                    //定义一个字符串插入每个文件之间用于连接输出
                    separator: ';'
                },
                dist: {
                    src: ['src/*.js'],
                    dest: 'build/main.total.js',
                }
            },
            //压缩js
            uglify: {
                options: {
                    banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */
    '
                },
                build: {
                    src: 'build/<%= pkg.name %>.js',
                    dest: 'build/<%= pkg.name %>.min.js'
                }
            },
            //代码检测
            jshint: {
                files: ['src/*.js'],
                options: {
                    "strict": true,
                    "globalstrict"  : true,
                    "node":true,
                    "browser":true,
                    globals: {
                        exports: true
                    }
                }
            },
            watch: {
                scripts: {
                    files: ['<%= jshint.files %>'],
                    tasks: ['jshint'],
                    options: {
                        spawn: false,
                    },
                },
            },
            browserify: {
                options: {
                    browserifyOptions: {
                        debug: true
                    }
                },
                demo:{
                    files: {
                        './src/app/build/app.js': ['./src/app/app.main.js']
                    }
                }
            },
        });
        // 加载包含 "concat" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-concat');
        // 加载包含 "uglify" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-uglify');
        // 加载包含 "jshint" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-jshint');
        // 加载包含 "watch" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-watch');//grunt watch
        //加载包含 "browserify" 任务的插件。
        grunt.loadNpmTasks('grunt-browserify');
        // 默认被执行的任务列表。
        grunt.registerTask('default', ['concat','uglify','jshint']);
        grunt.registerTask('app', ['browserify:demo']);
    };

    创建demo的js文件

    app.main.js、a.js

    —demo
      |-build
         |-index.html
      |-src
         |-app.main.js
         |-a.js
      |-Gruntfile.js
      |-package.js
        

    app.main.js

    'use strict';
    var A=require("./a");
    
    function app(){
        this.a=new A();
    }
    app.prototype={
        init      : function () {
            this.a.say();
        }
    };
    
    module.exports=app;
    var base = new app();
    base.init();
        

    a.js

    'use strict';
    function a(){
    }
    a.prototype={
        say      : function () {
            console.log("hello world!");
        }
    };
    
    module.exports=a;
        

    index.html

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <meta name="manifest" content="version.json|manifest.json" />
        <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
        <meta content="telephone=no" name="format-detection" />
        <title>平安</title>
    </head>
    <body>
    <header></header>
    <div id="main">123</div>
    <div id="cover"></div>
    <script src="./app.js"></script>
    </body>
    </html>
        

    编译开发代码生成上线代码

    grunt app

    开始第一个grunt项目 提高()单元测试

    安装grunt插件:grunt-karma,karma-browserify,karma-jasmine

    cnpm install grunt-karma --save-dev
    cnpm install karma-browserify --save-dev
    cnpm install karma-jasmine --save-dev

    配置grunt配置文件Gruntfile.js

    module.exports = function(grunt) {
        // Project configuration.
        grunt.initConfig({pkg: grunt.file.readJSON('package.json'),
            //合并js
            concat: {
                options: {
                    //定义一个字符串插入每个文件之间用于连接输出
                    separator: ';'
                },
                dist: {
                    src: ['src/*.js'],
                    dest: 'build/main.total.js',
                }
            },
            //压缩js
            uglify: {
                options: {
                    banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */
    '
                },
                build: {
                    src: 'build/<%= pkg.name %>.js',
                    dest: 'build/<%= pkg.name %>.min.js'
                }
            },
            //代码检测
            jshint: {
                files: ['src/*.js'],
                options: {
                    "strict": true,
                    "globalstrict"  : true,
                    "node":true,
                    "browser":true,
                    globals: {
                        exports: true
                    }
                }
            },
            watch: {
                scripts: {
                    files: ['<%= jshint.files %>'],
                    tasks: ['jshint'],
                    options: {
                        spawn: false,
                    },
                },
            },
            karma: {
                unit: {
                    configFile: 'karma.conf.js'
                }
            },
            browserify: {
                options: {
                    browserifyOptions: {
                        debug: true
                    }
                },
                demo:{
                    files: {
                        './src/app/build/app.js': ['./src/app/app.main.js']
                    }
                }
            },
        });
        // 加载包含 "concat" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-concat');
        // 加载包含 "uglify" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-uglify');
        // 加载包含 "jshint" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-jshint');
        // 加载包含 "watch" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-watch');//grunt watch
        //加载包含 "browserify" 任务的插件。
        grunt.loadNpmTasks('grunt-browserify');
        grunt.loadNpmTasks('grunt-karma');//grunt karma *****
        // 默认被执行的任务列表。
        grunt.registerTask('default', ['concat','uglify','jshint']);
        grunt.registerTask('app', ['browserify:demo']);
    };

    创建单元测试的js文件

    app.main.js、a.js

    —demo
      |-build
         |-index.html
      |-src
         |-app.main.js
         |-a.js
      |-test
         |-unit.js
         |-demo.js
      |-Gruntfile.js
      |-karma.conf.js
      |-package.js
        

    karma.conf.js

    // Karma configuration
    // Generated on Wed Sep 16 2015 17:29:29 GMT+0800 (CST)
    
    module.exports = function(config) {
      config.set({
    
        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',
    
    
        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['browserify','jasmine'],
    
    
        // list of files / patterns to load in the browser
        files: [
          {pattern:'./test/**/*.js'}
        ],
    
    
        // list of files to exclude
        exclude: [
        ],
    
    
        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors    : {
          './test/**/*.js' : ['browserify'],
        },
    
        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['progress'],
    
    
        // web server port
        port: 9876,
    
    
        // enable / disable colors in the output (reporters and logs)
        colors: true,
    
    
        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,
    
    
        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,
    
    
        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['PhantomJS'],
    
    
        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: false
      })
    }
        

    unit.js

    var methods = require("../demo");
    var methdo = new methods();
    
    
    describe("methods tests", function ()
    {
        it("should return 3", function ()
        {
            expect(methdo.add(1,2)).toBe(3);
        });
        it("should return 5", function ()
        {
            expect(methdo.add(2,2)).toBe(4);
        });
    });
        

    demo.js

    /**
     * Created by haoyuandai on 15/9/18.
     */
    function math(){
    
    }
    math.prototype={
     add:function(a,b){
        return a+b;
    }
    }
    module.exports = math;

    运行单元测试

    grunt karma

    开始第一个grunt项目 提高()自动为代码生成API文档

    安装grunt插件:grunt-jsdoc

    cnpm install grunt-jsdoc --save-dev

    配置grunt配置文件Gruntfile.js

    module.exports = function(grunt) {
        // Project configuration.
        grunt.initConfig({pkg: grunt.file.readJSON('package.json'),
            //合并js
            concat: {
                options: {
                    //定义一个字符串插入每个文件之间用于连接输出
                    separator: ';'
                },
                dist: {
                    src: ['src/*.js'],
                    dest: 'build/main.total.js',
                }
            },
            //压缩js
            uglify: {
                options: {
                    banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */
    '
                },
                build: {
                    src: 'build/<%= pkg.name %>.js',
                    dest: 'build/<%= pkg.name %>.min.js'
                }
            },
            //代码检测
            jshint: {
                files: ['src/*.js'],
                options: {
                    "strict": true,
                    "globalstrict"  : true,
                    "node":true,
                    "browser":true,
                    globals: {
                        exports: true
                    }
                }
            },
            watch: {
                scripts: {
                    files: ['<%= jshint.files %>'],
                    tasks: ['jshint'],
                    options: {
                        spawn: false,
                    },
                },
            },
            karma: {
                unit: {
                    configFile: 'karma.conf.js'
                }
            },
            browserify: {
                options: {
                    browserifyOptions: {
                        debug: true
                    }
                },
                demo:{
                    files: {
                        './src/app/build/app.js': ['./src/app/app.main.js']
                    }
                }
            },
            //生成API文档
            jsdoc : {
                dist : {
                    src: ['src/*.js'],
                    options: {
                        destination: 'doc'
                    }
                }
            }
        });
        // 加载包含 "concat" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-concat');
        // 加载包含 "uglify" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-uglify');
        // 加载包含 "jshint" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-jshint');
        // 加载包含 "watch" 任务的插件。
        grunt.loadNpmTasks('grunt-contrib-watch');//grunt watch
        //加载包含 "browserify" 任务的插件。
        grunt.loadNpmTasks('grunt-browserify');
        grunt.loadNpmTasks('grunt-karma');//grunt karma *****
        grunt.loadNpmTasks('grunt-jsdoc');
        // 默认被执行的任务列表。
        grunt.registerTask('default', ['concat','uglify','jshint']);
        grunt.registerTask('app', ['browserify:demo']);
    };

    生成接口文档

    grunt jsdoc

    小技巧

    部分功能IE9以下可能不支持哟

    如何让客户端加载服务器字体文件?

    css中@font-face 能够加载服务器端的字体文件,让客户端显示客户端所没有安装的字体。

    @font-face :{属性: 取值;}

    @font-face{
        font-family://设置文本的字体名称。
        font-style://设置文本样式。
        font-variant://设置文本是否大小写。
        ont-weight://设置文本的粗细。
        font-stretch://设置文本是否横向的拉伸变形。
        font-size://设置文本字体大小。
        src://设置自定义字体的相对路径或者绝对路径,注意,此属性只能在@font-face规则里使用。
    }

    如何在页面做一条(小于1px)很细的线

    body{
        background-image: url("data:image/svg+xml;utf8, <svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%'> <rect fill='#c1c1c1' x='0' y='0' width='0.75' height='100%'/> <rect fill='#c1c1c1' x='99.8%' y='0' width='0.75' height='100%'/> </svg>");
        background-position-x: 0;
        background-position-y: 100%;
        background-repeat: no-repeat;
        border-bottom: 0;
    }

    如何让页面在ios上滚动的顺滑

    添加css:

    body{
        -webkit-overflow-scrolling: touch;
    }

    如何解决ios上点击300毫秒延迟问题

    使用fastclickJs模块

    <script type='application/javascript' src='/path/to/fastclick.js'></script>
    if ('addEventListener' in document) {
        document.addEventListener('DOMContentLoaded', function() {
                FastClick.attach(document.body);
        }, false);
    }

    如何将特殊的表情字符传到服务器上

    使用nodeJs-base64 模块

    var base64=require('base64-coder-node')();
    var name = 'emojsay%3fwqUds';
    name= base64.encode(name);//string转base64
    name= base64.decode(name);//base64转string

    修复 iOS 下微信浏览器设置页面标题未生效

    /**
     * @function
     * @description 修复 iOS 下设置页面标题未生效。调用方法,设置 document.title = 'Title';,后调用 updatePageTitleiOS();
     * @memberof WeChatHelper.prototype
     */
    function updatePageTitleIniOS(title){
        ////iframe 加载后的回调函数
        //function unloadHandler(){
            //document.body.removeChild(ifrm);
        //}
        document.title = title;
        //创建 iframe
        var ifrm = document.createElement('iframe');
        //iframe 指向图标文件
        ifrm.src = '/favicon.ico';
        ifrm.style.position = 'absolute';
        ifrm.style.top = '-1000px';
        //绑定回调函数
        //ifrm.addEventListener('load', unloadHandler);
        ifrm.addEventListener('load', function () {
            ifrm.removeEventListener('load');
            setTimeout(function(){
            	document.body.removeChild(ifrm);
            },10);
        });
        //添加 iframe 至文档中
        document.body.appendChild(ifrm);
    }
        

    通过 冒泡 来监听 父级元素下 多个自元素

    loadList = document.getElementById("loadList");
        loadList.addEventListener("click", function (e) {
        var thisLi;
        thisLi = e.target.parentNode.parentNode.parentNode;
        var par = thisLi.className;
        var items = par.toString().split(' ');
        switch (items[1]) {
            case "1":
                var params = '{"idApplicant": "' + items[2] + '","claimType": "' + items[1] + '","toaTaskNo": "' + items[3] + '"}';
                router.navigate("wcOnlineClaimInfo/" + params);
                break;
            case "2":
                var params = '{"idApplicant": "' + items[2] + '","claimType": "' + items[1] + '","docuNo": "' + items[3] + '"}';
                router.navigate("wcOfflineClaimInfo/" + params);
                break;
        }
    }, true);
        

    Doc中 Class 操作

    javascript根据 class名称 来获取dom对象

    getElementsByClassName('className')

    classList操作

    body.classList.length //获取类名的数量
    body.classList.item(num) //根据num获取元素的类名
    body.classList.add('className') //增加元素的类
    body.classList.remove('className') //删除元素的类
    body.classList.contains('className') //检测元素是否包含某个类
    body.classList.toggle('className') //存在即删除不存在即添加

    掌控this

    Function.prototype.bind的作用

    this.a=1;
    document.body.addEventListener('click',function(e){
        alert(e.target);
        alert(this.a);//undefined
    });
    //document.body.addEventListener('click',function(e){
    //    alert(e.target);
    //    alert(this.a);//1
    //}.bind(this));
  • 相关阅读:
    2021NUAA暑假集训 Day3 题解
    2021NUAA暑假集训 Day2 题解
    2021NUAA暑期模拟赛部分题解
    CodeForces 1038D Slime
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 10689 Yet another Number Sequence
    HDU 4549 M斐波那契数列
    HDU 4990 Reading comprehension
    CodeForces 450B Jzzhu and Sequences
  • 原文地址:https://www.cnblogs.com/wjglj/p/4968488.html
Copyright © 2011-2022 走看看