<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DevOps on Time Friend</title><link>https://time-friend.com/zh/categories/devops/</link><description>Recent content in DevOps on Time Friend</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Sun, 15 Dec 2019 23:15:00 +0000</lastBuildDate><atom:link href="https://time-friend.com/zh/categories/devops/index.xml" rel="self" type="application/rss+xml"/><item><title>持续集成 - 代码质量扫描</title><link>https://time-friend.com/zh/archive/continuous-integration-code-quality-scanning/</link><pubDate>Sun, 15 Dec 2019 23:15:00 +0000</pubDate><guid>https://time-friend.com/zh/archive/continuous-integration-code-quality-scanning/</guid><description>&lt;p&gt;为了方便管理公司的代码质量,让代码质量扫描跟持续集成结合到一起是重要的一步.
目前公司比较年轻,但是在短短的一年时间里,也有了接近300个前端项目.&lt;/p&gt;
&lt;p&gt;这么多的前端项目,我们如何保证代码质量就成了一个很重要的事情.&lt;/p&gt;
&lt;p&gt;代码项目太多,codereview是必要的.但是人肉codereview不能保证效率.
因为个人水平的差距,与公司规范的熟悉程度.不能保证所有项目的规范一致性.
还有一些潜在的bug也有可能会被漏掉.&lt;/p&gt;
&lt;p&gt;我们公司是基于Gitlab CI/CD,所以以下说明是基于Gitlab的方式.但是思路的运用是相通的,有需要的人可以借鉴思路.&lt;/p&gt;
&lt;h2 id="修改gitlab-ciyml"&gt;修改.gitlab-ci.yml&lt;/h2&gt;
&lt;p&gt;为了方便每一个项目接入,我们对配置做了很小的改动.
并且每一个项目的配置的修改都是一样的,就是为了方便无脑的复制粘贴.&lt;/p&gt;
&lt;p&gt;我们还做了一个cli工具,里面包含代码扫描的一切功能.安装在runner的机器上.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;node:11.10.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;stages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;codereview&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 添加一个codereview的stage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;codereview&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;stage&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;codereview&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;cli codereview&lt;/span&gt; &lt;span style="color:#75715e"&gt;# cli工具触发codereview&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tags&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;fe&lt;/span&gt; &lt;span style="color:#75715e"&gt;#runner的tag,根据自己的情况自行修改&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="cli-触发代码扫描做什么"&gt;cli 触发代码扫描做什么?&lt;/h1&gt;
&lt;h2 id="执行sonarqube扫描"&gt;执行SonarQube扫描&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;关于SonarQube的安装,网上有很多教程请自行搜索.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;在执行runner的机器上安装 &lt;code&gt;sonar-scanner&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm i sonar-scanner -g
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;利用自研的cli工具,在项目根目录生成sonar 扫描的配置文件.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取gitlab 注入ci的环境变量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;CI_PROJECT_NAME&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;CI_PROJECT_ID&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;env&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 基于gitlab的项目id生成一个sonar的projectKey
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;projectBuffer&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Buffer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;from&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;sonar&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CI_PROJECT_ID&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;projectKey&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;projectBuffer&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toString&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;hex&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 检测代码目录
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 一般来说 src都是前端项目业务代码的目录
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//因为公司的nodejs项目是基于egg框架的,也有可能是app
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;existsSrc&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fs&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;existsSync&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cwd&lt;/span&gt;()&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/src/`&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// sonar配置文件模板
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sonarProject&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;sonar.projectKey=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;projectKey&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;sonar.projectName=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;CI_PROJECT_NAME&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;sonar.projectVersion=1.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;sonar.sources=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;existsSrc&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;src&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;app&amp;#39;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;sonar.binaries=bin
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;sonar.host.url=http://xxx.你部署sonar的服务地址.com 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;sonar.login=admin
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;sonar.password=admin
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;sonar.sourceEncoding=UTF-8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 生成一个路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sPath&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cwd&lt;/span&gt;(), &lt;span style="color:#e6db74"&gt;&amp;#39;sonar-project.properties&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 写入sonar的配置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fs&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;writeFileSync&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;sPath&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;sonarProject&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 执行sonar的代码扫描,并且上传代码质量报告
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;shelljs&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;exec&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;sonar-scanner&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="执行jscpd分析代码重复率"&gt;执行jscpd分析代码重复率&lt;/h2&gt;
&lt;p&gt;尽管sonar已经提供了代码重复率的报告,但是并不是很容易看懂,到底代码哪里重复.
我们使用jscpd来分析项目的重复率.并且输出友好的报告.&lt;/p&gt;</description></item><item><title>持续集成 - 使用Gilab CI进行前端项目的持续集成</title><link>https://time-friend.com/zh/archive/continuous-integration-using-gitlab-ci-for-frontend-projects/</link><pubDate>Fri, 20 Sep 2019 23:15:00 +0000</pubDate><guid>https://time-friend.com/zh/archive/continuous-integration-using-gitlab-ci-for-frontend-projects/</guid><description>&lt;p&gt;市面上的持续集成平台有很多,今天介绍Gitlab的CI.&lt;/p&gt;
&lt;p&gt;从Gitlab 8.0开始,Gitlab CI 就集成在了Gitlab中.&lt;/p&gt;
&lt;p&gt;使用方法非常简单,只要我们在项目的根目录创建一个 &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;文件,添加一个Runner,就直接接入了Gitlab CI.&lt;/p&gt;
&lt;p&gt;接入方式非常的简单便捷.目前我们在前端脚手架中放一个&lt;code&gt;.gitlab-ci.yml&lt;/code&gt;文件,后续每一个前端项目都可以按照标准直接接入Gitlab CI.&lt;/p&gt;
&lt;h1 id="gitlab-runner"&gt;GitLab Runner&lt;/h1&gt;
&lt;p&gt;所有的Gitlab任务都会放在Gitlab Runner中执行.&lt;/p&gt;
&lt;p&gt;GitLab Runner的安装环境,根据你的需求而定,一个gitlab 可以注册的Runner是没有限制的.&lt;/p&gt;
&lt;p&gt;普通的前端项目直接安装在Linux中就可以了,如果是小程序或者RN这种项目,目前我是直接找了一台mac mini来安装Runner.&lt;/p&gt;
&lt;h2 id="gitlab-runner安装"&gt;GitLab Runner安装&lt;/h2&gt;
&lt;p&gt;安装Runner 非常简单, 这里晒出Gitlab的官方安装教程,你可以根据你的系统环境自行下载.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.gitlab.com/runner/install/"&gt;安装Gitlab Runner 官方文档&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="注册runner"&gt;注册Runner&lt;/h2&gt;
&lt;p&gt;Runner安装好之后,想要关联到你的Gitlab,需要注册Runner.&lt;/p&gt;
&lt;p&gt;这里给大家介绍群组的runner注册方式,个人项目的runner方式注册基本一致&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.gitlab.com/runner/register/"&gt;注册Gitlab Runner 官方文档&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;大致流程为:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开Gitlab网站,选择群组-&amp;gt; 设置-&amp;gt; CI/CD -&amp;gt; 展开Runner -&amp;gt; 你会看到注册Runner的Token与Url&lt;/li&gt;
&lt;li&gt;安装好Runner的机器上,运行 &lt;code&gt;sudo gitlab-runner register&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;输入 你Gitlab的 URL&lt;/li&gt;
&lt;li&gt;输入 Token&lt;/li&gt;
&lt;li&gt;输入 Runner 的名字&lt;/li&gt;
&lt;li&gt;选择 Runner 的类型,没有特殊需求直接选shell&lt;/li&gt;
&lt;li&gt;完成&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="配置runner"&gt;配置Runner&lt;/h2&gt;
&lt;p&gt;Runner的配置文件会以执行的用户身份不同而不同&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;当GitLab Runner以root身份执行时 &lt;code&gt;/etc/gitlab-runner/config.toml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;当GitLab Runner以非root身份执行时 &lt;code&gt;~/.gitlab-runner/config.toml&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="runner的全局配置"&gt;Runner的全局配置&lt;/h3&gt;
&lt;p&gt;这里我只说关键的两点&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;concurrent&lt;/code&gt; 配置会限制整个GitLab Runner能并发处理job的数量,如果你发现你的runner当前时间全局只能执行一个job的时候,
可以检查concurrent是否默认配置为1.不然多个job同一时段并发的时候,会造成job排队的现象.&lt;/p&gt;</description></item><item><title>一个两年前.gitattributes文件导致的bug</title><link>https://time-friend.com/zh/archive/gitattributes-bug-from-two-years-ago/</link><pubDate>Thu, 24 Jan 2019 19:33:33 +0000</pubDate><guid>https://time-friend.com/zh/archive/gitattributes-bug-from-two-years-ago/</guid><description>&lt;h1 id="起因"&gt;起因&lt;/h1&gt;
&lt;p&gt;一时兴起,我打开了我两年前写的一个前端项目开始代码审查.
这个项目我一个人写了两年,大概十几万行代码的样子.&lt;/p&gt;
&lt;p&gt;发现这个项目的git居然把所有的代码文件都识别成了二进制文件.
这个问题,之前困扰了我很久,却一直找不到原因.导致我的代码没有对比记录.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;再顽固的问题也有水落石出的一天&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;说巧不巧,今天偏偏找到了问题的源头.&lt;/p&gt;
&lt;h1 id="gitattributes"&gt;.gitattributes&lt;/h1&gt;
&lt;p&gt;最后发现是因为&lt;code&gt;.gitattributes&lt;/code&gt;文件有一行配置因为换行问题.导致所有text的文件都识别成了二进制文件.&lt;/p&gt;
&lt;h2 id="gitattributes的作用"&gt;.gitattributes的作用&lt;/h2&gt;
&lt;p&gt;.gitattributes文件是一个简单的text文本文件，它的作用是重新定义指定文件的属性, 指定非文本文件的对比合并方式&lt;/p&gt;
&lt;h3 id="编写规则"&gt;编写规则&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pattern attr1 attr2 ...
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="示例"&gt;示例&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;*.ttf binary
*.woff binary
*.eot binary
*.otf binary
* text=auto
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面这段代码表示,将一些字体文件指定为二进制文件,当提交代码的时候git不会diff这些文件的变动详情.
他只会告诉你,文件变动了,但是不会告诉你具体哪里变了.&lt;/p&gt;</description></item><item><title>Git大小写不敏感导致的烦人问题</title><link>https://time-friend.com/zh/archive/git-case-insensitive-issue/</link><pubDate>Wed, 09 Jan 2019 19:33:33 +0000</pubDate><guid>https://time-friend.com/zh/archive/git-case-insensitive-issue/</guid><description>&lt;blockquote&gt;
&lt;p&gt;因为同事把一个文件夹的小写改成了大写,导致我本地的提交不能直接push rebase 等一些列操作.恼的很~&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;error: The following untracked working tree files would be overwritten by checkout:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xxx.js
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Please move or remove them before you can switch branches.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Aborting
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="解决办法"&gt;解决办法&lt;/h1&gt;
&lt;p&gt;设置为大小写敏感(问题解决后,一定要还原配置)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git config core.ignorecase false
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;尽管设置大小写敏感之后,始终会影响其他分支的代码,所以不建议一直使用这个配置,当问题解决之后,还是要改回去.&lt;/p&gt;
&lt;h1 id="改回默认"&gt;改回默认&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git config core.ignorecase true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git config --unset core.ignorecase
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="尾巴"&gt;尾巴&lt;/h1&gt;
&lt;p&gt;平时编码的时候,还是千万不要直接重命名大小写,自己本地看起来没有什么问题.在别人问题上却是大问题.&lt;/p&gt;
&lt;p&gt;如果发生了类似问题的,应该在源头解决(谁机器上重命名的,谁改回去).如果不解决的,应该拖出去打~~&lt;/p&gt;</description></item><item><title>使用Travis CI自动化部署你的Hugo,Hexo博客</title><link>https://time-friend.com/zh/archive/automated-deployment-hugo-hexo-blog-with-travis-ci/</link><pubDate>Tue, 20 Nov 2018 16:14:25 +0000</pubDate><guid>https://time-friend.com/zh/archive/automated-deployment-hugo-hexo-blog-with-travis-ci/</guid><description>&lt;h1 id="travis-ci-是什么"&gt;Travis CI 是什么?&lt;/h1&gt;
&lt;p&gt;Travis CI 是在线托管的 CI 服务，用 Travis 来进行持续集成，不需要自己搭服务器。最重要的是，它对开源项目是免费的。
如果公司是用的是 gitlab,也有提供相应的持续集成服务.这里就过多赘述.&lt;/p&gt;
&lt;h1 id="travis-ci-配置文件"&gt;Travis CI 配置文件&lt;/h1&gt;
&lt;p&gt;Travis 要求项目的根目录下面，必须有一个&lt;code&gt;.travis.yml&lt;/code&gt;文件。&lt;/p&gt;
&lt;p&gt;当你的仓库有提交的时候,travis 会自动执行你下面配置的行为.&lt;/p&gt;
&lt;h1 id="travis-ci-的钩子与生命周期"&gt;Travis CI 的钩子与生命周期&lt;/h1&gt;
&lt;h2 id="travis-的钩子"&gt;Travis 的钩子&lt;/h2&gt;
&lt;p&gt;Travis 有不同的阶段,他提供了 7 个钩子。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;before_install：install 阶段之前执行&lt;/li&gt;
&lt;li&gt;before_script：script 阶段之前执行&lt;/li&gt;
&lt;li&gt;after_failure：script 阶段失败时执行&lt;/li&gt;
&lt;li&gt;after_success：script 阶段成功时执行&lt;/li&gt;
&lt;li&gt;before_deploy：deploy 步骤之前执行&lt;/li&gt;
&lt;li&gt;after_deploy：deploy 步骤之后执行&lt;/li&gt;
&lt;li&gt;after_script：script 阶段之后执行&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="生命周期"&gt;生命周期&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;before_install&lt;/li&gt;
&lt;li&gt;install&lt;/li&gt;
&lt;li&gt;before_script&lt;/li&gt;
&lt;li&gt;script&lt;/li&gt;
&lt;li&gt;aftersuccess or afterfailure&lt;/li&gt;
&lt;li&gt;[OPTIONAL] before_deploy&lt;/li&gt;
&lt;li&gt;[OPTIONAL] deploy&lt;/li&gt;
&lt;li&gt;[OPTIONAL] after_deploy&lt;/li&gt;
&lt;li&gt;after_script&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="travisyml"&gt;.travis.yml&lt;/h1&gt;
&lt;p&gt;下面是我的博客部署配置,也是我项目&lt;code&gt;.travis.yml&lt;/code&gt;文件的内容.&lt;/p&gt;
&lt;h2 id="hugo"&gt;hugo&lt;/h2&gt;
&lt;p&gt;这是我的 hugo 部署配置,仅供参考&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;language&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;node_js&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;node_js&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;10.13.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;install&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;wget https://github.com/gohugoio/hugo/releases/download/v0.51/hugo_0.51_Linux-64bit.deb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;sudo dpkg -i hugo*.deb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;hugo version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;rm -rf public&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;npm install&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;hugo --buildFuture&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;gulp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;echo &amp;#39;Build done!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;after_success&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;git config --global user.name &amp;#34;Fan&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;git config --global user.email &amp;#34;你的邮箱&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;git clone https://${ACCESS_TOKEN}@github.com/Num142857/alili.tech.git container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;rm -rf container/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;cp -r public/* container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;cd container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;git add .&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;git commit -m &amp;#39;Travis upate blog&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;git push -u origin gh-pages -f&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="hexo"&gt;Hexo&lt;/h2&gt;
&lt;p&gt;这是我的 hexo 部署配置,仅供参考.&lt;/p&gt;</description></item><item><title>Git删除所有提交记录解决方案</title><link>https://time-friend.com/zh/archive/git-delete-all-commits-solution/</link><pubDate>Tue, 30 Oct 2018 19:33:33 +0000</pubDate><guid>https://time-friend.com/zh/archive/git-delete-all-commits-solution/</guid><description>&lt;p&gt;如果你之前的项目提交了一些敏感数据,或者要清除以前提交的记录,给出下面解决方案.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 1. 检出一个新的分支&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git checkout --orphan latest_branch
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 2. 暂存所有文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git add -A
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 3. 提交刚刚暂存的文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git commit -am &lt;span style="color:#e6db74"&gt;&amp;#34;commit message&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 4. 删除最原始的分支&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git branch -D master
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 5. 重命名当的第分支&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git branch -m master
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 6. 提交你的记录到远程仓库&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push -f origin master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Git push卡住解决办法</title><link>https://time-friend.com/zh/archive/git-push-stuck-solution/</link><pubDate>Mon, 09 Apr 2018 19:33:33 +0000</pubDate><guid>https://time-friend.com/zh/archive/git-push-stuck-solution/</guid><description>&lt;p&gt;博客的每天英语是直接爬的扇贝英语,为了不直接请求代理接口(会相对比较慢).
所以每天我的程序每天会生成相应的数据文件,前端直接ajax获取就好了.
博客内容也会每天自动发布,达到每天更新名言名句的效果.
好久没管,发现很多git提交的内容没有push.手动直接push之后发现有800多个修改地方没有push.&lt;/p&gt;
&lt;p&gt;手动push的时候直接卡住了.
就像这样:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;master 9447645&lt;span style="color:#f92672"&gt;]&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; file changed, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; insertion&lt;span style="color:#f92672"&gt;(&lt;/span&gt;+&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Counting objects: 20, &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Compressing objects: 100% &lt;span style="color:#f92672"&gt;(&lt;/span&gt;876/876&lt;span style="color:#f92672"&gt;)&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Writing objects: 100% &lt;span style="color:#f92672"&gt;(&lt;/span&gt;876/876&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;网上找了个方法,解决了这个问题:
添加sendpack.sideband属性并置为false&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 全局的：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git config –global sendpack.sideband false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 仓库的：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git config –local sendpack.sideband false
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我只在我的本地仓库设置一下,然后再执行 &lt;code&gt;git push&lt;/code&gt;就成功了&lt;/p&gt;</description></item><item><title>Git系列之关于add命令的一些事</title><link>https://time-friend.com/zh/archive/git-series-about-add-command/</link><pubDate>Sun, 10 Sep 2017 19:33:33 +0000</pubDate><guid>https://time-friend.com/zh/archive/git-series-about-add-command/</guid><description>&lt;h2 id="基本用法"&gt;基本用法&lt;/h2&gt;
&lt;p&gt;通常是通过git add &lt;path&gt;的形式把&lt;path&gt;添加到索引库中，&lt;/p&gt;
&lt;p&gt;&lt;path&gt;可以是文件也可以是目录:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git add &amp;lt;path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果有很多改动,可以用以下命令来一次添加所有改变的文件:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; git add -A .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;将所有修改添加到暂存区,包括添加新文件和编辑过的文件不包括删除的文件:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ git add . 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;表示添加所有内容:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git add -A
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;表示添加编辑或者删除的文件，不包括新添加的文件:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git add -u
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果不小心执行了以下命令:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git add * -f(force) //添加被忽略的文件。
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;可以吃一个后悔药:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git reset HEAD
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>自动化部署前端代码 - grunt-ftp-deploy的使用</title><link>https://time-friend.com/zh/archive/automated-deployment-frontend-code-grunt-ftp-deploy/</link><pubDate>Sun, 14 Jun 2015 23:36:00 +0000</pubDate><guid>https://time-friend.com/zh/archive/automated-deployment-frontend-code-grunt-ftp-deploy/</guid><description>&lt;p&gt;每一次修改完代码之后,要部署到远程的服务器,我的操作步骤是:&lt;/p&gt;
&lt;p&gt;修改代码 &amp;ndash;&amp;gt; grunt build &amp;ndash;&amp;gt; 打开FileZilla &amp;ndash;&amp;gt;登录ftp服务器 &amp;ndash;&amp;gt;找到本地文件夹 &amp;ndash;&amp;gt; 找到远程服务器目标文件夹 &amp;ndash;&amp;gt;全选本地文件 &amp;ndash;&amp;gt; 上传&lt;/p&gt;
&lt;p&gt;因为部署代码,在某个时候会特别频繁.每一次都要重复上面的八个操作.表示要做点什么,改变一下.&lt;/p&gt;
&lt;p&gt;今天我们的主角:grunt-ftp-deploy&lt;/p&gt;
&lt;p&gt;如果是sftp可以使用grunt-sftp-deploy&lt;/p&gt;
&lt;p&gt;安装:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;npm install grunt-ftp-deploy --save-dev

or

npm install grunt-sftp-deploy --save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;!-- more --&gt;
&lt;p&gt;在与Gruntfile文件同一目录,我们新建一个&amp;quot;.ftppass&amp;quot;的文件,
里面是ftp的授权信息,
内容如下:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;key1&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;username&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;username&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Gruntfile配置代码:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//ftp-deploy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;grunt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;initConfig&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;ftp-deploy&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;build&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;auth&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;host&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;192.168.1.245&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;//ftp服务器的ip地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;port&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;,&lt;span style="color:#75715e"&gt;//服务器端口
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;authKey&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;key1&amp;#39;&lt;/span&gt;&lt;span style="color:#75715e"&gt;//.ftppass文件里,key1的授权信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;path/to/source/folder&amp;#39;&lt;/span&gt;,&lt;span style="color:#75715e"&gt;//本地文件夹
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;dest&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;/path/to/destination/folder&amp;#39;&lt;/span&gt;,&lt;span style="color:#75715e"&gt;//服务器的目标文件夹
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;exclusions&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;path/to/source/folder/**/.DS_Store&amp;#39;&lt;/span&gt;]&lt;span style="color:#75715e"&gt;//不上传的文件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//sftp-deploy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;grunt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;initConfig&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;sftp-deploy&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;build&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;auth&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;host&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;192.168.1.245&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;//ftp服务器的ip地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;port&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;,&lt;span style="color:#75715e"&gt;//服务器端口
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;authKey&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;key1&amp;#39;&lt;/span&gt;&lt;span style="color:#75715e"&gt;//.ftppass文件里,key1的授权信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cache&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;false&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;path/to/source/folder&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;//本地文件夹
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;dest&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;/path/to/destination/folder&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;//服务器的目标文件夹
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;serverSep&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;,&lt;span style="color:#75715e"&gt;//服务器的相对路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;localSep&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;,&lt;span style="color:#75715e"&gt;//本地的相对路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;concurrency&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;,&lt;span style="color:#75715e"&gt;//每次上传多少个文件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;progress&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; &lt;span style="color:#75715e"&gt;//是否显示进度条
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;加载task&lt;/p&gt;</description></item><item><title>烦人的AngularJS注解 - grunt-ng-annotate的使用</title><link>https://time-friend.com/zh/archive/annoying-angularjs-annotations-grunt-ng-annotate/</link><pubDate>Fri, 12 Jun 2015 23:15:00 +0000</pubDate><guid>https://time-friend.com/zh/archive/annoying-angularjs-annotations-grunt-ng-annotate/</guid><description>&lt;p&gt;angular加入了依赖注入&lt;/p&gt;
&lt;p&gt;编写代码的时候,大致的写法如下&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;controller&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;tempController&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;$scope&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;$http&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;$state&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;$timeout&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可是这样的代码,压缩后会造成一个问题.
函数的参数:$scope, $http, $state, $timeout会变成: a,b,c,d&lt;/p&gt;
&lt;p&gt;导致这个函数找不到需要注入的服务,因为每个参数的命名都是严格规定的.&lt;/p&gt;
&lt;p&gt;如下:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;controller&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;tempController&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;,&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;,&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;,&lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!-- more --&gt;
&lt;p&gt;为了解决这个问题,angular支持如下写法:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;controller&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;tempController&amp;#39;&lt;/span&gt;, [&lt;span style="color:#e6db74"&gt;&amp;#34;$scope&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;$http&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;$state&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;$timeout&amp;#34;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;$scope&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;$http&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;$state&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;$timeout&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;那么问题来了:&lt;/p&gt;
&lt;p&gt;每一次添加一个服务的时候,都需要写两遍.
每一次删除一个服务的时候,都需要删两遍.&lt;/p&gt;
&lt;p&gt;表示大大降低了变成的愉悦.&lt;/p&gt;
&lt;p&gt;那么我们怎么解决这个问题呢?&lt;/p&gt;
&lt;p&gt;今天的主角来了,那就是grunt-ng-annotate&lt;/p&gt;
&lt;p&gt;这是一个grunt的插件,当然在glup上也有.因为我的项目主要是用grunt写的.
那么这次主要讲grunt版本的ng-annotate.&lt;/p&gt;
&lt;p&gt;首先我们需要安装ng-annotate:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;npm install grunt-ng-annotate --save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在你的Gruntfile里运行这个插件:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;grunt.loadNpmTasks(&amp;#39;grunt-ng-annotate&amp;#39;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;配置代码:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-JavaScript" data-lang="JavaScript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;grunt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;initConfig&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ngAnnotate&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;dist&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;files&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;expand&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cwd&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;lt;%= yeoman.dist %&amp;gt;&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;//相对路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;**/*Controller.js&amp;#39;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;//需要匹配的文件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;dest&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;lt;%= yeoman.dist %&amp;gt;&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;//文件输出的路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;js代码在函数里加入 &amp;ldquo;ngInject&amp;rdquo;:&lt;/p&gt;</description></item></channel></rss>