Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

巧用cheerio重构grunt-inline #23

Open
chyingp opened this issue Jul 14, 2014 · 0 comments
Open

巧用cheerio重构grunt-inline #23

chyingp opened this issue Jul 14, 2014 · 0 comments

Comments

@chyingp
Copy link
Owner

chyingp commented Jul 14, 2014

**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);

写在后面

没什么好写的其实,求勘误~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant