精選

園丁的話

歡迎到叡揚第一次嘗試的部落格分享,這也是我們從鼓勵內部分享後邁出的另一大步。

不同於公司公開的官方文件或是網頁資料,這些部落格來自公司現在與過去的員工的個人意見 ── 它們表達我們在工作中智慧上的領悟與挫折,或是情感上的喜樂與哀愁。

繼續閱讀 “園丁的話”

Tutorial : Waypoint Landing Page

https://codepen.io/desbear96/pen/Gxrzry

課程目標

了解transition delay來創造進場動畫

透過Waypoint的js產生滾動過程中的動態效果

並再次強調zindex的應用來帶出hero image中的圖層順序

並於此次帶出inline-block垂直置中的實作方式

學前必備知識

  • position
  • z-index
  • background-size
  • transform basic
  • transition
  • margin:0 auto
  • clear both
  • float
  • inline-block
  • :before :after ( pseudo element )
  • Scss基礎 nest與variable

重點知識

  • waypoint.js
  • inline-block vertical align middle
  • scss nest selector and XXX &
  • transition delay

教學方式

  • 首先要先解釋inline-block創造垂直置中的條件與概念,將hgroup區塊安至於中間
  • 接著將花與方塊透過指定的大小安置進去
  • 而三段文字則透過after與before安置前後層圖片
  • 並透過variable指定高度順序運算
  • 透過animate &這樣的祖代選擇方式,製作在進場前的位置,讓animate抽走後可以依序展示出物件
  • 安置下方的section結構,安置inner創造中間區塊的置中並設定最大寬度限制
  • 教授透過float與set-left right的樣式名稱,讓原本一樣的結構可以依據樣式名稱置左置右
  • 透過雙層祖代選擇達到同前animate抽換後產生的動畫結構

素材

https://cl.ly/qIfb/hero-flower.png

https://cl.ly/qHo7/vintage.png

https://cl.ly/qHsB/vintage-up.png

https://cl.ly/qHcj/illustration-up.png

https://cl.ly/qHMB/illustration.png

https://cl.ly/qIV4/nature.png

jQuery(document).ready(function(){
jQuery(‘body’).imagesLoaded(function (){
jQuery(‘.os’).addClass(‘ready’);
function onScrollInit( items, trigger ) {
items.each( function() {
var osElement = jQuery(this)
var osTrigger = ( trigger ) ? trigger : osElement;
osTrigger.waypoint(function() {
osElement.removeClass(‘animate’);
},{
triggerOnce: true,
offset: ‘50%’
});
});
}
onScrollInit( jQuery(‘.os’) );
});
});

$bgC:#F3D5D7;

$color:#CE4D5A;

script(src=”https://cl.ly/q6Ke/jquery.min.js“)

script(src=”https://cl.ly/qI9e/imagesloaded.pkgd.min.js“)

script(src=”https://cl.ly/qI1b/jquery.waypoints.min.js“)

script(src=”https://cl.ly/qIja/inview.js“)

Tutorial : Pure CSS Modal

https://codepen.io/desbear96/pen/oqpwLO

課程目標

主要透過:target辦到讓有特定id之物件達到樣式變換的效果,並在此次了解absolute的位置的概念來產生tooltips,並創造滿版遮罩的概念,在tooltips中可以帶入三角形與透過transform讓物件置中的方式。

學前必備知識

  • box-modal
  • html basic
  • inline-block
  • :hover
  • margin:0 auto

重點知識

  • :target
  • position left top right bottom
  • text-align
  • css triangle
  • psedo element
  • transform:translate3d basic

教學方式

  • 先教導創造按鈕並解釋box-modal與inline-block
  • 透過body的text-align來讓按鈕置中
  • 創造a之中的tooltips結構
  • 並透過psedo element創造三角形的部分
  • 在解釋hover後讓子物件作指定除了自己以外的物件作樣式變換後
  • 進一步開始解釋target之用法
  • 先將modal card與overlayer創造出來
  • 將modal card隱藏
  • 將modal card用target設定樣式滑入
  • 創造關閉按鈕reset 網址列

注意

不要透過transform來將modal or card置中

OWASP ZAP 憑證安裝的方式(OWASP ZAP Certificate)

問題

透過 ZAP 去錄 https 時,如果沒有安裝憑證時,在 Browser 就會出現「 “Your connection is not private”, “你的連線並不安全”」的警告訊息,如下圖所示。
Chrome的警告

Firefox的警告

解法

為什麼會出現那個警告訊息呢? 因為 Browser 用的那個憑證已經不是原本連接的那個 host 的憑證,而變成了 OWASP Zed Attack Proxy Root CA 了哦! 而這個憑證並沒有被電腦 Trust 所以就會有那個警告訊息哦!
那要怎麼辦呢? 就是把憑證裝進去電腦的信任區。
以下我們就一步步來說明,

1.儲存 ZAP 憑證

開啟 OWASP ZAP ,Tools -> Options -> Dynamic SSL Certificates -> Save
儲存 ZAP 憑證

2.匯入 ZAP 憑證

DbClick剛才儲存的憑證檔,按下「Install Certificate…」,並將憑證存到「Trusted Root Certification Authorities」之中,如下,
Certificate Import Wizard

記得要將憑證存到「Trusted Root Certification Authorities」之中
存到「Trusted Root Certification Authorities」

最後按下 Finish 就可以了哦!
Import 完成

FIREFOX 匯入 ZAP 憑證

因為 firefox 憑證是自已管理的,所以 firefox 也要匯入 ZAP 憑證 ,如果會用 firefox 來錄的話,可以省略這步哦!
firefox 選項 -> 隱私權與安全性 (或在網址列輸入 about:preferences#privacy) -> 檢視憑證
隱私權與安全性

匯入 ZAP 憑證
匯入 ZAP 憑證

勾選「信任此憑證機構以識別網站」
勾選「信任此憑證機構以識別網站」

透過上述的方式,我們就可以錄 https 的網站,而不會一直出現警告訊息。 如果不會再錄的話,就請記得將 ZAP 的憑證移除哦!

Figure out and divide Angular module in project _Angular 切版實戰 part 2: 如何在 Angular 專案裡切模組

前情提要 (連載的概念)
距離上次發文(切分 shared feature)已經過了半年,我們的產品持續長大,光 shared feature 底下已經擁有40多支的元件,到處 import 到處 export。於是上週開始解決技術債,整理、重新分類 module 和元件們。

在講 Angular module 的構造前,不得不說寫了幾個月 Angular 後,才發現 Angular 處境有點尷尬。雖然是模仿了 React 的 component 概念,但 React 目前生態更活躍、元件更好寫,framework 方面 AngularJS 社群比較成熟,套件多,反觀 Angular 東找西找資源真的不多 (´・ω・`)。但凡走過才有收穫,部門也有 React 和 Vue 的開發者,剛好可以互相學習,取其所長,棄其所短。

之後目標是想辦法在擁有 Angular 框架的穩定下,又能學習 React 元件相依性降到最低、資料達成單一來源,不要讓 js 資料指來指去最後變成折騰人心肝的小妖精。之前被 js 傳遞資料全部用 pointer 的特性嚇到,趕快用 immutable 壓壓驚,不過資料流還沒理出頭緒阿 _(:3」ㄥ)_

Angular 成員

首先介紹 Angular 常用的成員:module、component、directive、service。

  • module:大致可視為需執行某特定任務的功能區塊
  • component:呈現在 html 中的元件
  • directive:可彈性綁在 Component 身上的功能需求
  • service:inject 後可執行的某功能需求
    app 以 app.module 為進入點開始運行之後,依照不同的頁面需求,可藉由切換 module 或是 import 不同的 module 來決定此頁面要載入多少資源來完成工作。module 層級最高,可載入 module 、定義 component、inject service 等等。以我們專案的 HomeModule(Home 畫面所需的模組)最初的版本為例:

@NgModule({
imports: [
ROUTES,
CommonModule,
],
declarations: [
HomeComponent,
HeaderComponent,
TooltipDirective, …
],
provider: [
SwitchAuthService, …
]
exports: [
]
})
export class HomeModule {}


Module 參數

參考 Angular 文件,各 module 設定參數可粗淺說明為:

  • imports:此模組需要載入的模組資源(只有 module 能被載入)
  • declarations :此模組使用到的 component、directive
  • providers:此模組使用到的 Service(子模組也一樣可使用,providers 作用域比較廣,不像 imports 的資源只有自己本身可使用。用起來感覺很像.…..新增一支 js 檔案?很神祕還不太清楚)
  • exports:此模組輸出的資源(意即:其他模組若載入此模組,能使用的所有資源),輸出的資源必須是 imports、declarations 裡面定義過的項目。
    一開始還對 module 沒什麼概念,這初版立刻受到挑戰,在 home 的子 module — DashboardModule (dashboard 頁面)試圖加入 TooltipDirective 的時候,得到了 Angular “xxx is part of the declarations of 2 modules” 的回應。Angular 規定 一個 component 只能附屬在一個 module 底下。所以為了讓不同模組可以共用元件,我們在第二版中創了個 SharedModule,包山包海 import 一堆 module 再 export 一堆 module、component、directive,每次有新頁面要使用共用元件,就只能 import 一大包 SharedModule,造成龐大負擔。於是切分 Module 是一定要的了。

切分 Module

在第三版中,切出了 UISharedModule(放置所有 UI 相關功能的模組):

@NgModule({
imports: [
CommonModule,
],
declarations: [
TooltipDirective,
PlaceholderComponent, …
],
provider: [
dialogService,
]
exports: [
TooltipDirective,
PlaceholderComponent, …
]
})
export class UISharedModule {}


還有 DataPipeModule、LayoutSharedModule 等等其他功能性的模組區塊,並整理出以下特性:

1. component / directive / pipe 等元件只能定義在一個 module 底下,因此只要有通用的元件,就要分類到某個 module 麾下,才能被多個 module 給 import 使用
2. exports 僅含 declaration 裡面的元件,儘量不要 export module,避免 module相依性、減輕 module 重量
3. Module 分越細,每個新頁面負擔越小,不會單一 import 就很重,但需要import的項目數量也會更多,需自行拿捏
其中第二點提到的 “不要 export module” 是因為避免在 import module 的時候,載入了非預期的 module。譬如之前因為 TagModule 與 TagSharedModule 常常被一起使用,初版長這樣:

@NgModule({
imports: [
TagSharedModule,
],
declarations: [
TagComponent,
],
exports: [
TagComponent,
TagSharedModule, …
]
})
export class TagModule {}


原本是方便載入 TagModule 時可以連 TagSharedModule 一起使用。但也會導致原本只想使用 TagComponent 的 module 被迫載入 TagSharedModule。所以即使兩者常常被一起使用,TagModule 也還是不要 exports TagSharedModule 才好,需要兩者的時候再分別 imports:

@NgModule({

imports: [
TagModule,
TagSharedModule, …
]
})
export class SomeModule {}


原本只是想寫一下上週辛苦的切分 module 甘苦談,結果居然變成很正經的分享了 (*´・д・)? 不得不說 Angaulr 這種分層架構,對一切講求扁平的 component 世代很不利,但對團隊開發與理解是有幫助的。只希望之後優化專案的過程,能找到更好的結合兩者好處的開發方法。

透過 WinDbg 來找出 ASP.NET CPU 100% ASP.NET 程式的問題

問題

我們有一個 ASP.NET 的系統部署到 IIS 上(Windows 2012, .NET 4.x),有時候會導致 w3wp.exe 吃掉所有的 CPU 資源,一直要等到應用程式回收後,程式再重新啟動後就正常了。這種狀況不定期會發生。

解法

我們可以使用 WinDbg 來找出導致 IIS CPU 100% 的原因,方法如下,

  • 透過「工作管理員」來「建立傾印檔案」
    當發生 IIS 導致 CPU 100% 時,開啟「工作管理員」,按右鍵選取「建立傾印檔案」。要依 Web 應用程式的平台(x86/x64)來開啟「工作管理員」(x86的工作管理員在 C:\Windows\SysWOW64\taskmgr.exe )。
  • 安裝 WinDbg
    請參考 Debugging Tools for Windows (WinDbg, KD, CDB, NTSD) 來安裝對應的版本。
  • 設定 Symbol Path
    先建立一個 C:\RTX64_SYMBOLS 目錄(依您自行定義),然後開啟 Command 設定 _NT_SYMBOL_PATH 的環境變數,如下,

    set _NT_SYMBOL_PATH=srv*C:\RTX64_SYMBOLS*https://msdl.microsoft.com/download/symbols

    set _NT_SYMBOL_PATH所以在 command 中,輸入 set 後,就可以看到 _NT_SYMBOL_PATH 的設定值哦,

    _NT_SYMBOL_PATH當然,如果常常會用到的話,就直接設定到 環境變數之前,下次 debug 時,就不用再設定一次了哦! 詳細請參考Set up your system to use Microsoft’s public Symbol Server

  • 在 WinDbg 中找問題
    • 載入 sos.dll
      WinDbg 有 x86/x64 的版本,我是使用 x64 的版本,所以 sos.dll 的路徑是 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll,您輸入如果發生錯誤的話,請使用 C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll 。
    • 設定 Symbol 檔目錄
      !sym noisy
      .cordll -ve -u -l
    • 透過 !runaway 顯示Threads所佔的時間
      輸入 !runaway 後,會顯示各 Thread 所花費的時間,花最多的會在最上面,如下圖,

      !runaway

      !runaway

    • 透過 ~[thread]s 切換到該 thread 的位置
      由上圖所示,Thread 40 佔最多時間,所以我們切到它的位罝去,

      ~40s

      ~40s

    • 透過 !clrstack 來查看呼叫堆疉
      !clrstack

      !clrstack從上圖可以發現,應該是有關 Dictionary 操作的問題,而它是由我們系統中 TemplateCfg.initial() 這個 Method 所引起的。

  • 檢視並調整程式碼
    開啟 TemplateCfg 程式碼,在 initial 這個 Method 之中會建立 Dictionary 物件,Clear 它,並 Insert 資料,但這些 Dictionary 的變數卻又設定成 static 。TemplateCfg.initial()即然這些 Dictionary 是 static 的,而且它們值又都是相同的,就沒有必要每次 request 時,就重新建立並 insert 這些資料。
    所以將 initial 裡面的 Code 搬到 static constructor 。
    調整完程式碼後,從去年觀察到目前,已經沒有再發生 CPU 100% 的狀況。

參考資料

Debugging in Production Part 1 – Analyzing 100% CPU Usage Using Windbg
WinDBG 應用實例:找出 ASP.NET CPU 100% 原因
Debugging Tools for Windows (WinDbg, KD, CDB, NTSD)
Set up your system to use Microsoft’s public Symbol Server
High CPU Hangs – 05
中小型研发团队架构实践:生产环境诊断利器WinDbg帮你快速分析异常情况Dump文件
Intro to WinDBG for .NET Developers
.NET Debugging Demos Lab 4: High CPU Hang – Review