什麼是webpack ,本質上,webpack 是一個現代 JavaScript 應用程式的靜態模組打包器(module bundler)。當 webpack 處理應用程式時,它會遞迴地構建一個依賴關係圖(dependency graph),其中包含應用程式需要的每個模組,然後將所有這些模組打包成一個或多個 bundle.webpack 有哪些功能(程式碼轉換 檔案最佳化 程式碼分割 模組合併 自動重新整理 程式碼校驗 自動釋出)首先學習webpack 需要有簡單的node 基礎,開啟node官方網站進行安裝node, http://nodejs.cn/ 下載最新版node包並進行安裝
學習目標:
webpack 常見配置 webpack高階配置webpack最佳化策略AST抽象語法樹webpack中的Tapable掌握webpack流程 手寫 webpack手寫webpack中常見的loader手寫webpack 中常見的pluginwebpck--->基礎搭建與使用:
安裝完畢在終端 快速建立node專案 執行命令npm init -y 生成packge.json在當前目錄安裝本地webpack終端執行命令:npm i webpack webpack-cli -di 表示 install , d表示當前是開發環境安裝完成會產生node_modules檔案webpack 可以進行0配置 並且webpack是打包工具(預設是js模組 透過入口進行打包輸出打包後js結果)。建立src目錄 --> 建立index.js -> 輸出:console.log('hello webpack');npx 語法進行把index.js 進行打包終端執行命令:npx webpack我們發現當前目錄生成了一個dist 目錄並且建立了一個main.js(如圖:)
執行順序:(預設找node_modules--->bin檔案 --> webpack檔案 )
這裡我們明白了安裝webpack 必須安裝他的依賴 webpack-cliwebpack打包預設支援js模組化 ->類似於common.js
webpack:兩種默兩種模式如果沒有建立webpack.config.js 配置檔案指定mode (production/development)生成模式或開發模式,打包執行會直接預設生產模式打包並且進行壓縮。這裡說一下webpack配置檔案的預設名稱有兩種 (webpack.config.js / webpackfile.js 一般情況下我們會選擇前一種)
如何手動配置webpack呢?其實比較簡單
(1)建立webpack.config.js 配置檔案 由於webpack是node.js的框架所以配置檔案中要採用node語法來進行編輯。
const path = require("path"); //webpack內部方法path元件
module.exports = {
mode: "development", //打包模式 development開發模式
entry: "./src/index.js", //入口檔案指定
output: { //出口檔案配置 配置出口打包路徑
filename: "build.js", //打包後的檔名稱
path: path.resolve(__dirname, "build") //resolve絕對路徑引入
}
}
接收到modules 裡 先定義一個快取物件 installedModules先定一個快取目的是如果我當前模組載入完成沒有必要再進行載入webpack_require 實現了一個require方法因為瀏覽器無法直接執行node的require方法
執行__webpack_require__ 發現接收了一個入口模組
終端執行:npx webpack , 發現我們打包當前目錄產生了資料夾build目錄分析了一下打包檔案是不是感覺webpack 原始碼沒有想象的那麼難繼續我們webpack 的探索之旅。如何更改webpack配置檔名稱呢其實重新命名webpack.config.js (webpack.test.js)執行命令:
npx webpack --config webpack.test.js 發現可以執行webpack打包。這樣打包我發現命令很長所以我們利用packge.json 來配置打包指令碼在scripts-->新增build.
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config webpack.config.js"
}
終端執行 npm run build 發現執行打包結果一樣.
(2)webpack 其他配 -->置外掛的使用不會生成檔案會生成記憶體中的打包安裝webpck內建服務 webpack-dev-server 好處是終端執行命令: npm i webpack-dev-server -d -save安裝完成可以執行 npx webpack-dev-server 按提示開啟http://localhost:8080/如何配置開發服務執行目錄可以在配置檔案中新增在webpack.config.js新增devServer
const path = require("path");
module.exports = {
mode: "development", //打包模式
entry: "./src/index.js", //入口檔案指定
output: { //出口檔案配置 配置出口打包路徑
filename: "build.js", //打包的檔名稱
path: path.resolve(__dirname, "build") //resolve絕對路徑引入
},
devServer: { //開發伺服器配置
contentBase: "./build", //指向打包目錄
port: 3000, //服務埠號
progress: true, //打包進度
open: true, //是否開啟瀏覽器
compress: false //是否壓縮
}
}
在packge.json中新增start 啟動服務指令碼
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config webpack.config.js",
"start":"webpack-dev-server"
}
執行 npm run start 發現沒有自動建立index.html 不能直觀看到我們程式碼在瀏覽器的執行。在src目錄下建立html模板 index.html 並安裝 html-webpack-plugin 外掛
終端執行: npm i -d html-webpack-plugin在webpack.config.js 下新增外掛配置plugins
const path = require("path");
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "development", //打包模式
entry: "./src/index.js", //入口檔案指定
output: { //出口檔案配置 配置出口打包路徑
filename: "build[hash:8].js",
path: path.resolve(__dirname, "build") //resolve絕對路徑引入
},
devServer: { //開發伺服器配置
contentBase: "./build", //指向打包目錄
port: 3000, //服務埠號
progress: true, //打包進度
open: true, //是否開啟瀏覽器
compress: false //是否壓縮
},
//外掛
plugins: [ //陣列形式 存放所有的webpack外掛
new HtmlWebPackPlugin({
filename: "index.html", //生成打包檔名
template: "./src/index.html", //模板路徑
minify: { //生產模式可以進行配置
collapseWhitespace: true //摺疊空行
},
hash:true, //新增雜湊值
})
]
}
終端執行打包測試:npm run build (build目錄下生成了我們想要生成的index.html檔案)
樣式的配置 webpack配置css模組:
配置樣式需要一個合適loader,loader會將我們的樣式檔案解析成模組(module)終端:npm i -d --save css-loader style-loader如何使用樣式loader進行配置呢?我們先在src下建index.css並給body賦予簡單樣式在webpack.config.js 進行簡單配置css-loader主要解析我們樣式中@import語法,style-loader是把css樣式插入head標籤中.
module: { //新增模組模組是物件
rules: [ //規則 css-loader主要解析我們樣式中@import語法
{
test: /\.css$/,
use: ["style-loader", "css-loader"] //執行順序是從右向左執行 - >從下到上
}
]
}
在index.js中引入樣式檔案 import './index.css'終端執行:npm run start 樣式生效了同樣我們也有對應的less less-loader終端:npm i -d --save less less-loader在這裡說一下loader 的另一種寫法物件寫法可以給loader新增一些屬性options
module: { //新增模組模組是物件
rules: [ //規則 css-loader主要解析我們樣式中@import語法
{
test: /\.css$/,
use: [
{
loader: "style-loader",
options: {
insertAt: "top" //把標籤插入頂部
}
},
"css-loader"
] //執行順序是從右向左執行 - >從下到上
},
{
test: /\.less$/,
use: [
{
loader: "style-loader",
options: {
insertAt: "top" //把標籤插入頂部
}
},
"css-loader",
"less-loader"
] //執行順序是從右向左執行 - >從下到上
}
]
}
css 樣式的抽離 安裝抽離外掛 mini-css-extract-plugin npm i -d --save mini-css-extract-plugin引入外掛並在配置檔案中進行配置
const path = require("path");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MinCssExtractPlugin = require("mini-css-extract-plugin"); //抽離css外掛
module.exports = {
mode: "development", //打包模式
entry: "./src/index.js", //入口檔案指定
output: { //出口檔案配置 配置出口打包路徑
filename: "[name][hash:8].js",
path: path.resolve(__dirname, "build") //resolve絕對路徑引入
},
devServer: { //開發伺服器配置
contentBase: "./build", //指向打包目錄
port: 3000, //服務埠號
progress: true, //打包進度
open: true, //是否開啟瀏覽器
compress: false //是否壓縮
},
//外掛
plugins: [ //陣列形式 存放所有的webpack外掛
new HtmlWebPackPlugin({
filename: "index.html", //生成打包檔名
template: "./src/index.html", //模板路徑
minify: {
collapseWhitespace: true //摺疊空行
},
hash: true //新增雜湊值
}),
new MinCssExtractPlugin({
filename: "mian.css"
})
],
module: { //新增模組模組是物件
rules: [ //規則 css-loader主要解析我們樣式中@import語法
{
test: /\.css$/,
use: [
MinCssExtractPlugin.loader, //建立link標籤放入到main.css裡
"css-loader"
] //執行順序是從右向左執行 - >從下到上
},
{
test: /\.less$/,
use: [MinCssExtractPlugin.loader, "css-loader","less-loader"]
//執行順序是從右向左執行 - >從下到上
}
]
}
}
新增樣式字首 postcss-loader autoprefixernpm i postcss-loader autoprefixer -d
module: { //新增模組模組是物件
rules: [ //規則 css-loader主要解析我們樣式中@import語法
{
test: /\.css$/,
use: [
MinCssExtractPlugin.loader, //建立link標籤放入到main.css裡
"css-loader",
"postcss-loader"
] //執行順序是從右向左執行 - >從下到上
},
{
test: /\.less$/,
use: [
MinCssExtractPlugin.loader, //建立link標籤放入到main.css裡
"css-loader",
"postcss-loader",
"less-loader"
] //執行順序是從右向左執行 - >從下到上
}
]
}
注意postcss-loader需要新增一個配置檔案否則不會生效目錄建立postcss.config.js
module.exports = {
plugins: [require("autoprefixer")]
}
但是我們發現問題使用mini-css-extract-plugin外掛導致我們css不會被壓縮。npm 官網有給出To minify the output, use a plugin like optimize-css-assets-webpack-plugin. Setting optimization.minimizer overrides the defaults provided by webpack, so make sure to also specify a JS minimizer:
要使用optimize-css-assets-webpack-plugin 外掛接下來我們安裝配置一下.npm i -d optimize-css-assets-webpack-plugin
發現可以已經轉換es6語法 但是僅僅這樣不能轉換es6高階語法比如一些特殊的類函式
class Test {
// new Test() a =1 例項上新增a屬性 這個語法屬於es7語法打包時發現並不能解析
a = 1;
}
終端執行:npm run build 發現報錯提示安裝 @babel/plugin-proposal-class-properties
那我們按照要求按照查一下外掛 npm i -d @babel/plugin-proposal-class-properties 並進行一次配置
//在rules下新增配置
{
test: /\.js$/,
use: [
{
loader: "babel-loader",
options: { //轉化es5語法--presets預設
presets: ["@babel/preset-env"],
plugins: ["@babel/plugin-proposal-class-properties"]
}
}
]
},
還有一種寫法 裝飾器@Log打包也是不被解析的 在js 新增
//在rules下新增配置
{
test: /\.js$/,
use: {
{
loader: "babel-loader",
options: { //轉化es5語法--presets預設
presets: ["@babel/preset-env"],
plugins: [ //這裡要注意新增順序
["@babel/plugin-proposal-decorators", { legacy: true }],
["@babel/plugin-proposal-class-properties", { loose: true }]]
}
}
},
轉化完語法接下來看一下babel語法的校驗 @babel/plugin-transform-runtime @babel/runtime
{
test: /\.js$/,
use: {
loader: "babel-loader",
options: { //轉化es5語法--presets預設
presets: ["@babel/preset-env"],
plugins: [
["@babel/plugin-proposal-decorators", { legacy: true }],
["@babel/plugin-proposal-class-properties", { loose: true }],
[
"@babel/plugin-transform-runtime",
{
absoluteRuntime: false,
corejs: false,
helpers: true,
regenerator: true,
useESModules: false
}
]
]
}
},
include: path.resolve(__dirname, "src"), //只找__dirname - >src
exclude: /node_modules/ //忽略node_modulse
}
includes 例項方法不被解析 需要一個補丁模組@babel/polyfillnpm install --save @babel/polyfillBabel includes a polyfill that includes a custom regenerator runtime and core-js.使用可以直接在js 裡引入即可。接下來看一下程式碼校驗ESLint程式碼校驗工具終端安裝 npm i -d eslint eslint-loader根據專案需求下載對應的eslintrc.json
//程式碼校驗eslint
{
test: /\.js$/,
use: {
loader: "eslint-loader",
options: {
enforce: "pre" //強制執行順序
}
}
}
本文回顧 1、webpack基本功能 build.js 打包的原理及原始碼分析 2、webpack基礎配置及常用外掛配置安裝 3、loader的使用與配置樣式的處理 4、webpack最佳化項的簡單使用 5、babel語法轉換與使用 babel語法校驗 . 完成以上我相信大家可以掌握並搭建簡單webpack專案。