天天看點

《前端之路》之 webpack 4.0+ 的應用建構

目錄

  • 一、版本
  • 二、webpack 的主體概念
    • 2-1、入口
    • 2-1-1、單頁面入口
      • 2-1-1-1、實作的寫法:
      • 2-1-1-2、同樣也可以通過對象文法來解決不同場景的問題:
    • 2-1-2、多頁面應用的入口
    • 2-2、輸出
      • 2-2-1、單頁面 輸出
      • 2-2-2、多頁面 輸出
    • 2-3、loader
      • 2-3-1、如何編寫一個 loader
    • 2-4、plugins
      • 2-4-1、如何編寫一個plugins
  • 三、如何使用
    • 3-1 關于 resolve 解析的相關的疑問
      • 3-1-1 resolve.alias
      • 3-1-2 resolve.extensions
    • 4-1 優化(optimization)
      • 4-1-1 optimization.minimize
      • 4-1-2 optimization.splitChunks
    • 5-1 插件(plugins)
    • 6-1 開發中 server (devServer)
  • 四、總結

目前 webpack 版本 : v4.18.0
webpack -v
// 4.18.0
           

同之前的版本不一樣的地方是需要 全局安裝 webpack-cli

webpack-cli -v
// 3.1.0
           
思考這個 webpack-cli 是真的有用麼? 其實對于我來講感覺很雞肋,雖然它是出現是為了讓我webpack 零配置化,但就目前 webpack-cli 的體驗來講,還是比較雞肋,在實際的開發過程中,我還是比較喜歡 diy ,這樣自由的折騰方式, 零配置,就意味着你要為 高度定制化作出犧牲。
這讓我想起了之前面試很多前端開發的時候,其實就是一個很簡單的問題,如何搭建一個最簡單的 webpack 的開發架構,JS 壓縮一下, LESS 預編譯一下, CSS 壓縮一下。這類,很多習慣了用 vue-cli 的同學就懵逼了,因為他們認為 架構就是用别人的東西,但實際的開發中,出于業務需求的需要,我們的架構需要更加多的靈活性和高度可定制化性。 是以這才是寫這篇文章的 出發點。

開局一張圖:
《前端之路》之 webpack 4.0+ 的應用建構

本質上,

webpack

是一個現代 JavaScript 應用程式的靜态子產品

打包器

(static module bundler)。在 webpack 處理應用程式時,它會在内部建立一個依賴圖(dependency graph),用于映射到項目需要的每個子產品,然後将所有這些依賴生成到一個或多個bundle。

在開始前我們需要先了解它的

核心概念

  • 入口(entry)
  • 輸出(output)
  • loader
  • 插件(plugins)

入口起點(entry point)

這裡是一切開始的起點。面對實際的業務來講的話,可以分為單頁面( SPA ) 和多頁面。那麼今天就針對這2種情況來分别 介紹下 利用 webpack 進行項目架構的需要注意的地方。

webpack.config.js
module.exports = {
	entry: './app.js'
}
           

module.exports = {
	entry: {
		app: './app.js',
		vendors: './src/JQ.js'
	}
}
           

module.exports = {
  entry: {
    pageOne: './src/pageOne/index.js',
    pageTwo: './src/pageTwo/index.js',
    pageThree: './src/pageThree/index.js'
  }
};
           

但是這裡隻是人工的去配置了多頁面,其實很明顯這種做法很不聰明。

是以你需要一個聰明的做法,這裡就大緻講一下思路。 通過

( ' ./src/**/*.js' ) 比對到 多頁面到檔案入口路徑,然後 通過 glob.sync(globPath)

擷取到全部路徑,拿到每個頁面的 入口檔案路徑。 最後傳值給 webpack 的 entry 對象。

module.exports = {
  output: {
    filename: 'bundle.js',
    path: '/home/proj/public/assets'
  }
};
           

module.exports = {
  output: {
    filename: '[name].js',
    path: __dirname + '/dist'
  }
};
           

這裡的 loader 就像一個又一個的加工廠一樣,把你輸送給 加工産的原材料加工生成你想要的成品或者半成品。最後出廠~

有用過 gulp 類似的建構工具等同學 就很 容易了解,這裡的一個個的 loader 就想當一一個個的 task, 這個任務完成就會交給下一個人,直到整個流水線工作跑完~

在更高層面,在 webpack 的配置中 loader 有兩個特征(demo):

const path = require('path');

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

其中有三個需要注意的地方:

1、loader 的特征之一:

test

屬性,用于辨別出應該被對應的 loader 進行轉換的某個或某些檔案。

2、loader 的特征之二:

use

屬性,表示進行轉換時,應該使用哪個 loader。

3、在 webpack 配置中定義 loader 時,要定義在

module.rules

中,而不是

rules

前期這裡也隻是大概的了解一下,在後面的文章中,我們會手把手的教你 手寫一個 loader

這篇文章還隻是教你如何使用 webpack。 敬請期待後面的文章吧 😁

插件是 webpack 的

支柱

功能。webpack 自身也是建構于,你在 webpack 配置中用到的相同的插件系統之上!

插件目的在于解決 loader

無法實作

的其他事。

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader'
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
}

           

一樣的,前期這裡也隻是大概的了解一下,在後面的文章中,我們會手把手的教你 手寫一個 plugins

在上面的文章中,我們已經大緻介紹了 webpack 的概念,下面就是需要我們來配置一個 可以實際使用的項目。

webpack基礎配置項目位址

建立 import 或 require 的别名,來確定子產品引入變得更簡單。例如,一些位于 src/ 檔案夾下的常用子產品:
module.exports = {
  //...
  resolve: {
    alias: {
	  'vue$': 'vue/dist/vue.common.js',
      'src': path.resolve(__dirname, './src/src/'),
      'assets': path.resolve(__dirname, './src/assets/'),
      'components': path.resolve(__dirname, '../src/components')
    }
  }
};
           

有了上面的配置後,在項目檔案中如果需要引用 components 檔案夾下面的某個元件的時候 就可以 直接 如下的引用方式:

import Alert from 'component/alert'
           

這樣就可以 忽略因為項目檔案過深而引起的 引用元件路徑出錯的問題,進而加快效率。

自動解析确定的擴充。預設值為:
module.exports = {
  //...
  resolve: {
    extensions: ['.wasm', '.mjs', '.js', '.json']
  }
};
           

這樣的話,就會幫你把未加上 字尾名的檔案自動加上配置字尾,進而加快開發效率。

當然也是按照你所給出的檔案路徑去比對的字尾,而不是随意加上字尾名。

關于 resolve 解析 的内容還有很多,大家可以參考 webpack 官方文檔去尋找自己需要的内容,讓自己開發項目的速度變得更加快捷友善。

在 4.0 以後的 webpack 版本,他們專門把 optimization 提取出來作為一個大的子產品來進行了優化,因為這個功能實在是太能有效的提升項目的加載速度了。為什麼會這麼說呢?下面我們就來了解了解~

我們先來看一個簡單的配置:

module.exports = {
  //...
  optimization: {
    minimize: false
  }
};
           

這個屬性是一個 布爾類型,是告訴 webpack 我們是否在目前環境下去壓縮混淆我們的 JS 代碼。

當然 需要配合這個屬性來使用的還有一個

插件

主要注意:

UglifyjsWebpackPlugin

這個屬性是在 webpack 4.0 + 才提供的。用來 分離切割 體積較大的 JS 檔案。

然後 webpack 會自動将 通用的 chunk 進行分割,進而最大限度的做到

複用

,進而減少 main chunk 的體積。

plugins

選項用于以各種方式自定義 webpack 建構過程。webpack 附帶了各種内置插件,可以通過

webpack.[plugin-name]

通路這些插件。

webpack 插件清單。例如,當多個 bundle 共享一些相同的依賴,CommonsChunkPlugin 有助于提取這些依賴到共享的 bundle 中,來避免重複打包。這裡還是舉例說明:

module.exports = {
  //...
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      filename: 'vendor-[hash].min.js',
    })
  ]
};
           
這裡 CommonsChunkPlugin 就會告訴 webpack 讓它把 多個 bundle 共享一些相同的依賴,抽離出來,形成一個單獨的 bundle 進而避免重複打包而帶來的性能損耗。

這裡的重要部分就是 webpack-dev-server 這個插件了。

webpack-dev-server 建立目前本地開發的node環境,進而才能有上面種種 webpack 對于檔案的操作權限,才能為所欲為,這個是基本。我們還是來一個最簡單的 demo。
module.exports = {
  //...
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,   
    port: 9000
  }
};
           

這裡面也有非常多的 屬性配置,基本滿足了我們開發中遇到的大多數的問題。

基本上完成了上面文章中介紹到的内容,我們就已經可以完成基本的 webpack 配置的功能了, 注意: 這裡說到的是 基本的 webpack 的配置工作,那麼在我們的實際的項目開發中,我們會遇到的問題和需要我們通過webpack 來解決的問題非常之多。
因為我們需要結合一系列的架構來完成我們的前端開發的工作,React、Vue、Angular、JQ,Backbone 等等等。 這系列的架構 風格各異,但是又萬變不離其宗,核心需要注意的地方就那麼多,下一篇文章就會 講到一個 現代 前端開發 需要注意的一個重要 插件。

Babel

關于 webpack 入門的文章就介紹到這裡了,歡迎一起來論道~
GitHub 位址:(歡迎 star 、歡迎推薦 : )

前端 webpack 4.0 的應用建構

歡迎推薦,歡迎 star