前端工程化~強大的glob語法

glob 在正則出現(xiàn)之前就有了锭环,主要用于匹配文件路徑,例如大名鼎鼎的 gulp 就使用了 glob 規(guī)則來匹配泊藕、查找并處理各種后綴的文件辅辩。在前端工程化的過程中,不可避免地會用 Node.js 來讀取文件,例如想找到 src 目錄下所有 jsjsx 文件玫锋,代碼應(yīng)該怎么寫呢蛾茉?首先安裝依賴包:

yarn add glob

然后 3 行代碼搞定:

const glob = require('glob')
const files = glob.sync('src/**/*.js{,x}')
console.log(files)

有沒有感覺很強大呢?更重要的是 glob 語法在命令行就支持撩鹿,不需要安裝任何依賴谦炬,例如老板讓你創(chuàng)建 a1.jsa9.jsb1.jsb9.js 這 18 個測試文件的話节沦,怎么操作键思?一個個創(chuàng)建的話太傻了,glob 一句話就搞定:

$ touch {a,b}{1..9}.js
$ ls
a1.js a3.js a5.js a7.js a9.js b2.js b4.js b6.js b8.js
a2.js a4.js a6.js a8.js b1.js b3.js b5.js b7.js b9.js

更更更重要的是甫贯,glob 的語法非常簡單吼鳞,只要記住下面7個符號代表的含義就能掌握了:

  • 基礎(chǔ)語法:/*获搏、?赖条、[]
  • 拓展語法:**{}常熙、()

接下來就逐個解釋一下:

基礎(chǔ)語法

分隔符和片段

概念:分隔符是/纬乍,通過split('/') 得到的數(shù)組每一項是片段。

示例:

  • src/index.js 有兩個片段裸卫,分別是 srcindex.js
  • src/**/*.js 有三個片段仿贬,分別是 src***.js

單個星號

概念:單個星號* 用于匹配單個片段中的零個或多個字符墓贿。

示例

  • src/*.js 表示 src 目錄下所有以 js 結(jié)尾的文件茧泪,但是不能匹配 src 子目錄中的文件,例如 src/login/login.js
  • /home/*/.bashrc 匹配所有用戶的 .bashrc 文件

需要注意的是聋袋,* 不能匹配分隔符/队伟,也就是說不能跨片段匹配字符。

問號

概念:問號 ?匹配單個片段中的單個字符幽勒。

示例

  • test/?at.js 匹配形如 test/cat.js嗜侮、test/bat.js 等所有3個字符且后兩位是 at 的 js 文件,但是不能匹配 test/flat.js
  • src/index.?? 匹配 src 目錄下以 index 打頭啥容,后綴名是兩個字符的文件锈颗,例如可以匹配 src/index.jssrc/index.md,但不能匹配 src/index.jsx

中括號

概念:同樣是匹配單個片段中的單個字符咪惠,但是字符集只能從括號內(nèi)選擇击吱,如果字符集內(nèi)有-,表示范圍遥昧。

示例:

  • test/[bc]at.js 只能匹配test/bat.jstest/cat.js
  • test/[c-f]at.js 能匹配 test/cat.js覆醇、test/dat.js朵纷、test/eat.jstest/fat.js

驚嘆號

概念:表示取反,即排除那些去掉驚嘆號之后能夠匹配到的文件永脓。
示例:

  • test/[!bc]at.js不能匹配 test/bat.jstest/cat.js柴罐,但是可以匹配 test/fat.js
  • !test/tmp/**' 排除 test/tmp 目錄下的所有目錄和文件

擴展語法

基礎(chǔ)語法非常簡單好記,但是功能非常局限憨奸,為了豐富 glob 的功能,衍生了下面三種擴展語法:

兩個星號

概念:兩個星號** 可以跨片段匹配零個或多個字符凿试,也就是說**是遞歸匹配所有文件和目錄的排宰,如果后面有分隔符,即 **/ 的話那婉,則表示只遞歸匹配所有目錄(不含隱藏目錄)板甘。

示例:

  • /var/log/** 匹配 /var/log 目錄下所有文件和文件夾,以及文件夾里面所有子文件和子文件夾
  • /var/log/**/*.log 匹配 /var/log 及其子目錄下的所有以 .log 結(jié)尾的文件
  • /home/*/.ssh/**/*.key 匹配所有用戶的 .ssh 目錄及其子目錄內(nèi)的以.key 結(jié)尾的文件

大括號

概念:匹配大括號內(nèi)的所有模式详炬,模式之間用逗號進行分隔盐类,支持大括號嵌套,支持用.. 匹配連續(xù)的字符呛谜,即{start..end} 語法在跳。

示例:

  • a.{png,jp{,e}g} 匹配 a.pnga.jpg隐岛、a.jpeg
  • {a..c}{1..2} 匹配 a1 a2 b1 b2 c1 c2

注意:{}[] 有一個很重要的區(qū)別:如果匹配的文件不存在猫妙,[]會失去模式的功能,變成一個單純的字符串聚凹,而 {} 依然可以展開割坠。

小括號

概念:小括號必須跟在 ?*妒牙、+彼哼、@! 后面使用湘今,且小括號里面的內(nèi)容是一組以 | 分隔符的模式集合敢朱,例如:abc|a?c|ac*

示例:

  • ?(pattern|pattern|pattern):匹配0次或1次給定的模式
  • *(pattern|pattern|pattern):匹配0次或多次給定的模式
  • +(pattern|pattern|pattern):匹配1次或多次給定的模式
  • @(pattern|pattern|pattern):嚴格匹配給定的模式
  • !(pattern|pattern|pattern):匹配非給定的模式

應(yīng)用場景

webpack 多頁面應(yīng)用自動打包配置

在一個 webpack 項目中象浑,假如我們有多個入口蔫饰,每個入口都有一個 index.html 模板和 index.js 文件,而且這個入口是動態(tài)變化的愉豺,不希望每增加一個入口就改 webpack.config.js 配置文件篓吁,應(yīng)該怎么辦呢?

此時可以約定在 src 下面創(chuàng)建的文件夾蚪拦,只要里面有 index.js杖剪,我們就把它當做一個入口文件進行打包:

src
├── detail
│   ├── index.html
│   └── index.js
├── home
│   ├── index.html
│   └── index.js
├── login
│   ├── index.html
│   └── index.js
├── shop
│   ├── index.html
│   └── index.js

用 glob 很快就能寫出下面的自動打包代碼:

const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path')
const glob = require('glob')

// 動態(tài)生成 entry 和 html-webpack-plugin
function getMpa() {
  const entry = {}, htmlPlugins = []
  const files = glob.sync('src/*/index.js')
  files.forEach((file) => {
    const filename = file.split('/')[1]
    entry[filename] = path.join(__dirname, file)
    htmlPlugins.push(
      new HtmlWebpackPlugin({
        template: path.join(__dirname, `src/${filename}/index.html`),
        filename: `${filename}.html`,
        chunks: [filename],
      })
    )
  })
  return { entry, htmlPlugins }
}
const mpa = getMpa()

// 動態(tài)的配置文件
module.exports = {
  entry: mpa.entry,
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name]-[hash:6].js',
  },
  plugins: [...mpa.htmlPlugins],
}

這樣冻押,無論增加多少個入口,webpack.config.js 都不用變盛嘿。

手寫一個約定大于配置的 Node.js 框架

egg.js 是一款優(yōu)秀的 Node.js 企業(yè)級開發(fā)框架洛巢,就應(yīng)用了約定大于配置的思想,例如:

  • 約定一個中間件是一個放置在 app/middleware 目錄下的單獨文件
  • 約定了 app/router.js 文件用于統(tǒng)一所有路由規(guī)則
  • 約定 Service 文件必須放在 app/service 目錄次兆,可以支持多級目錄稿茉,訪問的時候可以通過目錄名級聯(lián)訪問

因為一個大規(guī)模的團隊需要遵循一定的約束和約定,開發(fā)效率才更高芥炭,有了這些約定之后漓库,我們就可以利用 glob 寫出匹配規(guī)則,找到用戶放到指定目錄下的文件并進行動態(tài)加載了园蝠,一個最基礎(chǔ)的 load 函數(shù)如下:

function load(folder, options) {
    const extname = options.extname || '.{js,ts}'
    return glob.sync(require('path').join(folder, `./**/*.js`)).forEach((item) => require(item))
}

使用 glob渺蒿,配合相應(yīng)的規(guī)范,例如 RESTful彪薛,我們自己也能封裝一個簡易的茂装、基于約定的 Node.js 框架了。

放在最后

贈與小伙伴們的一點點小福利~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末善延,一起剝皮案震驚了整個濱河市少态,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挚冤,老刑警劉巖况增,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異训挡,居然都是意外死亡澳骤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門澜薄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來为肮,“玉大人,你說我怎么就攤上這事肤京〖昭蓿” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵忘分,是天一觀的道長棋枕。 經(jīng)常有香客問我,道長妒峦,這世上最難降的妖魔是什么重斑? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮肯骇,結(jié)果婚禮上窥浪,老公的妹妹穿的比我還像新娘祖很。我一直安慰自己,他們只是感情好漾脂,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布假颇。 她就那樣靜靜地躺著,像睡著了一般骨稿。 火紅的嫁衣襯著肌膚如雪笨鸡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天坦冠,我揣著相機與錄音镜豹,去河邊找鬼。 笑死蓝牲,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的泰讽。 我是一名探鬼主播例衍,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼已卸!你這毒婦竟也來了佛玄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤累澡,失蹤者是張志新(化名)和其女友劉穎梦抢,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愧哟,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡奥吩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蕊梧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片霞赫。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖肥矢,靈堂內(nèi)的尸體忽然破棺而出端衰,到底是詐尸還是另有隱情,我是刑警寧澤甘改,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布旅东,位于F島的核電站,受9級特大地震影響十艾,放射性物質(zhì)發(fā)生泄漏抵代。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一疟羹、第九天 我趴在偏房一處隱蔽的房頂上張望主守。 院中可真熱鬧禀倔,春花似錦、人聲如沸参淫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涎才。三九已至鞋既,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間耍铜,已是汗流浹背邑闺。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留棕兼,地道東北人陡舅。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像伴挚,于是被迫代替她去往敵國和親靶衍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345