Blackbing Playground

[Angular] grunt-usemin

在使用 Angular generator 建立 project 相當的方便,

angular [app-name]```就可以裝完大部份所需要的東西,執行```grunt build```就會做好 uglify, minimize, packing, 等等的功能。其中一個對於線上環境很重要的功能就是 [usemin](https://github.com/yeoman/grunt-usemin)。功能很強大,設定有點多,因此我順便筆記一些一開始撞牆的地方。
1
2
3
4
5
6
7
8
9
10
11
#Blocks 打包某區塊裡頭的檔案(js/css)
例如你可以在 index.html 裡頭看到
``` html
<!-- build:js js/app.js -->
<script src="js/app.js"></script>
<script src="js/controllers/thing-controller.js"></script>
<script src="js/models/thing-model.js"></script>
<script src="js/views/thing-view.js"></script>
<!-- endbuild -->

這裡的設定是說在執行 usemin 時會將這幾隻 script 打包起來 output 成 js/app.js。因此如果你有額外新增加的程式需要一起打包的必須放在 block 裡頭,不然不會被打包進去。

不過在 build 完之後會發現有些檔案並沒有被打包進去,問題在於需要 compile 的程式(例如sass, coffee)會先被 compile 到 .tmp/ 的 folder 底下,因此預設的 search path 是搜尋不到這個檔案的。根據文件的說明:

1
<!-- build:<type>(alternate search path) <path> -->

1
2
3
4
例如:
```html
<!-- build:css({app,.tmp}) styles/main.css -->

(ㄜ…….這啥鬼格式?)

#revmap
rev 這個 task 會將 js/css/image/fonts 等做重新 rename 的動作,讓程式可以做到快取的優化,例如

會變成 ```foo.1234.png``` 這樣,而 usemin 的工作就是將 html 裡頭包含該檔案的路徑做取代。例如
1
2
3
```html
<img src="/images/toolset.png" alt="Yo, Grunt, Bower">

會變成

1
<img src="/images/75bab8-toolset.png" alt="Yo, Grunt, Bower">

不過由於在做 SPA(Single Page Application) 時會將很多 template view 拆開,所以我將一些其他的 view 分開像是這樣:

├── index.html
└── views
├── home.html
├── navbar.html
├── foo.html
└── bar.html

由於 這些 view 底下的 html 其實是要給 index.html 來使用的,因此他的路徑其實是從 root 開始算的,在開發階段其實都不會有問題,然而在 build 完之後就會發現圖片會找不到的情況。追了一下 log 才發現 usemin 雖然有 parse 這些 html 但並不會將 image tag 替換掉。其實想想也合理,因為根目錄的路徑不同啊!但這樣一來 template 享受不到 usemin 的好處,相當令人沮喪。

網路上好像找不到太到相關的問題,因此我就試著來解決,以下是我解決的步驟:

#####1. 在

"grunt-contrib-symlink": "~0.2.0"
1
#####2. 在```Gruntfile.js```加入以下的設定:

symlink: {
views:{
expand: true,
cwd: ‘<%= yeoman.dist %>/views/‘,
src: [‘*’],
dest: ‘<%= yeoman.dist %>/‘
}
}

1
#####3. 在```Gruntfile.js```加入以下的 task:

grunt.registerTask(‘clean-link’, function(target){
var yeoman = grunt.config.get(‘yeoman’);
var htmls = grunt.file.expand( {
}, yeoman.dist+’/*.html’).forEach( function(path){
if( grunt.file.isLink(path) )
grunt.file.delete(path);
});
});

1
#####4. 在 build task 裡頭的 ```'usemin'``` 改成

‘symlink:views’, //create symlink
‘usemin’,
‘clean-link’ //clear symlink
```

解決的方式是將 views/ 底下的 html 都建立 soft link 到根目錄,然後讓 usemin 去 parse,並且寫回 views/*.html ,最後將這些 symlink 清掉。

大概是這樣,grunt 真是很難懂。