一篇文搞懂webpack[零基礎教學+手把手帶你搞專案]

2021-06-09 08:00:04

一 簡介

webpack現在可謂炙手可熱,要是不懂,就難免讓人覺得有點跟不上時代。

其實webpack只是一種工具,我們以使用為目的去學習它,就一點也不難哦,本篇文章讓您在一個小時內上手webpack,沒時間學習也可以先收藏哦。

webpack主要用於相容性處理,程式碼預處理轉換處理,壓縮處理。

如轉換ES6語法,轉換JSX 指令等

CSS字首補全/前處理器,程式碼壓縮混淆,圖片壓縮等。

webpack的組態檔預設為webpack.config.js。

webpack --config命令可用於指定組態檔。

二 新手上路

2.1 環境準備

安裝nodejs和npm,直接在nodejs官網下載安裝包即可,npm作為nodejs附屬包同時自動安裝,無需另外安裝。

使用nodejs安裝包安裝後可用命令列在cmd視窗檢視安裝版本。
在這裡插入圖片描述

2.2 建立專案

首先,建立專案目錄(空目錄),使用命令列建立一個初始化的package.json

npm init -y
在這裡插入圖片描述

向專案目錄中安裝webpack依賴,安裝後目錄中出現node_modules檔案。
npm install webpack webpack-cli --save-dev
在這裡插入圖片描述
注意到上文命令列中包含字尾 --save-dev,含義如下。

  • –save : dependencies 鍵下,釋出後還需要依賴的模組,譬如像jQuery庫或者Angular框架類似的,我們在開發完後後肯定還要依賴它們,否則就執行不了。
  • –save-dev : devDependencies 鍵下,開發時的依賴比如安裝 js的壓縮包gulp-uglify 因為我們在釋出後用不到它,而只是在我們開發才用到它。

主要區別在於打包後是否保留該依賴,webpack本身是打包工具,當然不需要保留啦。

安裝成功後檢視安裝情況

./node_modules/.bin/webpack -v

在這裡插入圖片描述

2.3 專案上手

現在我們就可以使用webpack做專案了,首先做一個最簡單的例子。

首先z在專案目錄中建立組態檔webpack.config.js,

'use strict'

const path = require('path'); // 引入一個依賴

module.exports = {
    entry: './src/index.js', // 入口
    output: { // 出口
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    mode: 'production'
};

在上面檔案中,我們指定入口為’./src/index.js’,輸出檔案在dist資料夾中,名字為’bundle.js’。

翻譯一下也就是,webpack會以’./src/index.js’為入口,將其與其所有的依賴打包為一個出口檔案’bundle.js’放置在目錄dist中。

我們首先建立檔案’./src/index.js’與其依賴檔案’./src/helloworld.js’。

在index.js中引入helloworld.js檔案。

// './src/index.js'
import { helloworld } from './helloworld';

document.write(helloworld());
// './src/helloworld.js'
export function helloworld() {
    return 'hello webpack'
}

此時專案結構如下圖。

在這裡插入圖片描述
檔案准備完畢,我們使用webpack命令列打包。

./node_modules/.bin/webpack

在這裡插入圖片描述

專案目錄下,出現了資料夾dist,其中含有bundle.js,與前面組態檔出口路徑與名稱對應。

在這裡插入圖片描述

可以看到,bundle.js檔案是入口檔案的整合版,執行效果與入口檔案是相同的,只是少了依賴而已。

剛剛使用./node_modules/.bin/webpack打包,未免繁瑣,這裡可以通過在package.json中對scripts新增設定的方式,設定快捷命令。

{
  "name": "webpackTest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^5.38.1",
    "webpack-cli": "^4.7.0"
  }
}
rm -rf dist // 刪除之前的打包檔案
npm run build // 打包檔案 生成與剛剛相同的檔案

三 webpack基礎用法

3.1 核心概念瞭解

入口 - entry

剛剛的組態檔中見過,用於指定打包檔案入口。

單入口情況下為字串,多入口情況下為key-value物件。

剛剛的範例為單入口檔案。

出口 - Output

剛剛的組態檔中見過,用於指定編譯後的檔案輸出。

// 單入口 單出口
module.exports = {
    entry: './src/index.js', // 入口
    output: { // 出口
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js'
    }
};
// 多入口 多出口
module.exports = {
    entry: {
    	app: './src/app.js',
    	search: './src/search.js'
    }
    output: { // 出口
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
    }
};

可以看到,對於多入口出口設定,output中內容沒有太大改變,其實是使用預留位置[name]來實現檔案動態命名的,打包後的dist目錄中,有著對應入口檔案的n個出口檔案,名稱與entry中的key值一致。

上面的組態檔中,打包結果為dist中出現兩個檔案,分別為app.js和search.js。

載入 - loaders

webpack原生支援js和json,通過loaders做其他檔案型別的轉換,如vue等,將其他檔案型別轉化為有效的模組,新增到依賴圖中。

本身是一個函數,接受原始檔作為引數,返回轉換的結果。

常見loaders:

babel-loader轉換ES6.ES7等
css-loader支援.css檔案的載入和解析
less-loader將less檔案轉換為css
ts-loader將TS轉換成JS
file-loader進行圖片 字型等的打包
raw-loader將檔案以字串的形式匯入
thread-loader多程序打包JS和CSS

用法

module.exports = {
	module: {
		rules: [
			{test:/\.txt$/,use:'raw-loader'} // 匹配規則 loader名稱
		]
	}
}

外掛 - Plugins

外掛,增強功能。作用於整個構建過程。

常用外掛

用法

module.exports = {
	plugins: [
		new HtmlWebpackPlugin({template: './src/index.html'})
		// 建立html檔案去承載輸出的bundle
	]
}

環境 - Mode

指定當前的構建環境是:production development none

預設為 production。

通過對mode的不同設定,可以使用webpack不同內建函數。

3.2 基礎解析-loaders使用

ES6 與 JSX

使用babel-loader完成。

npm i @babel/core @babel/preset-env babel-loader -D

在src同級目錄下建立babel組態檔.babelrc,書寫設定。

{
	"presets": [
		"@babel/preset-env"
	]
}

修改webpack組態檔。

rules: [
	{
		test:/.js$/,
		use: 'babel-loader'
	}
]

設定完成後檢視效果。

rm -rf dist
npm run build

此時已經解析成功了。

那如果是React語法如何解析呢。

安裝babel-react。

npm i react react-dom @babel/preset-react -D

修改babel組態檔.babelrc。

{
	"presets": [
		"@babel/preset-env",
		"@babel/preset-react"
	]
}

書寫一個簡單的react-js檔案,檔案的含義是將一個模板放置到一個DOM節點上。

npm run build 構建即可檢視效果。

將輸出的JS檔案放置到一個新建的html檔案中,檔案中含有對應的節點,就可以成功插入了。

CSS解析

解析CSS使用css-loader,將css轉換為commonjs物件,使用style-loader,將樣式通過

首先在專案中安裝兩個依賴。

npm i style-loader css-loader -D

在專案中建立css檔案,寫入一些樣式,並在剛剛的react的js檔案中引入使用。

在webpack組態檔中rules中新增loader。

    module: {
        ...
        rules: [
            {
                test: /.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }

再編譯,生成的js檔案,放置在html中就有對應效果了。

但是這時候還是沒有單獨的css檔案的,要將css檔案分離出來,要使用外掛extract-text-webpack-plugin。

也可以使用mini-css-extract-plugin,都是用來抽離css樣式,防止將樣式打包在js中引起頁面樣式載入錯亂的現象

extract-text-webpack-plugin 4.0的beta版本才支援webpack4.x 或者使用mini-css-extract-plugin
extract-text-webpack-plugin 預設版本 在webpack3.x可用

npm install extract-text-webpack-plugin --save-dev
var Ex = require('extract-text-webpack-plugin');
// ...省略
module: {
  loaders: [{
    test: /\.css/,
    loader: Ex.extract('style-loader', 'css-loader','less-loader')  // 單獨打包出CSS,這裡設定注意下
  }]
},
plugins: [
  new Ex("[name].css")
]

如果我們想要一個載入器陣列,我們必須使用use,如果它只是一個載入器,那麼我們必須使用loader。

Less解析

安裝less和less-loader依賴。

npm i less less-loader -D

將剛剛的css檔案轉換為less檔案,之後在webpack中設定rules。

	{
		test: /.less$/,
		use: [
			'style-loader',
			'css-loader',
            'less-loader'
		]
	}

然後打包檢視效果即可。

解析圖片

使用file-loader處理檔案。

在src目錄下放置圖片logo.png,並在專案中引入使用。

npm i file-loader -D

在webpack組態檔中設定使用。

{
	test: /.(png|jpg|gif|jpeg)$/,
	use: 'file-loader'
}

打包即可。

解析字型

與圖片相同使用file-loader。

剛剛已經安裝過依賴了,無需再安裝,我們直接在css中引入和使用字型即可。

在webpack組態檔中新增設定。

{
	test: /.(woff|woff2|eit|ttf|otf)$/,
	use: 'file-loader'
}

然後打包編譯即可。

四 webpack檔案監聽

檔案監聽是指在發現原始碼發生變化時,自動構建新的輸出檔案。

webpack開啟監聽模式,有兩種方式。

  • 啟動webpack命令時新增–watch引數。
  • webpack組態檔中新增watch:true。

首先我們使用第一種方式。

在package.json的scripts中新增設定watch。

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "watch": "webpack --watch"
  },

然後執行構建的時候,使用 npm run watch構建。

webpack會輪詢判斷檔案的最後編輯時間是否變化,變化後會等待一段時間後執行。

剛剛說了第二種方式,也可在組態檔中設定。

webpack相關設定。

module.export = {
	// 預設false 也就是不開啟
	watch: true,
	// 只有開啟監聽模式時下面的設定才有效
	watchOptions: {
		// 忽略的檔案 預設為空
		ignored:/node_modules/,
		// 監聽後等待時候 預設300
		aggregateTimeout:300,
		// 輪詢時間 預設1000
		poll:1000
	}
}

如此,當我在編輯了檔案的時候,儲存後webpack就會自動編譯。

五 功能優化-plugins使用

5.1 webpack熱更新

剛剛新增了自動構建功能,但是構建完成後需要我們手動重新整理瀏覽器,瀏覽器的自動重新整理在webpack中也有體現,就叫做熱更新。

也就是webpack-dev-server。

安裝該包依賴。

npm i webpack-dev-server -D

我們在在package.json的scripts中新增設定dev。

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "watch": "webpack --watch",
    "dev": "webpack-dev-server --open"
  },

在webpack設定中引入並註冊熱更新外掛,並進行設定。

// webpack.config.js
const webpack = require('webpack');
// webpack.config.js
plugins: [
	new webpack.HotModuleReplacementPlugin()
],
devServer: {
	contentBase: './dist',
	hot:true
}

熱更新的內容不會儲存到磁碟,而是放置在記憶體中。

這時可能會有一個報錯:

Cannot find module 'webpack-cli/bin/config-yargs'

是因為webpack-cli的新版本對webpack-dev-server版本的不相容,之後降低webpack-cli的版本為 "^3.3.12"

npm i webpack-cli@3.3.12 -D 就ok了。

5.2 程式碼壓縮

JS壓縮

webpack已經內建了uglifyjs-webpack-plugin外掛進行JS壓縮。

CSS壓縮

使用外掛optimize-css-assets-webpack-plugin,同時使用cssnano。

安裝依賴。

npm i optimize-css-assets-webpack-plugin
npm i cssnano -D

參照外掛。

plugins: [
	...,
	new OptimizeCSSAssetsPlugin({
		assetNameRegExp: /.css$/g,
		cssProcessor: require('cssnano')
	})
]

然後打包,打包成的就是壓縮的css了。

html壓縮

設定外掛html-webpack-plugin,設定壓縮引數。

在html中新建html模板。

在webpack組態檔中引入html-webpack-plugin。

import HtmlWebpackPlugin = require(html-webpack-plugin)

在組態檔中設定外掛。

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

module.exports = {
  ...
  plugins: [new HtmlWebpackPlugin()],
};

上面是最簡單用法,這將會生成一個包含以下內容的 dist/index.html 檔案。

如果你有多個 webpack 入口,他們都會在已生成 HTML 檔案中的 <script> 標籤內引入。

如果在 webpack 的輸出中有任何 CSS 資源(例如,使用 MiniCssExtractPlugin 提取的 CSS),那麼這些資源也會在 HTML 檔案 <head> 元素中的 <link> 標籤內引入。

也可以為這個外掛傳入一寫引數,來指定入口html等值。