星期五, 8月 25, 2017

加了 gzip 以後,mp3 檔案無法播放

自從 server 加上了 gzip 處理後,前端頁面的音效 mp3 就出不來了(後來才發現是 gzip 的問題)...

播放時,console 會出現:
Failed to load resource: net::ERR_CONTENT_DECODING_FAILED

看一下 Network,也有帶驚嘆符號的「Provisional headers are shown」字樣


看了一堆文章後,發現跟 gzip 有關,所以去 AWS S3 把 gzip 的 Metadata 拿掉


結果沒用... @@

最後是直接把這個檔案刪除,重新上傳一個沒有 Content-Encoding: gzip 的 mp3 檔案,才解決了這個問題。

星期四, 3月 30, 2017

[Angular] App 是如何開始載入與運行的(進入點)

Angular (2.x/4.x) 入口:main.ts → 透過 bootstrapModule 把 AppModule 綁進來

app.module.ts 裡頭透過 bootstrap array,告訴 angular 有多少 components 要被用到。由於 index.html 裡頭不會引入其他 html 或 css 等資訊,那 angular 是如何知道去哪裡找這些資源?就是透過這個 NgModule 的 declarations,告訴 angular 我們需要用到哪些 components。

其中 app.component.ts 就會定義 Component 的 selector 名稱、html template、css 等內容

星期四, 10月 06, 2016

Google App Engine 使用 requests 時遇到 "no module named requests" 錯誤

開發 Google App Engine 應用,使用 requests 來發 RESTFul API 時,遇到了 "no module named requests" 錯誤。網路上一堆文章都是教你如何利用 pip 或 easy_install 來安裝 requests 模組。但是我還是持續看到同樣的錯誤訊息。

後來看到這篇 Stackoverflow 的回文指出:

Adding Third Party Python Libraries

You can include third party Python libraries with your application by putting the code in your application directory. If you make a symbolic link to a module's directory in your application directory, appcfg.py will follow the link and include the module in your app.

The Python module include path includes your application's root directory (the directory containing the app.yaml file). Modules you create in your application's root directory are available using a path from the root. Don't forget to create__init__.py files in sub-directories, so Python will recognize the sub-directories as packages.

大致上是說任何第三方模組,都必須放在應用的根目錄(跟 app.yaml 相同目錄)裡,但這樣一來,整個目錄就都是第三方模組的檔案夾,會非常雜亂。所以這時候可以參考 GAE 文件的建議
  1. 建立一個資料夾「lib」,把第三方模組都放在這裡面。
  2. 新增一個檔案 appengine_config.py,裡頭寫入:
from google.appengine.ext import vendor
# Add any libraries installed in the "lib" folder.
vendor.add('lib')

這樣子就能夠把 requests 這個模組放到這個資料夾裡。如果懶得新增模組,也可以建立一個 symbolic link 指向 python 的 package 目錄就可以了。


星期三, 9月 09, 2015

不只人帥,連字都帥氣的英俊體

昨天睡前滑了一下臉書,才知道 Justfont 眾籌大爆發這個事件,昨晚看到已經超標達百萬級,剛剛一看不得了,居然已經衝破千萬!?真是太優秀了!(募資活動網頁:金萱,新時代中文字型,培育新鮮台灣文字風景

這讓我想起了 2014 年 Justfont 剛好在父親節前推出了訂製手寫字服務,我馬上購買了一份當作父親生日禮物。(原本沒趕上限量優惠的活動期限,但剛好在某創業活動遇到了創辦人 Michael,跟他拿到了優惠名額!)

因為父親的字型很有特色,我當初在社團畫海報、寫 POP和毛筆字,受他影響很多,但就是沒辦法寫出他字體那種瀟灑與氣勢。過去我陸陸續續有找過自製字體的相關工具與方法,甚至還寫信去問過 Justfont 的朋友,但後來還是沒有試成功...

星期二, 9月 01, 2015

JBC 晚宴紀錄暨 Indiana's Blog 回顧文

昨晚參加了 Jamie 的 JBC (Jamie's Blogging Challenge) Thank You Dinner,一下子化身成為部落客了... 雖說好像寫了部落格就是部落客,但總覺得「部落客」這個稱號是指那些產出文章質量更高、關注者更多的作者。沒想到當時只是回應一下 Jamie 的貼文,竟獲得了正式的邀約!結果昨晚在場的大都是正港的優質部落客,這頓飯吃得還真是不好意思... :p (後來大家都在強調自己部落格 SEO 的成績,想當初我的 前十字韌帶復健系列 推出時,Google 輸入「前十字韌帶」的搜尋結果也是前三... 哈,這樣可以嗎?^^)
沒想到自己的 151 篇網誌能換來一頓台北寒舍艾麗 la Farfalla 義式餐廳晚宴

昨晚的聚會,大家除了自我介紹外,也規定要說一下近來最驕傲、最值得分享的一件事,以及最不想讓人知道的事。最不想讓人知道的事情,就不多說了(也許以後有機會在 Startup 系列 再多做分享)。至於最值得驕傲的事情,我仔細回想,其實這一路走來的創業歷程,也真的是跟部落格有關...

星期三, 1月 14, 2015

Sublime Text Plugin "AutoBackups"

唉... 杯具了... 沒有把 Git 弄熟,只會基本的 clone, pull, commit, push和一點 branch... 每次寫程式都感覺要寫到一個程度才 commit + push,沒有養成經常在 local commit 的習慣。結果因為手殘誤在某個 bower_components package 裡,下了 git reset --hard HEAD^ 把兩天的成果都給輕乾淨了...

至於為什麼會這麼搞,說來話長。總之痛過一次就學乖了... 不過,為了避免將來有其他耍笨的時候,還是裝了 Sublime Text 的自動備份 plugin「AutoBackups」。他可以在每次存檔的時候幫忙建立備份,備份資料的資料夾會以日期命名(yyyy-MM-DD),檔案名稱則是會自動加上時間(filename_HHmmss),所以可以回溯到每次存檔的階段。如果怕檔案累積量太大,也可以設定保留的時間(比方30天後自動刪除)。初步用起來感覺還不錯,推薦給各位試試。

星期二, 1月 06, 2015

Sublime Text 3 在 html tag pair 快速來回跳動 (go to matching pair)


  1. 安裝 Emmet package for Sublime Text
  2. 重新開啟 Sublime Text
  3. 就可以在任何 html tag 上使用快速鍵找到結束位置:
    • CTRL+ALT+J (Linux / Windows)
    • CTRL+SHIFT+T (OSX)

星期三, 10月 01, 2014

[Gulp] html 裡 include 的是 css 檔案,為什麼我們修改 scss 檔案,能夠即時修改輸出結果?而且在 watch 模式下還是把輸出檔案暫存在 .tmp 目錄下??

主要是跟 styles, watch, connect 這幾個 task 有關:

在 styles task 裡,我們先設定要針對哪些 scss 檔案作轉換處理;然後輸出到 .tmp/styles 目錄下
// scss files
var scss_files = [
  // 'app/styles/main.scss',
  'app/styles/**/*.scss',
  // smartadmin common_assets
  'COMMON_ASSETS/SASS_FILES/scss/bootstrap.scss',
  'COMMON_ASSETS/SASS_FILES/scss/smartadmin-production.scss',
  'COMMON_ASSETS/SASS_FILES/scss/library/fontawesome/font-awesome.scss',
  'COMMON_ASSETS/SASS_FILES/scss/smartadmin-skins.scss',
  'COMMON_ASSETS/SASS_FILES/scss/smartadmin-skins.scss'
];
gulp.task('styles', function () {
  return gulp.src(scss_files)
    .pipe($.rubySass({
        style: 'expanded',
        precision: 10
    }))
    .pipe($.autoprefixer('last 1 version'))
    .pipe(gulp.dest('.tmp/styles'))
    .pipe($.size());
});

在 watch task 自動載入下,指定要監看哪些檔案,並做出哪些相對應動作(這裡是利用 dependency 聯動 task 的方式)
gulp.task('watch', ['connect', 'serve'], function () {
    var server = $.livereload();
    // watch for changes
    gulp.watch([
        'app/*.html',
        '.tmp/styles/**/*.css',
        'app/scripts/**/*.js',
        'app/images/**/*'
    ]).on('change', function (file) {
        server.changed(file.path);
    });
    gulp.watch('app/styles/**/*.scss', ['styles']);
    gulp.watch('app/scripts/**/*.js', ['scripts']);
    gulp.watch('app/images/**/*', ['images']);
    gulp.watch('bower.json', ['wiredep']);
});

那放在 .tmp/styles 的檔案,如何能讓 html 連結到?html 裡頭寫的是 <link rel="stylesheet" type="text/css" media="screen" href="styles/main.css">?

這是因為 watch 的 dependency 裡有 connect task。在啟動 server 時,利用 connect.static 來指定「靜態文件服務器的路徑」,也就是 html 裡用到的所有相對路徑的根目錄。這裡預設了兩個靜態文件目錄,一個是 app,另外一個是 .tmp。所以如果我們需要找到 styles/main.css,系統會先去找 app/styles/main.css 是否存在,如果沒有,才會去找 .tmp/styles/main.css。
gulp.task('connect', function () {
    var connect = require('connect');
    var app = connect()
        .use(require('connect-livereload')({ port: 35729 }))
        .use(connect.static('app'))
        .use(connect.static('.tmp'))
        .use(connect.directory('app'));
    require('http').createServer(app)
        .listen(9000)
        .on('listening', function () {
            console.log('Started connect web server on http://localhost:9000');
        });
});

星期二, 9月 30, 2014

[Gulp] 輸出檔案(dest)的資料夾結構保持跟來源檔案(src)一致

gulp 針對某目錄下的所有檔案處理後,如果要能根據目錄結構輸出到另一個目錄,記得要指定 {‘base’: 來源根目錄}:

https://github.com/gulpjs/gulp/blob/master/docs/API.md#optionsbase

// without the 'base' set
gulp.src('app/**/*.scss')        //          file: 'app/css/somefile.scss'
  .pipe(gulp.dest('build'));      //->   file base: 'app/css'
                                              // relative path: 'somefile.scss'
                                              //    write path: 'build/somefile.scss'

// with the 'base' set
var glob = 'app/**/*.scss';
gulp.src(glob, { base: 'app' })  //          file: 'app/css/somefile.scss'
  .pipe(gulp.dest('build'));        //->   file base: 'app'
                                                // relative path: 'css/somefile.scss'
                                                //    write path: 'build/css/somefile.scss'

星期四, 9月 11, 2014

[Gulp 問題] “Possibly unhandled Error: path should be string...” when gulp build

不知怎搞的,才剛 build 沒事,緊接著改了無關緊要的 code,就出現了如下的錯誤訊息:
indiana@indiana-dt:.../program/web/my-project$ gulp build
[10:52:54] Using gulpfile ~/program/web/my-project/gulpfile.js
[10:52:54] Starting 'styles'...
[10:52:54] Starting 'scripts'...
[10:52:54] Starting 'images'...
[10:52:54] Starting 'fonts'...
[10:52:55] Starting 'extras'...
[10:52:55] Starting 'move'...
/home/indiana/program/web/my-project/app/scripts/facebook.js
  line 46  col 9   'alert' is not defined.
  line 63  col 50  'params' is defined but never used.
  line 82  col 52  'widget' is defined but never used.
  line 82  col 46  'href' is defined but never used.
✖ 4 problems
Possibly unhandled Error: path should be string
    at File.Object.defineProperty.set (/home/indiana/program/web/my-project/node_modules/gulp/node_modules/vinyl-fs/node_modules/vinyl/index.js:166:41)
    at Function.assign (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/lodash-node/modern/objects/assign.js:63:21)
    at /home/indiana/program/web/my-project/node_modules/gulp-cache/lib/TaskProxy.js:20:19
    at tryCatch1 (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/util.js:64:19)
    at Promise$_callHandler [as _callHandler] (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/promise.js:708:13)
    at Promise$_settlePromiseFromHandler [as _settlePromiseFromHandler] (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/promise.js:724:18)
    at Promise$_settlePromiseAt [as _settlePromiseAt] (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/promise.js:896:14)
    at Promise$_fulfillPromises [as _fulfillPromises] (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/promise.js:1041:14)
    at Async$_consumeFunctionBuffer [as _consumeFunctionBuffer] (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/async.js:64:12)
    at Async$consumeFunctionBuffer (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/async.js:37:14)
Possibly unhandled Error: path should be string
    at File.Object.defineProperty.set (/home/indiana/program/web/my-project/node_modules/gulp/node_modules/vinyl-fs/node_modules/vinyl/index.js:166:41)
    at Function.assign (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/lodash-node/modern/objects/assign.js:63:21)
    at /home/indiana/program/web/my-project/node_modules/gulp-cache/lib/TaskProxy.js:20:19
    at tryCatch1 (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/util.js:64:19)
    at Promise$_callHandler [as _callHandler] (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/promise.js:708:13)
    at Promise$_settlePromiseFromHandler [as _settlePromiseFromHandler] (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/promise.js:724:18)
    at Promise$_settlePromiseAt [as _settlePromiseAt] (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/promise.js:896:14)
    at Promise$_fulfillPromises [as _fulfillPromises] (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/promise.js:1041:14)
    at Async$_consumeFunctionBuffer [as _consumeFunctionBuffer] (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/async.js:64:12)
    at Async$consumeFunctionBuffer (/home/indiana/program/web/my-project/node_modules/gulp-cache/node_modules/bluebird/js/main/async.js:37:14)

[10:52:55] gulp-size: total 19.5 kB
[10:52:55] Finished 'scripts' after 864 ms
[10:52:55] Finished 'move' after 234 ms
[10:52:55] gulp-size: total 699.12 kB
[10:52:55] Finished 'fonts' after 421 ms
[10:52:55] Finished 'extras' after 258 ms
npm WARN package.json wifi@0.0.0 No description
npm WARN package.json wifi@0.0.0 No repository field.
npm WARN package.json wifi@0.0.0 No README data
[10:52:56] gulp-size: total 130.39 kB
[10:52:56] Finished 'styles' after 2.24 s
[10:52:56] Starting 'html'...
[10:53:15] gulp-size: total 2.08 MB
[10:53:15] Finished 'html' after 19 s
indiana@indiana-dt:.../program/web/my-project$ 

參考文件: https://github.com/jgable/gulp-cache/issues/24

星期六, 8月 30, 2014

[Gulp 問題] Task ‘fonts’ with package ‘gulp-bower-files’ miss some .eot,svg,ttf,woff files

gulp build 時,task ‘fonts’ 應該會透過 package ‘gulp-bower-files’ 的指令 bowerFiles 掃描所有 bower_components 下所有的檔案,並把附檔名為 **/*.{eot,svg,ttf,woff} 的檔案全都複製到 dist/fonts 下才對。但不知道為什麼只有 copy 了 bootstrap-sass-official 下的,卻漏掉 components-font-awesome 下的,造成錯誤。

參考文件: https://github.com/yeoman/generator-gulp-webapp/issues/71#issuecomment-40327323

星期一, 8月 25, 2014

Sublime Text 3 中文輸入問題

Sublime Text 很好用,但是我一直受無法中文輸入所苦。之前想說算了,就強迫自己盡量都用英文,但是現在要搞多國語系,不能輸入中文就麻煩了。所以還是想辦法把他搞定...

星期一, 6月 02, 2014

支線故事

在生命旅途中,你是否也有某幾個時期,因為某些事情而結識的朋友?這些朋友因為各自生活重心的轉移,彼此慢慢地失去了聯繫?彷彿是生命中的支線故事一般,在之後的某個時間點,因為某些人、事、物,讓你有機會回想起,甚至是再次與這些朋友聚在一起,過去的回憶大量湧入心頭,看著眼前既熟悉又陌生的友人,內心激動地很想跟他們說些什麼,卻又什麼都說不出口?

星期四, 8月 22, 2013

Sublime Text 2 + Emmet plugin

雖然看夥伴們用 vim 用得出神入化,但我實在是用不慣,所以還是回去用 sublime Text 2...

最近才知道有 Emmet 這個好用的工具,能在編輯 html 時方便許多。在此分享一下安裝 plugin 的方法。(參考自:原文連結

星期日, 10月 07, 2012

「珍妮鳥生活」演出心得

人只會越來越忙,「等我有空」的那天,可能永遠不會出現...


演出結束了,看著演員們的親友團成群地送花、拍照留念,上上下下地好不熱鬧... 腦海中突然浮現出上次離開哈姆慶功宴時的畫面與心境,好像才關上包廂的門,就又開啟了這齣劇的入口似的,感覺好不真實,卻又活生生地發生在眼前...

我做夢也沒想到,在家庭與工作越來越忙碌的現在,居然還有機會重返舞台?去年演出哈姆時,老婆正好懷孕,我以為有了女兒之後,我就沒空參加戲劇演出了... 沒想到一年後的今天,我不僅忙著照顧女兒、催生 MediQ 外,剛好在老婆懷第二胎時(沒錯!Vivian 已經有四個月的身孕了),我又接下了玉米雞這次「珍妮鳥生活」的演出邀約

星期二, 9月 25, 2012

玉米雞票房告急中!

自從女兒出生後,我的生活變得更加忙碌,剛好又在開發「MediQ 醫療輕鬆排!」這個 App,所以我幾乎暫停了我最愛的戲劇演出。

雖然如此,但我還是一直非常關心玉米雞劇團的事務,誠如我在「一場對我意義重大的演出!」分享的,我十分感動 Dorina 導演這麼努力地經營在地的劇團,她不僅得負責創作,還得忙著票務,真的是很不容易... 看著他們這樣辛苦,我總是盡可能地提供一些協助。

星期四, 6月 28, 2012

兩個寶貝都滿週歲了!

年紀越大,感覺時間過得真是越快,一眨眼的功夫,小女就已經滿週歲了!

隨著迎接這個小生命的到來,也因此開啟了我人生旅途的番外篇...

當初因為陪老婆到馬偕醫院產檢,等了 3 個小時才看到醫師,讓我有了開發「EzQ 輕鬆排!」的想法。從一個簡單的概念發想,有一搭沒一搭地開發系統雛形,到後來參加清大 AppUniverz 的 App 創作比賽臨時上場 pitch、找到展望亞洲科技成為策略夥伴等等,這些快速的發展,正巧都發生在我第一個女兒出生後最忙碌的期間...

與我熟識的朋友,在女兒出生前總笑著對我說:「看你女兒出生後還有沒有那麼多閒功夫參加有的沒的戲劇演出!」的確,女兒出生後我取消了所有戲劇演出的機會(瞧我講得好像有多少通告似的 :p),但取而代之的卻是更耗費心力與時間的精實創業...

星期二, 3月 13, 2012

畸戀

其實,在我認識現在的老婆 Vivian 前,我就已經跟她在一起一段時間了...

Vivian 和我交往不久後,就隱約感覺到她的存在,只是一直沒有主動提起。
甚至直到我們婚後的前幾年,偶爾會因為生活習慣不同而鬧彆扭的她,
也幾乎沒對這件事有太多抱怨,只有幾次非常親柔地暗示她的介意...
我也知道女人像水,但我真難想像她們竟有如此大的包容力...

我不是沒有嘗試和她分手,無論是平和或激進的手段,我都試過。
但總是徒勞無功,或許是依賴,或許是習慣,我們似乎是無法分離太久。

直到 Vivian 懷了我們的女兒小百兔,我終於意識到這件事情有多麼嚴重。
我曾駝鳥的以為,我們可以長久維持這樣的關係直到永遠,
但我一想到天真無邪的女兒,用她水汪汪的眼神望著我和她,
問道:「把拔,她是誰?」時,我該如何回答她?
我該如何說明我們這種不正常的關係?