前言:
瀏覽器會將從server下載回來的靜態檔案做快取,
好處是節省頻寬與資源,加快瀏覽速度。
壞處是需要針對存取資源做適當的快取配置,
讓client在瀏覽網頁的速度與資源的更新取得平衡。
作法:
除了更新資源檔案的檔名外,
一般都是從HTTP/1.1 header中的cache-control指令下手,
設定max-age(單位為秒數),讓browser定期跟server擷取資源,
不過各browser作法略有不同。
FireFox從第2次開始,會自行帶max-age=0給server,
Chrome不會自行帶max-age的指令,還是需server設定,
且需再增加no-cache指令,讓browser發request來重新驗證資源是否更新,
否則Chrome仍然使用local cache。
max-age雖然可讓browser定期擷取資源,但若資源內容沒有變動,
也沒有下載的必要,因此會搭配ETag指令:
server會依快取的檔案內容產出一字串,回應給browser,
之後browser送出request會夾帶If-None-Match指令,如果字串比對一致,
則回傳status code 304(表Not Modified),如下圖:
反之,若字串沒有match了,代表資源內容變更了,此時browser再重新擷取該資源即可。
建議font可善用CDN cache,分散又可降低server loading。
參考資料:
https://tools.ietf.org/html/rfc2616
https://tools.ietf.org/html/rfc7234
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching
https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Caching
https://medium.com/@codebyamir/a-web-developers-guide-to-browser-caching-cc41f3b73e7c
2020年1月31日 星期五
2019年12月1日 星期日
[Design Pattern] 策略模式(Strategy Pattern) in C#
前言:
一年前在實作資料處理程式時,不經意的用到該模式,
其實策略模式就是一種Dependency Injection的簡單例子,
因此,實務上很容易使用到。
說明:
類別圖如下:
可以看到Calculator是依賴ICal這個介面,
而實作ICal的類別,就是實作所謂的策略,
例如,將公分數值轉成公尺。
而Calculator可選擇要使用哪個策略,就可得到計算後的結果。
簡單實作如下:
一年前在實作資料處理程式時,不經意的用到該模式,
其實策略模式就是一種Dependency Injection的簡單例子,
因此,實務上很容易使用到。
說明:
類別圖如下:
可以看到Calculator是依賴ICal這個介面,
而實作ICal的類別,就是實作所謂的策略,
例如,將公分數值轉成公尺。
而Calculator可選擇要使用哪個策略,就可得到計算後的結果。
簡單實作如下:
但上面的做法,還可以再改善,將選擇策略的部分移到CalContext,
在建構CalContext時,傳入策略的名稱,就能在GetResult方法內再建立具體策略,
讓外部使用者操作更簡化,如下圖。
2019年9月17日 星期二
[Visual Studio] Console程式建立app.Release.config與app.Debug.config
前言:
使用Visual Studio(VS)開發Web Application,會有Web.config的設定檔,
預設會有Web.Debug.config與Web.Release.config來做組態管理,
但主控台專案的app.config預設卻沒有??
作法1:
● 在csproj專案上右鍵->卸載專案->編輯xxx.csproj
打開專案檔後,通常就可看到PropertyGroup的element,
在這群element附近(通常在之後)貼上:
<PropertyGroup>
<ProjectConfigFileName>App.config</ProjectConfigFileName>
</PropertyGroup>
如:
● 接著往下找到ItemGroup的element,會有如下的設定,
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
在上述的<None Include="App.config" />下加入:
<None Include="App.Debug.config">
<DependentUpon>App.config</DependentUpon>
</None>
<None Include="App.Release.config">
<DependentUpon>App.config</DependentUpon>
</None>
如:
●然後在<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />下方加入:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" />
<Target Name="AfterBuild">
<TransformXml Source="@(AppConfigWithTargetPath)" Transform="$(ProjectConfigTransformFileName)" Destination="@(AppConfigWithTargetPath->'$(OutDir)%(TargetPath)')" />
</Target>
如:
●重新載入專案後,在專案上右鍵->加入->新增項目->加入App.Debug.config/App.Release.config
● 最後,在各自組態設定檔中加入欲轉換的設定。
<applicationSettings>
<Project.Properties.Settings>
<setting name="key" serializeAs="String" xdt:Transform="Replace">
<value>value</value>
</setting>
</Project.Properties.Settings>
</applicationSettings>
或
<appSettings>
<add key="key" value="value" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
</appSettings>
作法2:
使用Configuration Transform,免除上述手動的作法,
方便快速又支援轉換預覽。操作部分可以參考該網址的說明。
參考資料:
https://demo.tc/post/775
https://marketplace.visualstudio.com/items?itemName=GolanAvraham.ConfigurationTransform
使用Visual Studio(VS)開發Web Application,會有Web.config的設定檔,
預設會有Web.Debug.config與Web.Release.config來做組態管理,
但主控台專案的app.config預設卻沒有??
作法1:
● 在csproj專案上右鍵->卸載專案->編輯xxx.csproj
打開專案檔後,通常就可看到PropertyGroup的element,
在這群element附近(通常在之後)貼上:
<PropertyGroup>
<ProjectConfigFileName>App.config</ProjectConfigFileName>
</PropertyGroup>
如:
● 接著往下找到ItemGroup的element,會有如下的設定,
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
在上述的<None Include="App.config" />下加入:
<None Include="App.Debug.config">
<DependentUpon>App.config</DependentUpon>
</None>
<None Include="App.Release.config">
<DependentUpon>App.config</DependentUpon>
</None>
如:
●然後在<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />下方加入:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" />
<Target Name="AfterBuild">
<TransformXml Source="@(AppConfigWithTargetPath)" Transform="$(ProjectConfigTransformFileName)" Destination="@(AppConfigWithTargetPath->'$(OutDir)%(TargetPath)')" />
</Target>
如:
●重新載入專案後,在專案上右鍵->加入->新增項目->加入App.Debug.config/App.Release.config
● 最後,在各自組態設定檔中加入欲轉換的設定。
<applicationSettings>
<Project.Properties.Settings>
<setting name="key" serializeAs="String" xdt:Transform="Replace">
<value>value</value>
</setting>
</Project.Properties.Settings>
</applicationSettings>
或
<appSettings>
<add key="key" value="value" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
</appSettings>
作法2:
使用Configuration Transform,免除上述手動的作法,
方便快速又支援轉換預覽。操作部分可以參考該網址的說明。
參考資料:
https://demo.tc/post/775
https://marketplace.visualstudio.com/items?itemName=GolanAvraham.ConfigurationTransform
2019年8月5日 星期一
[Design Pattern] 範本模式(Template Pattern)
前言:
以前看到範本模式的介紹時,心裡有一個疑問,
看起來就是衍生類別繼承基底類別,為何算一個模式?
直到有一次寫程式不經意用到範本模式,才恍然大悟,
範本不是單純繼承,而是定義好流程,細節留待衍生類別去定義。
說明:
簡單的類別圖如下:
BaseClass就是所謂的範本,定義了Main(),Main()則會執行Start()->Detail()->End(),
其中Start()是private方法,Detail()是abstract方法,讓繼承的類別去實作,
而End()是virtual方法,意即由衍生類別自己決定是否覆寫。
以前看到範本模式的介紹時,心裡有一個疑問,
看起來就是衍生類別繼承基底類別,為何算一個模式?
直到有一次寫程式不經意用到範本模式,才恍然大悟,
範本不是單純繼承,而是定義好流程,細節留待衍生類別去定義。
說明:
簡單的類別圖如下:
BaseClass就是所謂的範本,定義了Main(),Main()則會執行Start()->Detail()->End(),
其中Start()是private方法,Detail()是abstract方法,讓繼承的類別去實作,
而End()是virtual方法,意即由衍生類別自己決定是否覆寫。
2019年6月23日 星期日
[Angular] 建立第一個Angular專案(Windows環境)
前言:
Windows環境下從無到有建立第一個Angular專案的紀錄。
步驟:
● 下載nodejs並安裝,為啥要下載nodejs?
因為需要裡面的NPM(Node Package Manager)套件管理工具,
連至nodejs官網,選擇LTS(Long Term Support)版本下載安裝,目前LTS版本為10.16.0。
● 安裝好nodejs後,打開命令提示字元,輸入node -v,安裝成功會顯示nodejs的版本,
再輸入npm -v確認一下:
● 接著要透過NPM安裝Angular CLI,Angular CLI提供很多指令,讓developer開發Angular application更方便快速:
● 打指令:npm install -g @angular/cli,會問是否分享使用資料給Google的Angular team:
● 安裝結束後,一樣下指令ng v,若出現下圖就沒問題了:
● 接著來建立第一個Angular專案吧,切換好目標目錄後,
打指令:ng new(或n) <name> [options],name為專案名稱,options則是選擇性的設定,
這個指令會產生新的workspace與default project。不過安裝一開始,CLI就問了:
● 簡單講一下建立了那些檔案:
參考資料:
https://nodejs.org/en/
https://cli.angular.io/
https://angular.io/guide/file-structure
https://ithelp.ithome.com.tw/articles/10203185
https://jonny-huang.github.io/angular/training/01_creating_first_project/
Windows環境下從無到有建立第一個Angular專案的紀錄。
步驟:
● 下載nodejs並安裝,為啥要下載nodejs?
因為需要裡面的NPM(Node Package Manager)套件管理工具,
連至nodejs官網,選擇LTS(Long Term Support)版本下載安裝,目前LTS版本為10.16.0。
● 安裝好nodejs後,打開命令提示字元,輸入node -v,安裝成功會顯示nodejs的版本,
再輸入npm -v確認一下:
● 打指令:npm install -g @angular/cli,會問是否分享使用資料給Google的Angular team:
● 安裝結束後,一樣下指令ng v,若出現下圖就沒問題了:
● 接著來建立第一個Angular專案吧,切換好目標目錄後,
打指令:ng new(或n) <name> [options],name為專案名稱,options則是選擇性的設定,
這個指令會產生新的workspace與default project。不過安裝一開始,CLI就問了:
- Would you like to add Angular routing? 可選No(default值)
- Which stylesheet format would you like to user? 可選CSS(default值)
● 簡單講一下建立了那些檔案:
- angular.json:預設的CLI組態,提供CLI在建置、服務或測試專案所使用的設定。
- package.json:npm管理套件用。
- README.md:如大家所知,就是預設專案的說明檔。
- tsconfig.json:預設TypeScript組態。
- tslint.json:預設TSLint(linter for TS)組態。
● 建立完成後,cd到專案下,打指令:ng serve,就會開始建置專案並開啟server,
● 本來以為會自動開啟瀏覽器並開好網頁,不過應該是VS用太久,讓我有錯覺...請自行打開瀏覽器並貼上http://localhost:4200/:
● 本來以為會自動開啟瀏覽器並開好網頁,不過應該是VS用太久,讓我有錯覺...請自行打開瀏覽器並貼上http://localhost:4200/:
參考資料:
https://nodejs.org/en/
https://cli.angular.io/
https://angular.io/guide/file-structure
https://ithelp.ithome.com.tw/articles/10203185
https://jonny-huang.github.io/angular/training/01_creating_first_project/
2019年5月24日 星期五
[.Net] 如何複製instance(deep clone)/Prototype Pattern(原型模式)
前言:
有時候需要將物件instance複製出來,
.Net有提供ICloneable介面,以實作複製的方法(實作Clone方法):
而object有提供一擴充方法MemberwiseClone,以執行淺層複製(shallow copy),
但通常要的不是淺層複製,因reference type會指向同一塊heap,
因此若需要完全獨立的instance,就要自己實作。
作法:
1. 自行回傳新建立的instance:
若物件屬性可在建構子就完全決定的話,直接回傳新的instance即可:
不過通常沒這麼簡單,因此可先呼叫MemberwiseClone得到淺層複製,
再自行建立其他reference type屬性的instance:
不過如果物件屬性很多、很複雜又很多層,可考慮下一個做法。
2. 使用Json的Serialize與Deserialize:
不過作法2的執行時間應該比作法1長?? 實際測試一下:
各執行5次,作法2執行時間都在7秒上下,而作法1只要140毫秒,
因此2種作法各有所長,看狀況使用了。
參考資料:
https://docs.microsoft.com/zh-tw/dotnet/api/system.icloneable?view=netframework-4.8
https://docs.microsoft.com/zh-tw/dotnet/api/system.object.memberwiseclone?view=netframework-4.8#System_Object_MemberwiseClone
https://stackoverflow.com/questions/78536/deep-cloning-objects
有時候需要將物件instance複製出來,
.Net有提供ICloneable介面,以實作複製的方法(實作Clone方法):
而object有提供一擴充方法MemberwiseClone,以執行淺層複製(shallow copy),
但通常要的不是淺層複製,因reference type會指向同一塊heap,
因此若需要完全獨立的instance,就要自己實作。
作法:
1. 自行回傳新建立的instance:
若物件屬性可在建構子就完全決定的話,直接回傳新的instance即可:
不過通常沒這麼簡單,因此可先呼叫MemberwiseClone得到淺層複製,
再自行建立其他reference type屬性的instance:
不過如果物件屬性很多、很複雜又很多層,可考慮下一個做法。
2. 使用Json的Serialize與Deserialize:
不過作法2的執行時間應該比作法1長?? 實際測試一下:
各執行5次,作法2執行時間都在7秒上下,而作法1只要140毫秒,
因此2種作法各有所長,看狀況使用了。
參考資料:
https://docs.microsoft.com/zh-tw/dotnet/api/system.icloneable?view=netframework-4.8
https://docs.microsoft.com/zh-tw/dotnet/api/system.object.memberwiseclone?view=netframework-4.8#System_Object_MemberwiseClone
https://stackoverflow.com/questions/78536/deep-cloning-objects
2019年4月27日 星期六
[CSS] 手機版chrome背景圖(backgroun-size: cover)無法正常顯示
在html上使用background-image與background-size為cover設計全背景:
桌機上測試正常,但使用Android手機上Chrome直向瀏覽時,背景圖無法延伸至底部,
如下圖:
橫向瀏覽則正常,測試了一下,發現:
● background-size: cover:背景圖在mobile chrome就無法延伸至底部。
● background-attachment: fixed:在mobile chrome沒有生效。
google了一下,發現這似乎是mobile chrome的bug??
但直到目前,該問題依然存在,
常用的workaround是指定html的height為100%,如下圖:
測試結果如下圖:
參考資料:
https://support.google.com/chrome/forum/AAAAP1KN0B0l6BF3W0rymo/?hl=en&gpf=%23!topic%2Fchrome%2Fl6BF3W0rymo
https://issuetracker.google.com/issues/36908439
https://bugs.chromium.org/p/chromium/issues/detail?id=344338
https://css-tricks.com/perfect-full-page-background-image/
桌機上測試正常,但使用Android手機上Chrome直向瀏覽時,背景圖無法延伸至底部,
如下圖:
橫向瀏覽則正常,測試了一下,發現:
● background-size: cover:背景圖在mobile chrome就無法延伸至底部。
● background-attachment: fixed:在mobile chrome沒有生效。
google了一下,發現這似乎是mobile chrome的bug??
但直到目前,該問題依然存在,
常用的workaround是指定html的height為100%,如下圖:
測試結果如下圖:
參考資料:
https://support.google.com/chrome/forum/AAAAP1KN0B0l6BF3W0rymo/?hl=en&gpf=%23!topic%2Fchrome%2Fl6BF3W0rymo
https://issuetracker.google.com/issues/36908439
https://bugs.chromium.org/p/chromium/issues/detail?id=344338
https://css-tricks.com/perfect-full-page-background-image/
訂閱:
文章 (Atom)































