文章出處

grunt-inline是樓主之前寫的一個插件,主要作用是把頁面帶了__inline標記的資源內嵌到html頁面去。比如下面的這個script標簽。

<script src="main.js?__inline"></script>

技術難度不高,主要就是通過正則將符合條件的script標簽等匹配出來。當時就在想:

如果有那么一個插件,能夠幫我們完成html解析就好了!

沒錯,真有——cheerio。感謝當勞君的推薦 =。=

cheerio簡介

直接引用某前端同學的翻譯

為服務器特別定制的,快速、靈活、實施精益(lean implementation)的jQuery核心

舉個最簡單的栗子,更多API說明請參考官方文檔

var cheerio = require('cheerio'),
    $ = cheerio.load('<h2 class="title">Hello world</h2>');

$('h2.title').text('Hello there!');
$('h2').addClass('welcome');

$.html();
//=> <h2 class="title welcome">Hello there!</h2>

重構實戰

首先看下我們的目錄結構。其中,src里的是源文件,dest目錄里是編譯生成的文件。可以猛擊這里下載demo。

├── demo.js
├── package.json
├── dest
│ └── index.html
└── src
├── index.html
└── main.js

我們看下src/index.html,里面的main.js就是我們最終要內嵌的目標。let's go

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>cheerio demo</title>
</head>
<body>
    <h1>cheerio demo</h1>
    <script src="main.js?__inline"></script>
</body>
</html>

先看成果

在控制臺敲如下命令,就會生成dest/index.html。下一節我們會講下demo.js的實現

npm install
node demo.js

dest/index.html如下。

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>cheerio demo</title>
</head>
<body>
    <h1>cheerio demo</h1>
    <script>/**
 * Created by a on 14-7-15.
 */
var Main = {
    say: function(msg){
        console.log(msg);
    }
};</script>
</body>
</html>

demo.js代碼解析

直接上demo.js的代碼,一切盡在不言中。如果想更近一步,完成css資源、img資源的內嵌,非常簡單,參照script內嵌的那部分代碼就可以了。需要壓縮代碼?趕緊用uglifyjs啦,so easy,這里就不占用篇幅講這個了。

/**
 * Created by a on 14-7-15.
 */
var cheerio = require('cheerio'),   // 主角 cheerio
    fs = require('fs'),
    url = require('url'),
    path = require('path');

var from = 'src/index.html',    // 源文件
    to = 'dest/index.html', // 最終生成的文件
    content = fs.readFileSync(from),
    $ = cheerio.load(content),  // 加載源文件
    fd = 0;

// 選取 src/index.html 里所有的script標簽,并將帶有 __inline 標記的內嵌
$('script').each(function(index, script){
    var script = $(this),
        src = script.attr('src'),
        urlObj = url.parse(src),
        dir = path.dirname(from),
        pathname = path.resolve(dir, urlObj.pathname),
        scriptContent = '';

    // 關鍵步驟:__inline 檢測!(ps:非嚴謹寫法)
    if(urlObj.search.indexOf('__inline')!=-1){
        scriptContent = fs.readFileSync(pathname);
        script.replaceWith('<script>'+ scriptContent +'</script>');
    }
});

// 創建dest目錄
if(!fs.exists(path.dirname(to))){
    fs.mkdirSync(path.dirname(to));
}

// 將處理完的文件寫回去
fd = fs.openSync(to, 'w');
fs.writeFileSync(to, $.html());
fs.closeSync(fd);

寫在后面

沒什么好寫的其實,求勘誤~


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()