JavaScript编译vm模板(二)

638 阅读2分钟

上文(JavaScript编译vm模板(一))中介绍了vm文件编译为html文件的方法,并增加了watchpack进行实时监测以便vm文件变化时自动编译。本文我们要进一步进行优化,实现静态文件服务器以便展示生成的html文件,并实现vm变化后自动刷新html页面

涉及到的npm包

  • open:实现自动打开指定网页url
  • ws:实现# WebSocket服务器端,和浏览器端通信以便当vm文件变化时自动刷新页面

源码

const http = require('http');
const path = require("path");
const fs = require('fs');
const WebSocket = require('ws')
const WebSocketServer = WebSocket.Server;
const open = require('open');
const Watchpack = require("watchpack");
const velocity = require('velocityjs');

// 监听文件变化
const wp = new Watchpack({
    aggregateTimeout: 100,
    poll: true,
    followSymlinks: true,
    ignored: "**/.git"
});

wp.watch({
    files: [
        path.join(__dirname, 'day.vm'),
        path.join(__dirname, 'hour.vm')
    ],
    startTime: Date.now() - 10000
});

const dayContext = {
    isNormalDay: false,
    month: 12,
    dt: ["11/01", "11/02", '11/03']
};
const hourContext = {
    lastStr: '周三',
    isTop6Hour: true
};
const htmlPort = Math.floor(Math.random() * 1000 + 8000);
const wsClientPort = Math.floor(Math.random() * 1000 + 9000);
const wsClientS = [];
const clientWS = `
    <script>
        const ws = new WebSocket('ws://localhost:${wsClientPort}')
        ws.onmessage = function (evt) {
            if (window.location.href.indexOf(evt.data) !== -1) {
                window.location.reload();
            }
        };
    </script>
`;


wp.on("change", function (filePath, mtime, explanation) {
    let message = '';
    console.log(`change:${filePath}...`)
    if (filePath.indexOf('day') !== -1) {
        message = 'day'
    } else if (filePath.indexOf('hour') !== -1) {
        message = 'hour'
    }
    wsClientS.forEach(ws => {
        ws.send(message);
    })
});

// 创建本地服务器来从其接收数据
http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html; charset=UTF-8' });
    if (req.url === '/day.html') {
        const vmContent = velocity.render(
            fs.readFileSync(
                path.join(__dirname, 'day.vm'), 'utf-8'
            ), dayContext
        );
        res.end(vmContent.slice(
                0,
                vmContent.indexOf('</body>')) + clientWS + '</body></html>'
            );
    } else if (req.url === '/hour.html') {
        const vmContent = velocity.render(
                fs.readFileSync(path.join(__dirname, 'hour.vm'), 'utf-8'
            ), hourContext
        );
        res.end(vmContent.slice(
            0,
            vmContent.indexOf('</body>')) + clientWS + '</body></html>'
        );
    } else {
        res.end();
    }
}).listen(htmlPort, () => {
    console.log(`listen:http://127.0.0.1:${htmlPort}...`);
    open(`http://127.0.0.1:${htmlPort}/day.html`, { 
            app: { name: 'chrome' } 
        }
    );
});

// 获取自动刷新
(new WebSocketServer({
    port: wsClientPort
})).on('connection', function connection(ws) {
    wsClientS.push(ws);
});

需要注意的几个关键点:

  • 为了避免打开多个服务器以及冲突,端口号是随机生成的
  • vm文件变化时,我们是reload了整个页面,实际时,可以通过WebSocket将编译后的结果传给客户端,客户端只更新部分的页面dom(如body等),这样就不必刷新整个页面了。
  • 我们的静态文件服务器和WebSocket实际上是两个单独的服务器,各自有各自的端口
  • open@8.3.0官网上,打开谷歌浏览器写的namegoogle chrome,这是有问题的,实际上应该按照上文chrome来设置

相关文章