iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 21
1
Modern Web

前端三十 - 成為更好的前端工程師系列 第 21

21. [FE] 用過 Webpack 之類的打包工具嗎?為什麼需要?

backpack

隨著網頁技術不斷翻新,前端需要處理的事也就越來越繁雜;在 2016 年有一篇當時很紅的文章,詼諧的故事除了是技術名詞科普之外,同時也諷刺了前端技術的瘋狂增長,蠻推薦沒看過的讀者看一下的。在這樣龐雜豐富且迅速更迭的技術環境之下,將開發流程自動化、工程化就成了必需,開發者也自然會需要一些工具來協助優化這些流程。今天就讓我們一起聊聊前端的打包工具。

筆者撰文的時候,將該文章重看一次,發現比三年前第一次看的時候多理解不少,雖然還不到 100% 清楚,但總歸算得上是有成長吧XD

前端工程化

工程化的起點,自然是從 Node.js 問世,套件管理工具 npm 誕生開始。透過 npm ,開發者便能快速且輕易的從 NPM Registry 下載到其他開發者提交的套件,並加在自己的專案中;除此之外,npm 也提供了 script 的功能,將 shell script 封裝成別名快速使用:

{
  "scripts":{
    "dev": "node app.js"
  }
}

例如上例,當開發者輸入 npm run dev,就等同於執行了 node app.js 這行指令;透過這樣簡短的 script 設定,也確實可以解決一些基本的需求。

Grunt

Grunt

但其實大部分需求在開發過程中,重複性是非常高的。例如將 SASS、SCSS 編譯成 CSS,透過 npm script,就需要修改完、輸入指令進行編譯、Reload,開發者的開發體驗便會大打折扣;要解決這樣的情況,Grunt 是一個不錯的解決方案。

Grunt 提供了更大的程式化空間,讓開發者能更自由的控制自動化流程;藉由大量的插件(plugin),以及高度客製化的設定,開發者可以輕易的完成一些常見的任務。

例如 昨天 提到的 Uglify,就可以透過 grunt-contrib-uglify 這個套件,幫我們自動完成這樣繁瑣的步驟。

Gulp

Gulp

但 Grunt 的設定是大多是每個插件個別設定,一旦專案中的插件數量增加,設定跳來跳去,同一支原始檔案的去向很容易就變得難以追蹤;Gulp 透過管道(Pipes)及串流(Streams)的概念,便能有效避免前述的情況發生。

例如我們想要將 LESS 編譯成 CSS,再將檔案進行最小化(minify)處理,Gulp 中的設定可能會這樣寫:

function css() {
  return src('assist/style/*.less')
    .pipe(less())
    .pipe(minifyCSS())
    .pipe(dest('dist/css'))
}

藉由 pipe 函式,將任務結果依序往後傳遞,同檔案類型會經過什麼處理,也就變得一目了然;除此之外,Gulp 相較於 Grunt 還多了檔案監看、檔案讀寫等功能,將許多繁雜的基礎功能都得以自動化,開發者的開發流程也能因此省上不少力!

更多 Gulp 的說明及範例,可以參考 廖洧杰 的 Gulp.js 自動化前端任務流程

Webpack

Webpack

但隨著前端的演進,開發流程又更加複雜,針對檔案類型做處理已經不能滿足開發者的需求;加上資源量越來越多,在 HTTP/1.1 有單一網域請求數上限 的情況下,勢必需要將前端的程式分開包裝,才能夠將資源傳遞給使用者。

熱門套件 Webpack 則給出了一個全新的思考模式;藉由定義專案的 entryoutput,Webpack 便會從 entry 開始解析專案,最後將相依的檔案打包成指定的 output;除此之外,也可以在過程中間加上 loaderplugins,對需要的檔案做進一步的處理。

同樣拿 CSS 來看看好了,這次將 SCSS 依序處理成 CSS:

rules: [
  {
    test: /\.(scss)$/,
    include: [path.resolve(__dirname, 'app')],
    loader: ExtractTextPlugin.extract({
      fallback: 'style-loader',
      use: [
        {
          loader: 'css-loader',
          options: {
            modules: false,
            minimize: true,
            sourceMap: true,
            importLoaders: 3,
          },
        },
        {
          loader: 'postcss-loader',
          options: {
            sourceMap: true,
            config: {
              path: path.resolve(__dirname, 'postcss.config.js'),
            },
          },
        },
        {
          loader: 'resolve-url-loader',
          options: {
            sourceMap: true,
          },
        },
        {
          loader: 'sass-loader',
          options: {
            sourceMap: true,
          },
        },
      ],
    }),
  },
  //...
]

透過上述設定,將會依序透過 sass-loaderresolve-url-loaderpostcss-loadercss-loaderstyle-loader 對副檔名為 .scss 的檔案做處理,其餘檔案類型也能夠設定、搭配相對應的 loader,將前端的內容封裝、打包。

更多打包工具

看到一堆設定是不是快瘋掉了?那還只是冰山一角呢。這也是 Webpack 最讓人詬病的問題;Webpack 提供開發者更高的自由度,同時卻也帶來更多的複雜度;但在一般的中小型專案,可能根本不需要那些繁雜的設定,這時候用 Webpack 就有點殺雞用牛刀了。

開源社群中有一些新的打包工具,都能讓開發者可以減少撰寫龐大設定的痛苦,並享用自動化流程的便利;例如專注在 Node.js 後端專案的Backpack,號稱是新一代打包工具的 Rollup,及完全無設定便能直接使用的 Parcel,都是筆者我認為很值得關注的打包工具。

打包工具的用途

說了那麼多打包工具,用途到底是什麼呢?不外乎是以下幾點:

轉譯

我們在 前幾天 有稍微提到了前端三大框架,相信這也是不少開發者接觸打包工具的起點。由於前端框架提供了許多額外的語法,但瀏覽器只能解讀 JavaScript,中間必須要經過一個轉換的步驟,將開發者撰寫的程式,轉譯成瀏覽器能解讀的內容。

例如前面舉例的 LESSSASS 會透過 postcss 做相對應的處理;React 用的 JSX 語法,Vue 的 .vue 檔、ES6+ 的語法等等,則會透過在 本系列文的這一篇 提到過的 Babel,做程式碼的轉譯;有了打包工具轉譯程式碼,開發者也就可以自由使用更新的框架、更精簡的語言特性,不用太擔心支援度的問題。

優化程式

針對程式進行效能優化是非常重要的一環,也因為其繁瑣的流程設定,打包工具在優化程式這塊能充分的給予協助。

例如 昨天 我們聊到的優化手段,幾乎所有的內容,Webpack 都能找到相對應的插件協助開發者處理;例如 minify、uglify、切分 chunk 等等。關於這部份,筆者先前有撰寫過相關的內容,有興趣的讀者可以移步到 我的 Blog 參考。

加速開發

例如為了減少前端請求數目的 CSS Sprite,比起用 PS 慢慢對齊、計算 CSS 屬性,還不如透過打包工具的套件例如 Webpack Spritesmith,來完成圖檔合併的工作;其他像是 Webpack 的 Dev Server 內建的 Hot Reload 功能,網頁開發者就不用一直手動重新整理頁面了。

加上前面的轉譯及優化程式,將原本需要手動處理的事情,全部交給打包工具處理,再透過設定妥當的自動化流程,讓開發者寶貴的時間不用再去做週期性的繁瑣雜事。

結語

今天很快速的將打包工具的演進瀏覽了一圈,過程中提供幾個簡易小範例,並大致說明打包工具的用途,最後與昨天提到的程式優化做呼應。在網站內容不斷增加,開發流程逐漸趨近工程化的現在,嘗試去使用、理解這些能協助建置自動化開發流程的套件,可以讓開發者有效地省下大量的時間。

那麼今天的內容就到這邊啦,我們大家明天見~

參考資料

筆者

Gary

半路出家網站工程師;半生熟的前端加上一點點的後端。
喜歡音樂,喜歡學習、分享,也喜歡當個遊戲宅。

相信一切安排都是最好的路。


上一篇
20. [FE] 如何提升網站效能?
下一篇
22. [FE] 為什麼跨域請求會產生錯誤?如何處理?
系列文
前端三十 - 成為更好的前端工程師31

尚未有邦友留言

立即登入留言