Chia Yu Pai

Front-End, HTML5, Javascript, CSS3

Posts match “ generator-angular ” tag:

Yo Angular with CoffeeScript / Stylus / Jade

| Comments

2014-04-11 更新

我 Fork 出來一個可以自動產生的版本了
generator-angular-jade-stylus (GitGub)


yeoman 是十分方便的前端網頁產生模式,透過 angular generator 可以快速的產生良好架構的前端網頁,但 yo angular 預設支援 SASS / pure HTML 跟我的開發習慣不太吻合,研究了一下在 Grunt 加入自動編譯 Stylus / Jade 的方法。

此外,如果要在 generator-angular 啟用 CoffeeScript 請記得在 yo angular [appName] 就要加入 --coffee 參數,才會產生 Coffeescript 版的範例網頁唷。

generator-angular (GitHub)

首先我們需要載入 Grunt Contibutor for Stylus / Jade

npm install grunt-contrib-jade -D
npm install grunt-contrib-stylus -D

接著修改 Gruntfile.js 的配置

於最上方引用外部的 Task 並註冊給 compass

module.exports = function (grunt) {
  grunt.loadNpmTasks('grunt-contrib-stylus');
  grunt.loadNpmTasks('grunt-contrib-jade');
  grunt.registerTask('compass', ['stylus']);
  
  grunt.initConfig({
  //.....

}  

之後就要註冊我們自己的 Task Config

grunt.initConfig({
  jade: {
    dist: {
      options: {
        pretty: true
      },
      files: [{
        expand: true,
        cwd: '<%= yeoman.app %>',
        dest: '.tmp',
        src: ['*.jade', 'views/{,*/}*.jade'],
        ext: '.html'
      }]
    }
  },
  
  /*
  這裡我使用了 compass 協助我合併多個 stylus 的檔案,節省在引用時的 request 數量
  files 的 key 就是合併後的檔案位置 .tmp 是預設的 generator-angular test assets folder
  value 則是 source sheets 的陣列並可使用通用字符
  */
  
  stylus: {
    compile: {
      options: {
        compress: true,
        paths: ['node_modules/grunt-contrib-stylus/node_modules']
      },
      files: {
        '.tmp/styles/main.css': ['<%= yeoman.app %>/styles/*.styl']
      }
    }
  },
  
  /*
  為了可以即時透過 livereload 檢視修改的檔案,也在 watch 中加入監聽條件
  */
  
  watch: {
    jade: {
      files: ['<% yeoman.app %>/*.jade'],
      tasks: ['jade']
    },
    stylus: {
      files: ['app/styles/**/*.styl'],
      tasks: ['stylus']
    },
    // ...

  },
  
  /*
  接著因為我把 HTML 改成 Jade 編譯,所以原本 app 資料夾中僅有 source 檔案,build 過的檔案已經改到 .tmp 中了,要使 bower-install / usemin 可以正常運作在 build 時合併檔案,需要修改一些預設路徑。
  */
  
  'bower-install': {
    app: {
      html: '.tmp/index.html',
      ignorePath: '<%= yeoman.app %>/'
    }
  },
  
  useminPrepare: {
    html: '.tmp/index.html',
    options: {
      dest: '<%= yeoman.dist %>'
    }
  },
  
  // ...

最後只要在 grunt serve / build 的 task 裡面加入 jade 的 call 就可以囉

grunt.registerTask('serve', function (target) {
  if (target === 'dist') {
    return grunt.task.run(['build', 'connect:dist:keepalive']);
  }
  
  grunt.task.run([
    'clean:server',
    'jade',
  // ...

  ]);
});

// jade 的位置很重要,你必須在 usemin 之前先將 html 編譯完成,才可以正常的進行最小化以及 bower-install 的動作


grunt.registerTask('build', [
  'clean:dist',
  'jade',
  // ...

]);

以上就是在 generator-angular 加入 Jade / Stylus 的方法,這樣的修改方法會遇到個問題,就原本的用法 yo angular:controller 等新增動作時,會自動加入 index.html 的引用句會無法使用,因此你將必須手動將

至於修改這個 Bug 的方法,必須直接修改 generator 的 source 本身,這樣每當 generator 更新版本都需要再次修改,等於要維護一個新的 fork 在時間有限的情況下就先將就著用囉,詳細改法有興趣可以來信討論 :)

--
附上一個修改後的 index.jade 方便大家直接套用

doctype html
<!--[if lt IE 7]>
<html class="no-js lt-ie9 lt-ie8 lt-ie7">
<![endif]-->
<!--[if IE 7]>
<html class="no-js lt-ie9 lt-ie8">
<![endif]-->
<!--[if IE 8]>
<html class="no-js lt-ie9">
<![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->
head
  meta(charset="utf-8")
  meta(http-equiv="X-UA-Compatible", content="IE=edge")
  title
  meta(name="description", content="")
  meta(name="viewport", content="width=device-width")
  // Place favicon.ico and apple-touch-icon.png in the root directory
  // build:css styles/vendor.css
  // bower:css
  link(rel="stylesheet", href="bower_components/bootstrap/dist/css/bootstrap.css")
  // endbower
  // endbuild
  // build:css({.tmp,app}) styles/main.css
  link(rel="stylesheet", href="styles/main.css")
  // endbuild
body(ng-app="cominfinitibeatstyletripplacewebApp")
  <!--[if lt IE 7]>
  p.browsehappy
    | You are using an 
    strong outdated
    |  browser. Please 
    a(href="http://browsehappy.com/") upgrade your browser
    |  to improve your experience.
  <![endif]-->

  // Add your site or application content here 
  div.container(ng-view="")

  // Google Analytics: change UA-XXXXX-X to be your site's ID 
  script.
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-XXXXX-X');
    ga('send', 'pageview');

  <!--[if lt IE 9]>
  script(src="bower_components/es5-shim/es5-shim.js")
  script(src="bower_components/json3/lib/json3.min.js")
  <![endif]-->

  // build:js scripts/vendor.js 
  // bower:js 
  script(src="bower_components/jquery/jquery.js")
  script(src="bower_components/angular/angular.js")
  script(src="bower_components/bootstrap/dist/js/bootstrap.js")
  script(src="bower_components/angular-resource/angular-resource.js")
  script(src="bower_components/angular-cookies/angular-cookies.js")
  script(src="bower_components/angular-sanitize/angular-sanitize.js")
  script(src="bower_components/angular-route/angular-route.js")
  // endbower 
  // endbuild 

  // build:js({.tmp,app}) scripts/scripts.js 
  script(src="scripts/app.js")
  script(src="scripts/controllers/main.js")
  // endbuild 

最下方的 // endbuild 之上就是我提到要自行加入 script tag 的地方哦。