1. 程式人生 > >grunt和seajs的打包初體驗

grunt和seajs的打包初體驗

    seajs作為前端模組載入器,在依賴管理方面是挺方便的,用起來也還算比較簡單。不過,由於模組化使得模組劃分比較細,所以載入一個頁面將會發起多次http請求,這在生產環境中是不可接受的。一般而言,生產環境下,資源會放在CDN,而資源本身,通常會進行合併及壓縮。

    grunt 是 js 的一個著名的打包工具,可以作為node的一個包,使用npm安裝使用。為了進一步探索seajs在真實場景下可能會是一種怎樣的使用情況,本文將使用grunt進行seajs的打包測試。

    本文假定資源域名為: static.test.com , 使用host對映到 127.0.0.1 , 本文假設讀者知道  node 和 npm。

    建立的專案結構如下:

    

    1部分為頁面,為簡單起見,只有一個商城手機端首頁

    2部分為打包需要的一些node包,使用npm下載的

    3部分為一些js模組, js-build為打包後的資源

    首先,定義好 package.json

{
  "name": "mall",
  "version": "0.1.0",
  "dependencies": {
    "grunt": "^0.4.5",
    "grunt-cmd-concat": "^0.2.8",
    "grunt-cmd-transport": "^0.4.1",
    "grunt-contrib-uglify": "^0.2.7"
  }
}
    然後進入到 package.json目錄, 直接  npm install, 這樣將會生成 node_modules。

    接著看看我們的 index.jsp 頁面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>商城首頁</title>
</head>
<body>
商城首頁

<jsp:include page="resource.jsp"></jsp:include>
<script>
// 載入入口模組
seajs.use("mall/index/index.js");
</script>
</body>
</html>
    引用了統一的 resource.jsp , 同時 seajs 入口 為   mall/index/index.js 這個檔案。

    resource.jsp 的內容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<script src="http://static.test.com/plugin/js/sea-debug.js" id="seajsnode"></script>
<script>
// seajs 的簡單配置
seajs.config({
  base: "http://static.test.com/js-build/",
  map:[
       [".js" , "-min.js"]
       ],
  alias: {
    
  }
});
</script>
    非常的簡單, 當我們這樣編寫程式碼後,實際上,seajs會去載入 http://static.test.com/js-build/mall/index/index-min.js 這個檔案,這是我們 index的最終版,我們來看看index.js 裡面的內容
/**
 * 手機商城首頁
 */
define(function(require , exports , module){
	var header = require("../common/header");
	var footer = require("../common/footer");
	var content = require("../index/content");
	header.self();
	
	exports.self = function(){
		alert("index content.js");
	}
});
它是一個標準的cmd模組,依賴了其它三個模組,我們想要的結果就是,最終 header.self 會 alert出內容,那麼基本就正確了。 其它模組也是標準的cmd模組,內容就不看了。

    接著, grunt上場了,先配置好 Gruntfile.js,內容如下:

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    options: {
      },
    transport: { // 給 cmd 模組 提取 id 以及 依賴
        target_name: {
            files: [{
            	expand: true,
            	cwd: 'static/js/',
                src: '**/*.js',
                dest: 'static/js-build/'
            }]
        }
    },
    
    concat: { // 把 index.js 這個模組 以及 其依賴的所有模組 統一 合併為  index-transport.js 這個檔案
        index: {
          options: {
        	  include: 'all'
          },
          files: {
            'static/js-build/mall/index/index-transport.js': ['static/js-build/mall/index/index.js']
          }
        }
      },
      
      uglify: { // 對合並後的檔案進行壓縮
	    index: {
	    	options:{
	            sourceMap: 'static/js-build/mall/index/index-min.js.map'   // chrome下支援壓縮js除錯
	          },
	      files: {
	        'static/js-build/mall/index/index-min.js': ['static/js-build/mall/index/index-transport.js']
	      }
	    }
	  }
  });
  //  載入三個外掛
  grunt.loadNpmTasks('grunt-cmd-transport');
  grunt.loadNpmTasks('grunt-cmd-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  // 定義任務
  grunt.registerTask('default', ['transport' , 'concat' , 'uglify']);

};


準備好之後,直接在 Gruntfile.js 同級目錄下 grunt , 就會得到  index-min.js 這個最終版的檔案


啟動伺服器,便可以訪問 index.jsp 這個頁面了,而且 js 的載入也是正常的,也確實alert出來了。


    不過可能是我瀏覽器的問題, sourcemap 並沒有載入。

    整個過程看著東西雖然不多,但真實操作的時候,才知道是多麼折騰,怪不得很多人都在抱怨,seajs用起來容易,打包TMD太難了。

    一些小感悟:

    1) 如果使用了 seajs的alias和paths,打包可能會有各種意想不到的吭 

    2)   grunt 相關外掛的版本,也是一個大吭,打包過程可能會有各種不順,也是由於外掛包版本要不然太高,要不然又太低了,導致的各種問題,無奇不有。

    3)   使用相對路徑來互相引用模組是比較順利打包的一個基石(個人感覺)

   小小的實驗前前後後整了一大天,以此文記之,也算是了結了這次嚐鮮。