Giter Site home page Giter Site logo

blog's Introduction

blog's People

Contributors

paper avatar

Watchers

 avatar

blog's Issues

单项目,但里面又是多个独立页面,并且需要多人构建与部署内外网的问题

项目场景说明

项目是在 git 上是单项目,src 里面的每个目录是单个小项目,可单独构建。

比如项目名称叫:project,里面有个目录 src,然后里面是多个独立项目 activitysharelogin 等等50多项目(每个项目可单独构建调试与部署)。

遇到的问题

由于项目不是一个 npm run build 命令就可以全部构建,那么提交到远程分支 release/dev 时,触发 JK 想自动部署内网环境,就不知道运行哪个项目

有个思路是:在提交时的 commit 命令加上一些关键字,进行钩子解析。

或者使用一个 sh 文件,每次提交时,你可以修改这个文件并运行这个 sh 文件,sh 里面写 npm 命令(比如写 npm run share-build 等一个或多个)。这个想法可以,但有个问题,多人的话,每个人的事情不同,那么每次可能都会冲突或覆盖,有沟通成本。如果合并的话又会重复构建,浪费了部署时间。

所以我们根据这个思路,想了个法子

解决过程

第1步:建个 jk-build 目录

建个 jk-build 目录,里面放上每个同学 git 上提交的的名字,比如 zhangsan.shlisi.sh 等等。

第2步:Jenkinsfile 做加一些环境参数

environment {
    PROJECT_NAME = sh(script: 'basename -s .git `git config --get remote.origin.url`', returnStdout: true).trim()
    PATH = "/root/.nvm/versions/node/v12.13.1/bin/:$PATH"
    GIT_NAME = sh(script: "git --no-pager show -s --format='%an' $GIT_COMMIT", returnStdout: true).trim()
    GIT_EMAIL= sh(script: "git --no-pager show -s --format='%ae' $GIT_COMMIT", returnStdout: true).trim()
    GIT_FILES= sh(script: "git diff --name-only HEAD~ HEAD", returnStdout: true).trim()
    GIT_AUTHOR_LIST_ONE_MINUTE= sh(script: "git log --since=1.minute.ago --merges | grep '^Author: ' | sort | uniq -c | awk '{print \$3}'", returnStdout: true).trim()
    GIT_LATEST_LOGS_LIST= sh(script: "git log --pretty=format:'%h - %an, %ar : %s @#@' --since=15.minute.ago", returnStdout: true).trim()
}

这样在 JK 运行的 sh 里面可以获取对于的变量值 ${GIT_NAME} 等值

有个细节大家可以注意到:GIT_AUTHOR_LIST_ONE_MINUTE 是取最近1分钟提交提交的作者的名字,这是因为出现过比较边界的情况,就是当2个同学几乎同时提交后,JK 只会运行最后一次提交,那么前一个同学的构建就没有触发,所以我们把提交记录1分钟内的同学都进行构建。(你也可以改为2分钟)

第3步:编写某个同学的 sh 脚本内容

dingDingLogdingDingLogTextdingDingError 都是另外一个 sh 提供的钉钉通知的功能

zhangsan.sh 的内容:

# =================================================================
# 下面的代码不要动!!!!下面的代码不要动!!!!下面的代码不要动!!!!
# =================================================================
CURRENTDIR=`pwd`
source ${CURRENTDIR}/deploy_ecs/t.sh
echo "【日志】正在部署 张三 的脚本......"
dingDingLog 正在部署张三的脚本

# ====================  从这个下面开始修改  ==============================
# 这里写各自的 npmCheckRun 命令
# Example: npmCheckRun master-invitation-build

# 可构建1个或多个任务
npmCheckRun master-invitation-build
npmCheckRun master-invitation-v2-build
npmCheckRun master-invitation-v3-build

npmCheckRun 是一个 npm run 的校验版本

npmCheckRun() {
  name=$1

  npm run ${name}

  dingDingLogText "正在编译的项目是-->${name}"

  if [ $? -ne 0 ]
  then
      dingDingError "npm-build-failed-->${name}"
      exit 1
  fi
}

第4步:触发当前提交者的 shell 脚本

CURRENTDIR=`pwd`
branch=${GIT_BRANCH} # 分支名称
gitName=${GIT_NAME} # 提交人的全拼

gitNameShPath=${CURRENTDIR}/jk-build/${gitName}.sh

# https://www.cnblogs.com/emanlee/p/3583769.html
# 如果文件存在
if [[ -f "${gitNameShPath}" ]]
then
  # 先触发第一个提交的人的sh
  source ${gitNameShPath}
else
  echo "[日志] GIT_NAME=${gitName}.sh 不存在"
  dingDingError "${gitName}.sh不存在"
fi

# 再判断 GIT_AUTHOR_LIST_ONE_MINUTE 的提交人列表
for user in ${GIT_AUTHOR_LIST_ONE_MINUTE}
do
  userShPath=${CURRENTDIR}/jk-build/${user}.sh

  echo "[日志] userShPath=${userShPath}"

  # 如果文件存在
  if [[ -f "${userShPath}" ]]
  then
    # 因为前面已经执行了 GIT_NAME 的脚本,所有如果 user 相同就不再执行
    if [ "${user}" != "${GIT_NAME}" ]
    then
      echo "[日志] 正在执行--${user}.sh"
      source ${userShPath}
    fi
  else
    echo "[日志] ${user}.sh 不存在"
    dingDingError "${user}.sh不存在"
  fi
done

接下来的事情,就是和大家一样,同步代码等等

存在的问题

个人 sh 文件小冲突

当前用户提交到 release/dev 时,要解决一下自己 sh 的可能会出现小冲突问题,
不过这个也很好解

并发构建

当多人并发构建时,jk 机器为了并发构建,会根据你设置的并发构建数量(通常是机器的内核数),生成多个目录

CURRENTDIR=`pwd`
branch=${GIT_BRANCH} # 分支名称

if [[ "${branch}" = "release/dev-ecs" ]]
then
  # 只在测试环境做实验,因为测试环境提交的人多,并发的可能性很高
  # 先清空 workspace/fe_nodeproject_release_dev-ecs/dist 或 workspace/fe_nodeproject_release_dev-ecs@2/dist 目录
  # 这样做的目的是,当发生并发构建时,谁完成的顺序是未知的,如果 @2 先完成,把最新的代码copy到 f2e_very_important_dev_dist,再把 f2e_very_important_dev_dist拷贝回来。
  # 再最初的完成后,又会把 @2的旧项目copy到f2e_very_important_dev_dist,导致代码未更新。
  # 所以尝试,每次构建之前,先清空 dist 目录,构建完成后,只有当前人构建的项目,避免旧项目也一同copy
  
  rm -rf ${CURRENTDIR}/dist/*
fi

# ======================================================================
# 说明为什么这么做:因为如果 jk 并发构建时,会触发生成 @2,@3 这一类的目录,而这些目录里面的 dist 是空的或者是不全的。所以需要从外面的备份的完整的 dist 拷贝进来
# 方案:
# 1)先当项目里面一个或多个 npmCheckRun 构建都成功后,把项目的 dist 目录 copy 到对应分支的公共 dist 目录。(即更新公共目录的dist文件)
# 2)然后,把最新的公共 dist 目录里面的文件,拷贝回当前构建项目的 dist 目录。
# 3)这样,就保证了在打 docker 镜像时,dist 会是一个最新并且完整的。
# 4)很明显,这是一个增量的方式,所以外面 dist 目录的文件会越来越多,当大到一定程度时,我会写一个脚本,来移除文件时间老旧的文件,保留最新文件。

# 外面的目标目录名称
distName=""

if [[ "${branch}" = "release/dev-ecs" ]]
then
  distName="f2e_very_important_dev_dist"
fi

if [[ "${distName}" != "" ]]
then
  # 把整个 dist 目录放到 distName 目录里面
  cp -fpr ${CURRENTDIR}/dist /data/jenkins/${distName}/
  # 把 distName 里面的 dist 所有文件,复制到 CURRENTDIR/dist 里面
  cp -fpr /data/jenkins/${distName}/dist/* ${CURRENTDIR}/dist/ 
fi

总结

目前这套方案运行还是蛮顺利的,职责也非常清晰明了。

如果是发线上,那么就根据 master 分支,运行专属的 jk-build/master.sh 即可。

线上是全量部署,因为是打一个 Docker 镜像的方式部署的,所以要把所有代码全部打包进去。但 Docker 本身是有缓存的,利用缓存,推送镜像的速度也不会太慢。

notepad++ run java

cmd /k cd "$(CURRENT_DIRECTORY)" & javac "$(FILE_NAME)" & java "$(NAME_PART)"

用Shell脚本批量裁剪App Icon各个尺寸

http://www.isaced.com/post-247.html

#!/bin/sh

filename="logo.png"
dirname="cutimg"
name_array=("Icon-29.png" "Icon-40.png" "Icon-58.png" "Icon-76.png" "Icon-80.png" "Icon-87.png" "Icon-120.png" "Icon-152.png" "Icon-180.png")
size_array=("29" "40" "58" "76" "80" "87" "120" "152" "180")

mkdir $dirname

for ((i=0;i<${#name_array[@]};++i)); do
    m_dir=$dirname/${name_array[i]}
    cp $filename $m_dir
    sips -Z ${size_array[i]} $m_dir
done
  1. 把 icon.sh 文件放到 你的 logo.png(2014 * 1024) 的目录下
  2. 然后执行它

确定 和 取消?

今天同事群里发了个这个: http://weibo.com/3229125510/C44Cl8kwC
挺有意思,就 “收藏” 了一下。

当我再点 “取消收藏” 时,出现:
qq 1

我 “犹豫” 了一小会,虽然我知道微博想表达的含义,但还是“犹豫”了一会~~
后来经过在部门群内部讨论一下,改成下面这样是不是会更好?
qq 2

后来有个同事说,这个其实是已经有人总结的,在这里:
qq 3

看来我眼皮跳,果然是有先兆的!~

职业病好难受啊!摔!(╯‵□′)╯︵┴─┴

console 函数重写

console函数重写

有个需求,需要在手机端做个“彩蛋”:
在手机端,利用某种特殊手势操作,把代码里面所有的console过的东西,都打出来,放到页面上。

var debug = (function(){

    var consoleData = [];
    var oldConsole = console;

    return {
        init: function(){
            window.console = {};

            // 重写
            for(var i in oldConsole) {
                if ( typeof oldConsole[i] == 'function' ) {

                    window.console[i] = (function(cfn){
                        return function(){
                            var data = Array.prototype.slice.call(arguments);
                            consoleData.push(data);

                            cfn.apply(oldConsole, arguments);
                        }
                    })(oldConsole[i]);

                } else {
                    console[i] = oldConsole[i];
                }
            }
        },

        getConsoleData: function(){
            return consoleData;
        }
    }
})();

debug.init();

这样当代码里面使用 console 时,就会把数据记录下来。怎么使用,就简单多了~


这有个问题就是:正常的console的数据的定位会发生错误。。。

微信发送长文字

有没有这种情况

  1. 你有很多话想说
  2. 不想发语音(语音对于查询历史记录,那就是灾难)
  3. 不想打那么多字(手机打字还是蛮辛苦的)

肿么办~ 妥协之后,还是码字吧...Orz


目前的微信版本(5.2)是支持语音转文字的,
长按对方发的声音就会出现这个选项。
只要普通话不是很差,还是蛮不错的。

不过,还是有:

  • 标点符号混乱
  • 错别字

这个很难避免。

但我们可以利用这个:

  1. 长按左下角的语音文字图标,冒出“语音转文字”图标
  2. 进入“语音转文字录入页面”
  3. 按下录音,松手后,转换成文字
  4. 提供文字编辑功能,提供复制按钮
  5. 稍微编辑修改后,复制并关闭“页面”
  6. 你想发送给谁,就粘贴一下吧

解释一下第一条,为什么这个“图标”要这么隐蔽?

  1. 保持页面简洁,和以前一模一样
  2. 这个功能使用的场合比较少

我个人是挺需要这个功能的 ... 希望以后版本会有

就酱

idea or work

  1. nodeHost - nodeWebkit
    a. 右下角 tip 提示
    b. 查看当前系统host
  2. nodeSprite - like cssgaga
  3. es6 - js

前端实习生学习路线记录

2021年
这里记录下带实习生的路线

需要看的“书”

JavaScript

  1. JavaScript语言精粹 https://book.douban.com/subject/11874748/
  2. DOM编程艺术 https://book.douban.com/subject/6038371/
  3. ES6 入门教程:https://es6.ruanyifeng.com/
  4. 现代 JavaScript 教程 https://zh.javascript.info/
  5. JavaScript高级程序设计(第4版) https://book.douban.com/subject/35175321/

红宝书作为前面个看不懂时,可以去当做深入理解去查询的“字典”。
因为这本书有点厚,内容多而丰富,容易劝退和不容易记忆。所以放在最后,权先当做“字典”。

以后要看的进阶书:

  1. JavaScript 设计模式与开发实践 https://book.douban.com/subject/26382780/
  2. 你不知道的 JavaScript https://github.com/getify/You-Dont-Know-JS/tree/1ed-zh-CN

再后续:

  1. React
  2. Vue
  3. Typescript

CSS

  1. 《精通 CSS(第3版)》https://book.douban.com/subject/30450258/
  2. 后续CSS可能也要再多看1-2本,这个不急,先看完上面的:精通 CSS(第3版)

其他

  1. 正则表达式30分钟入门教程:https://deerchao.cn/tutorials/regex/regex.htm
  2. 写给大家看的设计书(第4版)https://book.douban.com/subject/26664522/
  3. 前端基本开发规范和命名 https://juejin.cn/post/6844903479698259975

要练习的Demo

  1. Windows11 日历 (分:重构,实现,交互,兼容性,移动版,拖动,最后组件化)
  2. 贪吃蛇
  3. 俄罗斯方块
  4. 扫雷
  5. taobao首页模拟(PC + Mobile)
  6. lodash 的函数实现。

做具体线上项目

运营商劫持临时解决方案

因为不是https,项目被联通运营商(移动网络)劫持。
听朋友建议使用CSP(Content-Security-Policy)

相关文章:
http://caniuse.com/#feat=contentsecuritypolicy
http://www.html5rocks.com/en/tutorials/security/content-security-policy/

目前是通过添加白名单的方式解决联通的js注入问题。

<!--脚本加载白名单 【临时解决方案,后续还是要使用https来解决这个问题】--> 
<meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-inline' 'unsafe-eval' *.sjzhushou.com *.xunlei.com"> 

后续还是最好使用https协议。

一个“合格”项目 readme.md 之我见

目前在公司正在推广项目的readme模板,代码之所以很难维护,或者说变成“屎山”,很大原因是项目交接时,没有把事情说清楚。而项目的 readme.md 本就应该承担起一大部分这个任务。(结合内部 wiki 可补充说明)

我曾经和同事说过:就好比你失忆了,然后第2天来公司开发这个项目,你觉得昨天的你需要告诉你哪些信息 ??

下面一些模板“填空题”,如果详细和完整的话,即使一个新招聘同学让他上手的话,会给他非常好的第一印象。


项目地址(必填)(你们项目的 gitlab 地址)

https://gitlab.company.cn/xxxx

项目说明(必填)

云盘是.....

项目相关文档和人员(必填)

  1. 产品总文档地址是:xxxx (wiki地址)
  2. 产品人员有:xxx
  3. 开发人员有:xxx
  4. 设计人员有:xxx
  5. 设计稿地址在哪:xxxx (ftp,figma等等)
  6. 测试人员有:xxx
  7. jira总项目地址在哪:xxxx
  8. 等等。。

项目支持的环境(必填)

  1. PC浏览器环境(Chrome,Safari,Edge 等等)
  2. 客户端内嵌页
  3. 等等。。

相关地址(必填)(如果要配 host 也要详细写上)

  1. 线上:https://www.xx.com
  2. 测试环境:https://
  3. 预发布环境:

如何开发(必填 - 重点 - 要非常详细)

  1. 第一步通常 npm install 开始
  2. package.json 每一个 script 的命令说明和它的用途是什么?
  3. 然后运行 xxx
  4. 手机上如何开发调试。。。
  5. pc上浏览器如何开发调试。。。
  6. 客户端上如何开发调试。。。
  7. 等等。。把你开发时用到工具 和 流程一步一步写一下。

如何部署(必填 - 重点 - 要非常详细,精确到操作的每一步)

  1. 线上如何部署和验证?(这里可展开讲讲)
  2. 测试环境如何部署和验证?(这里可展开讲讲)
  3. 预发布环境如何部署和验证?(这里可展开讲讲)

如何测试(如果有)

  1. mocha,jest 等等。。
  2. 无头浏览器(如果用到了)
  3. 等等。。

监控(如果有)

  1. 监控有哪些?
  2. 监控的地址是:
  3. 监控谁在管??
  4. 等等。。。

推荐的工具和经验(最好有)

  1. 项目开发过程中,第1批或第2批开发人员的一些开发、调试等常用工具
  2. 第1批或第2批开发人员开发这个项目时的一些经验之谈,给后续维护者少走弯路
  3. 等等。。

注意事项(最好有)

  1. 有哪些坑??给下一位开发者,要注意什么?(比如我什么时候踩过什么坑等等。。)
  2. 代码有哪些需要注意的也可以写出来。
  3. 等等。。

大体的技术细节有哪些?大概思路是怎样?(选填)

  1. 用的什么框架
  2. 做了哪些优化
  3. 有什么技术细节,只有你知道的
  4. 想让大家快速提前了解的重点
  5. 等等。。

重要目录和文件说明(尽量有)

  1. /pages Nuxt项目的页面地址(即路由)
  2. 等等。。

项目截图(看情况)

  1. 如果这个项目是一个UI组件,那就是必填了。

changelog

  1. 重要的更新说明

大家可自行补充

  1. TODO

如果可以的话,放到项目脚手架上也是最好的。

requirejs 和 r.js 构建实践与练习

短视频构建(requirejs + r.js)

2016年年底时,Android 和 iOS 短视频使用的是r.js 进行打包合并的。故在这里做一下简要说明。

短视频Android和iOS的地址分别是:
\web_common_h5\src\page\video\web_ios_h5\src\page\video

页面需要引入的必须代码:

  1. //m.sjzhushou.com/h5/thirdlib/zepto/1.1.6/zepto.all.min.js
  2. //m.sjzhushou.com/h5/thirdlib/vue/1.0.10/vue.min.js(因为短视频使用了vue)
  3. //m.sjzhushou.com/h5/thirdlib/requirejs/2.1.20/require.min.js

再引入:index.js

这里主要说明一下index.js

index.js 不仅是 requirejs 配置和执行的脚本,又是r.js的配置文件。这样做的好处就是,只需要维护一份代码,就可以同时使用开发模式和线上模式

// 这是 iOS短视频 的index.js
(function(){

    // 调试开关
    var debug = false;

    // 版本时间戳,如果是调试模式,那么就是无缓存模式
    // 每次上线时,压缩合并后的代码都具有自定义时间戳(而不使用md5)。这样方便回归代码,出问题方便回退。
    var t = debug ? (+new Date) + '' : '20160203_1727';
    var urlArgs = 't=' + t;

    var shortVideo_requirejs_config = {
        baseUrl: '../../',
        paths: {
            'text': 'lib/textjs/text.min',

            // 引用线上的代码,是无法合并打包的
            'md5':'http://m.sjzhushou.com/h5/lib/md5',
            'client':'http://m.sjzhushou.com/h5/lib/client',
            'ready':'http://m.sjzhushou.com/h5/lib/ready',
            'util':'http://m.sjzhushou.com/h5/lib/util',
            'video_source' : 'http://m.sjzhushou.com/h5/page/common/video_source',

            'video': 'component/video/video',
            'share': 'component/share/share',
            'recommend': 'component/recommend/recommend',
            'comment': 'component/comment/comment',

            'main': 'page/video/main',
            'main-build': 'page/video/dist/main-build-min-' + t
        }
    };

    // 这个是页面使用的代码,不是为了r.js构建的。
    // 故延迟1ms,是为了防止使用r.js 构建时报错
    setTimeout(function(){
        try{
            require.config({
                baseUrl : shortVideo_requirejs_config.baseUrl,
                paths   : shortVideo_requirejs_config.paths,
                urlArgs : urlArgs
            });

            if (debug) {
                // 测试环境
                require(['main']);
            } else {
                // 正式环境,打包后的
                require(['main-build']);
            }
        }catch (e) {}
    }, 1);

    // for rjs build
    // 这样只要写一份shortVideo_requirejs_config配置文件,就可以完成开发和上线时同步,不必担心遗漏
    return {
        baseUrl : shortVideo_requirejs_config.baseUrl,
        paths   : shortVideo_requirejs_config.paths,

        name    : shortVideo_requirejs_config.paths.main,
        out     : 'dist/main-build-min-'+ t +'.js'

        // 如果不压缩,就取消这个注释(一般都合并压缩)
        //optimize: "none",
    };

})();

配置 gulpfile.js

// 这是 iOS短视频 的gulp任务
var gulp = require('gulp');
var exec = require('child_process').exec;
var rjsPath = 'node_modules/requirejs/bin/r.js';

// 短视频rjs构建
gulp.task('shortVideoBuild', function(cb) {
    var buildPath = 'src/page/video/index.js'

    exec('node ' + rjsPath + ' -o ' + buildPath, function(err){
        if (err) return cb(err); // 返回 error
        cb(); // 完成 task
    });
});

上线之前,运行一次 gulp shortVideoBuild,然后上传对应的代码即可。
建议:除了上传压缩版本的main-build,还要上传其他用来被合并的单独的文件哦。(这里吐槽一下rz -y 的上传方式)

【注意点】
1,index.js: t = 上线时的时间点
2,index.js: debug = false
3,页面引入的 index.js 也要加时间戳哦,为了清缓存

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.