實現(xiàn)構(gòu)建工具之增量打包

銜接上文闷愤,由于每次修改文件课蔬,都會觸發(fā)重新全量打包何暇,在項目體積幾乎為0的情況下要花費3.5s句柠,希望能提升性能咸包,只對修改過的文件進行打包桃序,但由于我們沒有用到代碼拆分code splitting,所以此處優(yōu)化為:不會codeSplicing未更改的文件

思路

  • 精確獲取更改的文件
  • 將文件路徑當(dāng)作參數(shù)傳入browserify函數(shù)
  • browserify解析文件路徑烂瘫,只codeSplicing該文件

思考

  • 之前使用nodemon監(jiān)聽文件變化媒熊,沒有地方獲取變更文件的信息
  • 需要改為使用node,fs模塊的watch函數(shù)進行監(jiān)聽坟比,能夠獲取到更改文件的信息
  • 為了可用性芦鳍,解析之前的nodemon配置進行文件監(jiān)聽匹配
  • 由于可能分為文件夾和文件,且文件夾深度未知葛账,所以需要遞歸進行監(jiān)聽以及過濾

實現(xiàn)

收集nodemon配置柠衅,解析字段

const config = {
    "watch": ["."],
    "ext": "js,ts,css",
    "ignore": ["./dist/chunk.js", "./test/temp*.js"],
    "exec": "node ./src/browserify.js ./test/index.js"
}

遞歸過濾,監(jiān)聽

const extSet = new Set(config.ext.split(','))
const ignoreList = config.ignore.concat(['node_modules', '.git'])

const fileFilter = (path) => {
    // 忽略文件校驗
    const isIgnore = ignoreList.some(item => {
        return new RegExp(`${item.replace(/\./g, '\.').replace(/\\/g, '\\\\').replace(/\*/g, '.*')}$`).test(path)
    })
    if (isIgnore) return

    //區(qū)分文件或文件夾
    const stat = fs.statSync(path)
    const isDirectory = stat.isDirectory()
    if (isDirectory) {
        const dir = fs.readdirSync(path)
        dir.forEach(fileName => {
            //遞歸對文件夾內(nèi)每個文件執(zhí)行一遍
            fileFilter(join(path, fileName))
        })
    } else {
        // 后綴校驗
        const ext = extname(path).replace(/^\./, '')
        if (!ext || !extSet.has(ext)) return

        //符合配置籍琳,開啟監(jiān)聽
        fs.watch(path, (eventType, filename) => {
            console.log('開始重新構(gòu)建');
            console.log(filename, eventType);
            execSync(config.exec)
            console.log('完成重新構(gòu)建');
        })
    }
}

測試

開始重新構(gòu)建
module1.js change
完成重新構(gòu)建
開始重新構(gòu)建
module1.js change
完成重新構(gòu)建

可以看到

  • 確實實現(xiàn)了按照配置過濾及文件監(jiān)聽
  • 能夠獲取到修改的文件名菲宴,以及修改類型
  • 改一次文件watch可能會觸發(fā)兩次
    關(guān)于觸發(fā)兩次的問題,發(fā)現(xiàn)官網(wǎng)說法如下

fs.watch API 跨平臺并非 100% 一致趋急,并且在某些情況下不可用喝峦。

網(wǎng)友反饋

Node.js `fs.watch`:

*   不報告OS X上的文件名。
*   在OS X上使用Sublime等編輯器時呜达,根本不報告事件谣蠢。
*   經(jīng)常報告兩次事件。
*   發(fā)布大多數(shù)更改為`rename`闻丑。
*   有[a lot of other issues](https://github.com/joyent/node/search?q=fs.watch&type=Issues)
*   不提供遞歸查看文件樹的簡便方法漩怎。

Node.js `fs.watchFile`:

*   事件處理幾乎一樣糟糕。
*   也不提供任何遞歸觀看嗦嗡。
*   導(dǎo)致CPU利用率過高勋锤。

網(wǎng)上的解決方案如下:

  1. trick方式,但其實不是每次都會出發(fā)兩次watch侥祭,所以不可取
var fs = require('fs');
var working = false;
fs.watch('directory', function (event, filename) {
  if (filename && event == 'change' && active == false) {
    active = true;
//do stuff to the new file added
active = false;
});
  1. 建議使用chokidar(https://github.com/paulmillr/chokidar)

好的叁执,話不多說茄厘,這就使用chokidar,代碼如下:

const chokidar = require('chokidar');
const { execSync } = require("child_process");

// One-liner for current directory
const watcher = chokidar.watch('.', {
    persistent: true,
    ignored: ['./dist/chunk.js', './test/temp *.js', '.git', '.history', 'node_modules', './src/moduleFuncCache.js'],
    ignoreInitial: false,
    followSymlinks: true,
    cwd: '.',
    disableGlobbing: false,

    usePolling: false,
    interval: 100,
    binaryInterval: 300,
    alwaysStat: false,
    depth: 99,
    awaitWriteFinish: {
        stabilityThreshold: 2000,
        pollInterval: 100
    },

    ignorePermissionErrors: false,
    atomic: true
})


watcher.on('change', path => {
    console.log(`更改文件${path}`);
    //增量更改模塊谈宛,需傳入更改的文件的路徑
    execSync(`node ./src/browserify.js ./test/index.js ${path}`)
})
    .on('unlink', path => {
        // 遇到刪除文件操作則重新打包一遍次哈,及時發(fā)現(xiàn)錯誤
        execSync(`node ./src/browserify.js ./test/index.js`)
    });

更改js和css代碼,效果如下:

更改文件test/module2.js
更改文件asserts/css/color.css

注意這句execSync(node ./src/browserify.js ./test/index.js ${path})吆录,它會將更改的文件路徑傳入browserify.js窑滞,從而明確哪個模塊更改了,從而只針對該模塊進行替換

browserify.js文件接收如下:

const [path, changeFilePath] = process.argv.splice(2);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末恢筝,一起剝皮案震驚了整個濱河市哀卫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撬槽,老刑警劉巖此改,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異侄柔,居然都是意外死亡共啃,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門暂题,熙熙樓的掌柜王于貴愁眉苦臉地迎上來移剪,“玉大人,你說我怎么就攤上這事薪者」易遥” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵啸胧,是天一觀的道長。 經(jīng)常有香客問我幔虏,道長纺念,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任想括,我火速辦了婚禮陷谱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瑟蜈。我一直安慰自己烟逊,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布铺根。 她就那樣靜靜地躺著宪躯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪位迂。 梳的紋絲不亂的頭發(fā)上访雪,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天详瑞,我揣著相機與錄音,去河邊找鬼臣缀。 笑死坝橡,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的精置。 我是一名探鬼主播计寇,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼脂倦!你這毒婦竟也來了番宁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤狼讨,失蹤者是張志新(化名)和其女友劉穎贝淤,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體政供,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡播聪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了布隔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片离陶。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衅檀,靈堂內(nèi)的尸體忽然破棺而出招刨,到底是詐尸還是另有隱情,我是刑警寧澤哀军,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布沉眶,位于F島的核電站,受9級特大地震影響杉适,放射性物質(zhì)發(fā)生泄漏谎倔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一猿推、第九天 我趴在偏房一處隱蔽的房頂上張望片习。 院中可真熱鬧,春花似錦蹬叭、人聲如沸藕咏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽孽查。三九已至,卻和暖如春坦喘,著一層夾襖步出監(jiān)牢的瞬間卦碾,已是汗流浹背铺坞。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留洲胖,地道東北人济榨。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像绿映,于是被迫代替她去往敵國和親擒滑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容