iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 16
0

早安,昨天介紹完模組化,今天我們來討論現在最火紅的自動化模組化打包工具巴。

Webpack

一樣先依照慣例進入 www 時間

  1. What Webpack?? Webpack 是什麼?

    • 官網:本質上,webpack 是一個用於現代 JavaScript 應用程序的靜態模塊打包工具。當 webpack 處理應用程序時,它會在內部構建一個 依賴圖(dependency graph),此依賴圖對應映射到項目所需的每個模塊,並生成一個或多個 bundle。
    • 翻譯:它是一個「打包工具」。將眾多模組與資源打包成一包檔案,並編譯我們需要預先處理的內容,變成瀏覽器看得懂的東西,讓我們可以上傳到伺服器。
    • 前端日新月異,我們寫的內容已不只是寫 HTML、CSS、JavaScript 單純的檔案。前端出現了許多預處理工具及框架,預處理工具如 PUG、SASS、Babel;框架如 Vue、React。不過瀏覽器並看不懂我們寫的預處理內容,每每都需要透過編譯才能使用,也因此出現了自動化工具,Webpack、Gulp、Grunt、Parcel、Browserify…等。
  1. Webpack會做什麼??

    • 打包(Bundle)多個 .js 檔案成單一檔案。
    • 你可以寫模組化的 JavaScript,你不再需要在 HTML 中引入每個 JavaScript 檔案
      <script src="..."></script>,如果有眾多的 .js 檔案,可以透過 Webpack 來設定。
    • 使用 NPM Packages
    • 撰寫 JavaScript ES6 或以上
    • 需要 babel 協助轉譯
    • 最小化、優化程式碼
    • 編譯 LESS 或 SCSS 成 CSS
    • 使用 HMR(Hot Module Replacement)
    • 包含任何類型的檔案到 JavaScript
    • CommomJS、AMD、ES6 Modules、CSS、Images、JSON、Coffeescript、LESS
  2. webpack 幾本概念

    entry [入口] :

    webpack 運作的方式是透過指定一個單一檔案作為你的進入點。 這個檔案會是 tree 的 root。然後你每次 require 一個檔案從其他檔案並把它加入到 tree。
    當你執行 webpack,所有的檔案和 module 都會被 bundle 成一個檔案。

    //webpack.config.js
    
    module.exports = {
       entry: './path/to/my/entry/file.js'
    };
    
    

    output 出口:

    告訴 webpack 在哪裡輸出它所創建的 bundle,以及如何命名這些文件。主要輸出文件的默認值是 ./dist/main.js,其他生成文件默認放置在 ./dist 文件夾中。

    //webpack.config.js
    
       const path = require('path');
    
        module.exports = {
          entry: './path/to/my/entry/file.js',
          output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'my-first-webpack.bundle.js'
          }
        };
    
    

    在上面的示例中,我們通過 output.filename 和 output.path 屬性,來告訴 webpack bundle 的名稱,以及我們想要 bundle 生成(emit)到哪裡。
    而上面的path 模塊是一個 Node.js 核心模塊,用於操作文件路徑。

    loader :

    webpack只能理解JavaScript和JSON文件,這是webpack開箱可用的自帶能力。loader讓webpack能夠去處理其他類型的文件,並將它們轉換為有效模塊,以供應用程序使用,以及被添加到依賴圖中。
    在 webpack 這些東西我們稱為 loader。使用這些 loader,你可以 require 任何 .css 和 .png 到 .html 檔。

    也就是說這些loader會把.css 和 .png 到 .html 檔轉換成各種 js 模組。

    //webpack.config.js
    
       const path = require('path');
    
       module.exports = {
         output: {
           filename: 'my-first-webpack.bundle.js'
         },
         module: {
           rules: [
             { test: /\.txt$/, use: 'raw-loader' }
           ]
         }
       };
    
    

    以上配置中,對一個單獨的 module 對象定義了 rules 屬性,裡麵包含兩個必須屬性:test 和 use。這告訴 webpack 編譯器(compiler) 如下信息:

    “ 嘿,webpack 編譯器,當你碰到「在 require()/import 語句中被解析為 '.txt' 的路徑」時,在你對它打包之前,先 use(使用) raw-loader 轉換一下。 ”

    plugin 外掛

    想像一下你使用 webpack 將你的檔案 bundle 在一起,然後你發現到 bundle 後的結果是 900KB。這裡有個問題,但是你可以透過 minify 你的 bundle 檔案來做改善。如果需要做到這一點,你需要使用一個我在前面稍早提到的 UglifyJsPlugin plugin。

    //webpack.config.js
    
    const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
     const webpack = require('webpack'); // 用于访问内置插件
    
     module.exports = {
       module: {
         rules: [
           { test: /\.txt$/, use: 'raw-loader' }
         ]
       },
       plugins: [
         new HtmlWebpackPlugin({template: './src/index.html'})
       ]
     };
    
    

    mode(模式):

    這是webpack特有的環境變數處理方式

    通過選擇development, production或none之中的一個,來設置mode參數,你可以啟用webpack內置在相應環境下的優化。其默認值為production。

    歐買尬我到底在說什麼,怎麼把mode講解得比"高等微積分還難哩" (( 小弟我是數學系QQ
    ,這一步我會多舉幾個範例說明

    • 配置方式:
//webpack.config.js
   
   module.exports = {
      mode: 'production'
    };
//範例來自Vue源碼 /vue-server-renderer/index.js
  try {
    var vueVersion = require('vue').version
  } catch (e) {}

  var packageName = require('./package.json').name
  var packageVersion = require('./package.json').version
  if (vueVersion && vueVersion !== packageVersion) {
    throw new Error(
      '\n\nVue packages version mismatch:\n\n' +
      '- vue@' + vueVersion + '\n' +
      '- ' + packageName + '@' + packageVersion + '\n\n' +
      'This may cause things to work incorrectly. Make sure to use the same version for both.\n'
    )
  }
// 小提醒這裡的意思是在vue-cli-service build和vue-cli-service test指令 載入這些包
  if (process.env.NODE_ENV === 'production') {
    module.exports = require('./build.prod.js')
  } else {
    module.exports = require('./build.dev.js')
  }  

就像上面範例中的 if(process.env.NODE_ENV === 'production')

webpack可以利用控制mode來設置process.env.NODE_ENV的值,並在哪些情況下,甚麼東西應該被載入。

瀏覽器支援度

不支持IE8及以下版本

環境限制

webpack在Node.js版本8.x和更高版本上運行。

參考資料

webpack官網(https://webpack.docschina.org/concepts/)
如何用Webpack來打包JavaScript、SCSS/CSS、HTML網頁和任意檔案?(https://magiclen.org/webpack/)
什麼是Webpack? 能吃嗎?(https://medium.com/i-am-mike/%E4%BB%80%E9%BA%BC%E6%98%AFwebpack-%E4%BD%A0%E9%9C%80%E8%A6%81webpack%E5%97%8E-2d8f9658241d)
webpack初學者課程(https://neighborhood999.github.io/webpack-tutorial-gitbook/Part1/)
webpack 新手教學之淺談模組化與 snowpack(https://blog.techbridge.cc/2020/01/22/webpack-%E6%96%B0%E6%89%8B%E6%95%99%E5%AD%B8%E4%B9%8B%E6%B7%BA%E8%AB%87%E6%A8%A1%E7%B5%84%E5%8C%96%E8%88%87-snowpack/)


上一篇
模塊 Module
下一篇
模塊打包工具 rollup
系列文
想成為超級開源貢獻者嗎 ? 新手也能用Javascript寫出專業高效能的"新世代"開源庫30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言