zoukankan      html  css  js  c++  java
  • 前端客户端自动构建

    构建原因

    • 规范代码所有代码构建前均会先进行规范审核,根据不同语言预设判断。
    • 提高效率将需要重复输入的有规律的设置,用自动化的方式添加。
    • 避免疏忽把默认需要操作的动作用程序代替,避免人为疏忽。
    • 提高性能把开发时的易于编辑的源码转化为访问时性能较高的结果。
    • 减少重复将重复调用的内容用程序的方式生成结果,避免访问负荷。
    • 板块化按板块开发,生成整体页面,用组装的方式实现。

    构建内容

    • 脚本*.js --> *.js, *.min.js, map/js.json
    • 样式*.css --> *.less, *.min.css, map/css.json
    • 模板views/.json --> views/.hbs, views/*.min.hbs, map/html.json
    • 图片*.[png|jpg|gif|svg|ico] --> *.[png|jpg|gif|svg|ico], map/img.json
    • 字体font/.[eot|ttf|woff|woff2|svg] --> font/.[eot|ttf|woff|woff2|svg]
    • 第三方bower.json --> bower.json, bower_components/*

    构建配置

    • 安装全局命令
    npm install gulp-cli -g
    npm install bower -g
    
    • 安装构建依赖
    cd node-m/static/auto
    npm install --no-save // 安装但不更新 package.json 和 package-lock.json 
    "bower": "^1.7.9",
    "browser-sync": "^2.11.0",
    "del": "^2.2.0",
    "gulp": "^3.9.0",
    "gulp-changed": "^1.3.0", // 用于判断文件是否更新
    "gulp-clean-css": "^2.0.9",
    "gulp-csslint": "^0.3.1",
    "gulp-eslint": "^4.0.0", // 更新至 4.0.0
    "gulp-hasher": "^0.1.0", // 生成文件 md5
    "gulp-htmllint": "0.0.11",
    "gulp-htmlmin": "^1.2.0",
    "gulp-include": "^2.0.2",
    "gulp-less": "^3.0.1",
    "gulp-lintspaces": "^0.4.1",
    "gulp-rename": "^1.2.2", // 更改后缀/增加前缀
    "gulp-uglify": "^1.4.1",
    "gulp-util": "^3.0.7", // 主要用于输出错误信息
    "gulp-watch": "^4.3.6",
    "htmllint": "^0.3.0",
    "merge-stream": "^1.0.0",
    "q": "^1.4.1",
    "run-sequence": "^1.1.5",
    "svgo": "^0.7.2",
    "through2": "^2.0.0" // 可读、可写流生成
    

    构建方式

    • 自动监听构建
    gulp watch // 监听所有资源
    
    • 全量重新构建
    gulp all // 生成所有资源(除第三方资源外)
    
    • 增量单独构建
    gulp tpl // 生成修改或新增模板
    gulp css // 生成修改或新增样式
    gulp js // 生成修改或新增脚本
    gulp img // 生成修改或新增图片
    gulp font // 生成修改或新增字体
    gulp bower // 生成修改或新增第三方资源
    
    • 全量单独构建
    gulp tplAll // 生成所有模板
    gulp cssAll // 生成所有样式
    gulp jsAll // 生成所有脚本
    gulp imgAll // 生成所有图片
    gulp fontAll // 生成所有字体
    gulp bowerAll // 生成所有第三方资源
    

    构建原理(图片)

    //pipe直接复制(svg 除外) 
    .pipe(svgProcess())
    .pipe(gulp.dest('../dest'))
    .pipe(hasher()) // 计算文件 md5
    .pipe(resouceMap(hasher.hashes, 'img')); // 生成后缀文件
    //svgProcesssvg 压缩 
    return through.obj(function(file, enc, cb) {
        if(file.path.match(/.svg$/)){
            (new svgo()).optimize(String(file.contents), function (result) {  // 使用 svgo 对象
                if (result.error) {
                    return cb(new gutil.PluginError('svgProcess', result.error));
                }
                file.contents = new Buffer(result.data); // 对文件内容重新赋值
                cb(null, file); // 继续往下流
            });
        }else{
            cb(null, file);
        }
    });
    
    //resouceMap对后缀文件对象进行排序生成 
    for(x in hashesRead){
        keyTemp.push(x);  // 已有文件
    }
    for(y in hashesWrite){
        keyTemp.push(y);  // 新增文件
    }
    keyTemp.sort();  // 文件名排序
    keyTemp.forEach(function(v,k){
        hashesTemp[v] = 'undefined' !== typeof hashesWrite[v] ? hashesWrite[v] : hashesRead[v]; // 排序后的对象
    });
    

    构建原理(脚本)

    //pipe生成未压缩和已压缩版本 
    .pipe(eslint({
        configFile: '.eslintrc' // eslint 配置文件
    }))
    .pipe(eslintReportor()) // 审核错误报告
    .on('error',errorProcess)
    .pipe(gulp.dest('../dest')) // 直接复制生成未压缩文件
    .pipe(browserSync.stream())
    .pipe(uglify({
        preserveComments: 'license' // 压缩,保留许可注释
    }))
    .on('error',errorProcess)
    .pipe(rename(function (path) {
        path.basename += ".min";  // 压缩文件增加前缀
    }))
    .pipe(gulp.dest('../dest'))
    .pipe(rename(function (path) {
        path.basename = path.basename.replace(/.min$/, ''); // 恢复原名
    }))
    .pipe(hasher())  // 以压缩版本生成后缀
    .pipe(resouceMap(hasher.hashes, 'js'));
    //eslintReportor审核通过继续,不通过输出错误信息 
    if(result.errorCount > 0 || result.warningCount > 0){ // 错误或警告数大于 0
        result.messages.forEach(function (issue) { // 错误信息循环输出
            lintReporter('eslint', result.filePath, issue.line, issue.column, issue.ruleId, issue.message, type[issue.severity]);
        });
    }
    if(result.errorCount < 1){
        cb(null, file);  // 没有错误,继续往下走
    }else{
        cb(); // 有错误,当前文件不再往下走
    }
    

    构建原理(样式)

    //pipe生成未压缩和已压缩版本 
    .pipe(lintspaces({
        indentation: 'spaces',  // 统一缩进
        spaces: 4
    }))
    .pipe(lintspacesReporter())  // 缩进错误输出
    .pipe(less())  // less 编译
    .on('error',errorProcess)
    .pipe(csslint('.csslintrc'))  // csslint 配置文件
    .pipe(csslintReporter())  // 审核错误报告
    .on('error',errorProcess)
    .pipe(cssImgHash())  // 增加图片后缀
    .pipe(gulp.dest('../dest'))  // 生成 css 文件
    .pipe(browserSync.stream())
    .pipe(hasher())
    .pipe(resouceMap(hasher.hashes, 'css'))
    .pipe(minifyCss({rebase: false}))  // 压缩样式,不处理路径
    .pipe(rename(function (path) {
        path.basename += ".min";
    }))
    //cssImgHash对所有引用图片添加后缀 
    contents = contents.replace(/url((["']?)([^)"']+?)1)/ig, function(match, quote, url){ // 匹配引用图片
        var result;
        var hashUrl = url.replace(/^//, '');
        hashUrl = hashUrl.substring(0, -1 != hashUrl.indexOf('?') ? hashUrl.indexOf('?') : hashUrl.length).replace(//|.|-/g, '_'); // 后缀字段
        if('undefined' != typeof hashes[hashUrl]){
            result = 'url(' + url + '?' + hashes[hashUrl] + ')';
        }else{
            result = match;
        }
        return result;
    });
    

    构建原理(模板组装)

    //pipe将 json 中的板块合并为 hbs 
    .pipe(concatLibs()) // 组装板块
    .pipe(htmlParser(false)) // 处理文档
    .pipe(rename({extname:".hbs"}))
    .pipe(htmllint({}, function(){}))
    .on('error',errorProcess)
    .pipe(htmllintReporter())
    .pipe(gulp.dest('../dest'))
    .pipe(htmlParser(true))
    .pipe(htmlmin({ // 压缩 html
        collapseWhitespace: true, // 空格处理
        processScripts: ['text/x-handlebars-template'], // 脚本标签中的模板
        removeComments: true, // 去除注释
        ignoreCustomFragments: [/\?{{.+?}}/] // 忽略变量
    }))
    .on('error',errorProcess)
    .pipe(rename(function (path) {
        path.basename += ".min";
    }))
    //concatLibs把板块连接,并更新相对路径 
    data = data.replace(/(['"])((?:..?/)+)/g, function(match, quote, url){
        return quote + path.relative(file.base, path.join(path.dirname(libFile), url)).replace(/\/g, '/') + '/';
    });
    
    

    构建原理(地址处理)

    //图片地址增加域名与后缀 
    reg.img = /<img[^>]*src="([^"]*)"[^>]*>/igm; // 普通图片
    reg.imgData = /<img[^>]*data="([^"]*)"[^>]*>/igm; // 延迟加载图片
    reg.ico = /<link[^>]*href="([^"]*.(ico|png))"[^>]*>/igm; // ico 图片 
    tempUrl = tempUrl.substring(0, -1 !== tempUrl.indexOf('?') ? tempUrl.indexOf('?') : tempUrl.length); // 去掉原有后缀
    var hashUrl = tempUrl.replace(//|.|-/g, '_'); // 统一字段字符
    tempUrl = '{{constant.url.resource}}' + tempUrl + '?{{hash.img.' + hashUrl+ '}}'; // 添加域名后缀
    //样式地址增加域名与后缀,放置在 head 里,压缩版本串联 
    var stylesReg = /({{#[^}]*?}}(?:
    ?
    )?)?<link(?:.*)rel="stylesheet"(?:[^>]*)/?>(?:
    ?
    )?({{/[^}]*?}}(?:
    ?
    )?)?/gim // 提取样式标签 
    contents = contents.replace(/({{{w+}}}s*)?(</head>)/, stylesTag + '$1$2'); // 放到 head 结束标签前 
    stylesUrl += styles[x].replace(stylesReg, '$1').trim()
        + minUrl + '?{{hash.' + hashKey + '.' + hashUrl + '}}' + (x >= stylesLength-1 ? '' : ',')
        + styles[x].replace(stylesReg, '$2').trim();  //连接为一条地址
    //脚本地址增加域名与后缀,放置在 body 最后面,压缩版本串联 
    var scriptsReg = /<script[^>]*>[^<]*</script>(
    ?
    )?/gim; // 提取脚本标签 
    var orderReg = /order="(-?d+)/i // 脚本顺序提取
    if(!toMin){
        var order = 10000;
        scripts = scripts.map(function(v){
            if(!v.match(orderReg)){
                v = v.replace('<script', '<script set-order="' + order + '"'); // 设置默认顺序
                order++;
            }
            return v;
        });
        scripts.sort(function(a,b){
            return parseInt(orderReg.exec(a)[1]) - parseInt(orderReg.exec(b)[1]); // 从小到大排序
        });
        scripts = scripts.map(function(v){
            v = v.replace(/sset-order="(d+)"/i, ''); // 删除增加的顺序属性
            return v;
        });
    }
    
  • 相关阅读:
    C#中 @ 的用法
    ASP.NET页面间传值
    ASP.NET中常用的文件上传下载方法
    把图片转换为字符
    把图片转换为字符
    JavaScript 时间延迟
    Using WSDLs in UCM 11g like you did in 10g
    The Definitive Guide to Stellent Content Server Development
    解决RedHat AS5 RPM安装包依赖问题
    在64位Windows 7上安装Oracle UCM 10gR3
  • 原文地址:https://www.cnblogs.com/junhey/p/8981699.html
Copyright © 2011-2022 走看看