前言
之前也是从grunt/gulp/fis/过来的,到现在的webpack,中间有些问题没怎么细想,比如明明是构建工具为什么调试总是要开启一个http服务之类的,现在就来简单梳理下思路
最原始的构建工具无非是这样:
改动了某个资源文件, 要手动运行构建命令才能重新构建,
重新构建的时候构建工具将所有资源文件重新构建一次,再合并打包.
你要手动刷新页面才能加载到到最新的构建完成的资源文件
而我们希望构建工具最好是这样:
你改动了某个资源文件,构建工具能够监听到这个变化,自动进行重新构建
构建工具重新构建的时候并不会将所有的资源文件全部构建, 而是将
变化了的
资源文件重新构建,再将这个变化了的
资源文件和其他的资源文件合并打包构建完成之后能够自动刷新你的调试页面(当然如果能类似ajax无刷新加载就更好了)
核心功能轻量,通过plugin来拓展其他功能,比如编译coffee/typescript/tpl/sass等
实现原理
资源文件修改自动编译
监听资源的修改实现自动编译是构建工具要实现的基本功能,其原理是
node有api能够可以监听单个资源文件的状态(fs.watch),当资源文件发生变化,能够触发回调通知node, 这也是许多基于node的构建工具实现核心. 当然强大的node社区还出了监听文件夹的node模块比如Chokidar
按需构建资源文件
构建工具监听到了某个资源文件的变化,重新构建一遍这个资源文件,然后在最后打包的阶段和其他没有变化的之前已经构建好的资源文件合在一起重新打包成aio(
all in one
)构建工具监听到了某个资源文件的变化,重新构建一遍这个资源文件,然后在之前构建的aio中抽离出这个资源文件变化前的逻辑,填入变化后的逻辑, 连一块打包都省了,不过实现起来逻辑比较复杂.
页面自动加载新资源以方便调试
要实现这种功能,一般要在本机建立一个简单的http server,构建工具构建完成之后将文件整个放置在server目录.
并且在开发环境(dev)中,构建工具构建出来的最终的页面文件除了你的业务代码,一般还会引入一段socket
的相关代码,通过socket使得client能够一直和server保持通信.比如你构建完成之后,通过127.0.0.1:port/index.html调试页面,你这个index.html中嵌入了了socket的代码(当然,生产环境(prod)不会把socket的功能打包进去的)
有了socket使得服务端和客户端保持通信连接,服务器推动客户端刷新就很容易实现了. 处理方式有两种,同步刷新
和异步热加载
如果服务器资源发生了变化,服务器会通过socket来向客户端发送指令,客户端socket捕获到这条指令,就刷新页面来重载新的资源.
如果服务器发生了变化,服务器会通过socket来向客户端发送指令,客户端socket捕获到这条指令,异步向服务器拉去新的资源,来实现无刷新异步重载.
通过plugin来拓展其他功能
绝大多数构建工具都是通过插件拓展的,就不说了