在三大框架潮流的推動下,大大小小的SPA
單頁面應用層出不窮,工程化 / 模塊化 / 自動化 漸漸成爲開發的核心思想,但是他們都有一個特點:
源代碼無法在瀏覽器裏直接運行,必需通過編譯才行
因此也帶來了很多構建工具的興起;諸如具有代表性的 Gulp
、Grunt
、webpack
等等
今天,我們具體介紹 webpack 4.X
,webpack
也從V1過渡到V4,不久之後發佈V5版本( lz學不動了!!!)
一、初始化安裝
建議node
版本在 5.0以上
npm init // 可選屬性創建 | npm init -y // 自動創建
npm webpack -D
npm webpack-cli -D
安裝完,執行 webpack -v
| webpack-cli -v
,驗證是否安裝成功
二、搭建項目
這裏我們基礎配置index.html
用於測試我們的打包後的效果,webpack.config.js
用來配置編譯需求,src
項目源碼,package.json
項目基本配置
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack 4.X</title>
</head>
<body>
<div id="root"></div>
<script src="./dist/build.js"></script>
</body>
</html>
webpack.config.js
webpack
採用CommonJS
的規範,moudle.exports
導出
const path = require('path') // node提供的path工具,用來做路徑的拼接、轉換等
const fs = require('fs') // node提供的fs文件系統,用來操作文件、文件夾等
module.exports = {
mode: 'development ',
entry: '',
output: {},
module: {},
plugins: [],
devServer: {}
}
src
– index.js
入口文件
– home.js
測試多入口文件
– assets
靜態資源
:::-- img
圖片
:::-- font
字體文件
:::-- media
音視頻文件
:::-- css
樣式文件
package.json
這裏我們使用 npm run test 命令啓動 webpack 編譯
...
"scripts": {
"test": "webpack -p --progress --color --config webpack.config.js"
},
webpack
執行命令之後可以添加一些參數,下面是參數列表:
參數名 | 作用 |
---|---|
webpack --config XXX.js | 使用另一份配置文件來打包 |
webpack --watch | 監聽變動並自動打包 |
webpack -p | 壓縮混淆腳本,這個非常非常重要! |
webpack -d | 生成map映射文件,告知哪些模塊被最終打包到哪裏 |
webpack --progress | 顯示進度條 |
webpack --color | 添加顏色 |
三、基礎配置
webpack
從 編譯 -> 輸出 -> 運行 等等都是由很多配置內容完成
webpack
的核心配置:- 1.
mode
:模式----4.X新增,配置當前環境 - 2.
entry
:入口----要打包的文件 - 3.
output
:出口----配置編譯完成目錄 - 4.
module
:模塊----瀏覽器不識別的文件 - 5.
plugins
:插件----hook函數輔助開發,提高開發效率 - 6.
devServer
:服務器----webpack提供的本地服務器
mode
-
作用:代表當前的環境:
development
代表開發模式,production
(默認)代表生產模式 -
區別:mode
entry
-
作用:將要打包的入口文件
-
可選類型:String | Array | Object
// String
entry: './src/index.js',
// Array
entry: ['./src/index.js', './src/home.js'],
// Object
entry: {
'path/js': './src/index.js',
home: './src/home.js'
}
output
- 作用:向硬盤寫入編譯文件配置
- 屬性:↓↓↓↓↓↓↓
屬性名 | 作用 |
---|---|
filename | 向硬盤寫入編譯文件的名稱 |
path | 向硬盤寫入編譯文件的絕對路徑 |
publicPath | 指定資源文件引用的目錄 |
①:當entry
爲String
時,編譯入口文件並輸出
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'build.js',
path: path.resolve(__dirname, 'dist'),
}
}
②:當entry
爲Array
時,編譯入口文件合併輸出
const path = require('path')
module.exports = {
mode: 'development',
entry: ['./src/index.js', './src/home.js'],
output: {
filename: 'build.js',
path: path.resolve(__dirname, 'dist'),
}
}
③:當entry
爲Object
時,編譯多個入口文件並輸出
entry
入口指定多個key
,value
時,output
的filename
要注意,不可寫死entry
入口的key
可以指定爲路徑(多頁面),編譯輸出也是路徑entry
入口的value
可以指定數組形式,編譯合併輸出
const path = require('path')
module.exports = {
mode: 'development',
entry: {
vendor: ['./src/index.js', './src/home.js'], // 合併打包爲輸出爲vender.js
'path/index': './src/index.js', // 路徑模式打包
home: './src/home.js' // 打包輸出爲home.js
},
output: {
filename: '[name].[hash:7].[ext]', // path原名/路徑指定hash輸出
path: path.resolve(__dirname, 'dist'),
}
}
module
- 介紹:
webpack
中任何一個東西都稱爲模塊(css/img/video/woff
…),而且只識別js
。 - 作用:藉助
loader
編譯js
爲供瀏覽器識別
①:處理 CSS
install
npm i style-loader -D — 把處理完的 css 插入到 style 標籤裏
npm i css-loader -D — 處理 css
npm i postcss-loader -D — 處理不用的瀏覽器廠商前綴
npm i autoprefixer -D — 搭配 postcss-loader 個性化配置
瀏覽器 | 內核 | 前綴 |
---|---|---|
Chrome、Safari | webkit | -webkit- |
Firefox | gecko | -moz- |
Opera | presto | -o- |
IE | trident | -ms- |
… | … | … |
base
:
// index.css
section {
display: flex;
align-items: center;
transition:all 1s;
}
// index.js
import './asset/css/index.css'
document.getElementById('root').innerHTML = `<section>Webpack</section>`
webpack.config.js
:
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'build.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(css)$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},
]
}
- 這裏要注意
loader
的使用順序:從後向前 - 1.首先把
.css
文件利用postcss-loader
過濾 - 2.接着利用
css-loader
處理css
爲瀏覽器所能識別的文件 - 3.最後利用
style-loader
插入到瀏覽器style
標籤中 - 4.如果是
less
、stylus
、sass
,借住各自的loader
追加到postcss-loader
即可
這裏編譯會報錯:No PostCSS Config found in: W:\webpack\src\asset\css
,缺少PostCSS config
配置文件,這裏我們搭配 autoprefixer
進行配置
根目錄新建 postcss.config.js
module.exports = {
"plugins": {
"autoprefixer": {}
}
}
package.json
追加 browserslist
...
"browserslist": [
"defaults",
"not ie < 11",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
]
...
:::編譯完成
:::打開 index.html
,我們可以看到一切OK!
②:處理 JS | JSX
上面的代碼我們在 Chrome
無壓力,我們在毒瘤 IE11
中 運行試試效果
果不其然,報錯了,因爲我們在項目中使用到 ES6
提供的 模板字符串
,一些瀏覽器在ES6
發佈後沒有做出相應更新,出現不識別的情況
隨之出現babel-loader
:可以用來處理ES6語法,將其編譯爲瀏覽器可以執行的js
語法
接下來,我們安裝使用:
- 這裏要注意版本的一致性
babel-preset-es2015
落伍了,官方推薦使用babel-preset-env
install
這裏的 babel-loader 與 babel/core 版本要對應
npm i babel-loader @babel/core @babel/preset-env -D
webpack.config.js
...
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader',
options: {
include: path.join(__dirname, 'src'), // 具體到 src 更快的搜索速度
exclude: '/node_modules/', // 排除node_modules,第三方代碼已經處理,不需要二次處理
presets: '@babel/preset-env' // 將ES6 解析 爲ES5
}
},
]
...
:::編譯完成
:::然後我們在毒瘤 IE
中 運行,IE11
、IE10
、IE9
都沒有問題
因爲在IE8
中,Object.defineProperty
沒有實現,並且不讓別人訪問或修改!!!
③:處理 jpe?g
| png
| gif
| svg
install
npm i url-loader file-loader -D
base
:
// index.css
section {
display: flex;
align-items: center;
transition: all 1s;
width: 100vw;height: 100vh;
background-image: url(../img/background.jpg) // 引入背景圖
}
// index.js
import './asset/css/index.css'
import icon from './asset/img/icon.png'
// 創建img對象
let img = new Image()
img.width = 200
img.height = 200
img.src = icon
// 創建section對象
let section = document.getElementById('section')
section.appendChild(img)
section.innerHTML += '<img src="./asset/img/bj.jpg">'
// 插入
document.getElementById('root').appendChild(section)
:::這裏配置如果文件大於 10K file-loader
原路徑輸出,否則利用url-loader
打包爲base64
,從而減少http請求,但是會變大!
webpack.config.js
...
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[hash:8].[ext]', // 以原圖片名輸出
outputPath: 'images/', // 輸出路徑
publicPath:'./dist/images', // 公共路徑 預防404
limit: 10240 // 超過10K打包爲圖片,反之打包爲base64
}
}
},
]
...
我們看到效果完全一致,icon
打包爲base64
,background.jpg
原路徑輸出
:::但是,有一個問題,我們看到頁面無法顯示圖片,這張圖片,我們是直接頁面 img
src
引入的
這裏因爲html
中直接使用img
標籤src
加載圖片的話,因爲沒有被依賴,圖片將不會被打包
官方文檔,提供loader
解決類似問題 html-withimg-loader
npm i html-withimg-loader -D
wepback.config.js
追加插件
{
test: /\.(htm|html)$/i,
loader: 'html-withimg-loader'
}
④:處理 mp4
| webm
| ogg
| mp3
…
webpack.config.js
...
rules: [
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[hash:8].[ext]', // 以原文件名輸出
outputPath: 'media/', // 輸出目錄
publicPath:'./dist/media', // 公共路徑 預防404
limit: 102400
}
}
},
]
...
⑤:處理 woff2
| eot
| ttf
| otf
…
webpack.config.js
...
rules: [
{
test: /\.(woff2|eot|ttf|otf)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[hash:8].[ext]', // 以原文件名輸出
outputPath: 'font/',
publicPath:'./dist/font',
limit: 10240
}
}
}
]
...
plugins
- 介紹:用於擴展
webpack
的功能,Hook Funtion
- 作用:提高開發效率,自動化 / 工程化
①:HtmlWebpackPlugin
- 自動或依據模板生成一個
html
,動態hash
引入JS
CSS
等 - 可配置單頁面、多頁面入口
安裝:
npm i html-webpack-plugin -D
使用:
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin') // 引入
...
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack 4.X', // 文件標題
filename: 'index.html', // 文件名
template: path.resolve(__dirname, 'index.html'), // 依賴模板
inject: true, // js放置位置: true -- body 底部 | head -- head標籤 | false -- 不加載js
hash: true, // 添加hash
minify: {
collapseWhitespace: true, // 移除空格
removeAttributeQuotes: true, // 移除引號
removeComments: true // 移除註釋
}
})
]
...
index.html
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- EJS 語法引入title,配置 minify :removeComments 會移除 -->
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="root"></div>
</body>
</html>
:::構建成功
②:CleanWebpackPlugin
- 作用:清空上一次編譯結果目錄,默認dist
安裝:
npm i clean-webpack-plugin -D
使用:
webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin') // webpack 4.0 解構賦值,源碼 export { CleanWebpackPlugin }
...
plugins: [
new CleanWebpackPlugin() // 寫到第一位置,默認清除dist,可配置絕對路徑
new CleanWebpackPlugin({
dry:true, // true -- 僅僅報告要刪除的文件並不刪除 fale -- 全部刪除
cleanOnceBeforeBuildPatterns: [path.resolve(__dirname, 'test')] // 指定絕對路徑
})
]
...
③:MiniCssExtractPlugin
- 作用:抽取合併
css
,並自動添加hash
值
安裝:
npm i mini-css-extract-plugin -D
使用:
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
...
module: {
rules: [
{
test: /\.(css)$/,
use: [
MiniCssExtractPlugin.loader, // 這裏使用,style-loader插入到style標籤,這裏抽取到單獨css文件後Link引入
'css-loader',
'postcss-loader'
]
},
]
}
plugins: [
new MiniCssExtractPlugin({
filename: 'css/common.css', // 指定路徑、hash
})
]
...