1. 什麼是webpack
WebPack可以看做是模組打包機:它做的事情是,分析你的專案結構,找到JavaScript模組以及其它的一些瀏覽器不能直接執行的擴充語言(Scss,TypeScript等),並將其打包為合適的格式以供瀏覽器使用。
2. webpack核心概念
- Entry:入口,Webpack 執行構建的第一步將從 Entry 開始,可抽象成輸入。
- Module:模組,在 Webpack 裡一切皆模組,一個模組對應著一個檔案。Webpack 會從配置的 Entry 開始遞迴找出所有依賴的模組。
- Chunk:程式碼塊,一個 Chunk 由多個模組組合而成,用於程式碼合併與分割。 Loader:模組轉換器,用於把模組原內容按照需求轉換成新內容。
- Plugin:擴充套件外掛,在 Webpack 構建流程中的特定時機注入擴充套件邏輯來改變構建結果或做你想要的事情。
- Output:輸出結果,在 Webpack 經過一系列處理並得出最終想要的程式碼後輸出結果。
3. webpack執行流程
webpack啟動後會在entry裡配置的module開始遞迴解析entry所依賴的所有module,沒找到一個module, 就會根據配置的loader去找相應的轉換規則,對module進行轉換後在解析當前module所依賴的module,這些模組會以entry為分組,一個entry和所有相依賴的module也就是一個chunk,最後webpack會把所有chunk轉換成檔案輸出,在整個流程中webpack會在恰當的時機執行plugin的邏輯
4. 開始從零配置webpack
- 初始化配置
mkdir webpack-start
cd webpack-start
npm init
複製程式碼
- 配置webpack
yarn add webpack webpack-cli -D //webpack4把webpack拆分了
mkdir src cd src並且建立index.html, index.js
mkdir dist
touch webpack.config.js
複製程式碼
webpack.config.js
module.exports = {
entry: './src/index.js', //入口檔案,src下的index.js
output: {
path: path.join(__dirname, 'dist'), // 出口目錄,dist檔案
filename: '[name].[hash].js' //這裡name就是打包出來的檔名,因為是單入口,就是main,多入口下回分解
},
module: {},
plugin: {},
devServer: {}
}
複製程式碼
- 配置開發伺服器
yarn add webpack-dev-server -D
修改webpack.config.js
devServer: {
contentBase: path.join(__dirname, "dist"), //靜態檔案根目錄
port: 9090, // 埠
host: 'localhost',
overlay: true,
compress: true // 伺服器返回瀏覽器的時候是否啟動gzip壓縮
}
修改package.json
"script": {
"build": "webpack --mode development", //這裡為了不壓縮程式碼,用開發環境
"dev": "webpack-dev-server --open --mode development"
}
複製程式碼
- 支援css檔案
yarn add style-loader css-loader -D
// css-loader用來處理css中url的路徑
// style-loader可以把css檔案變成style標籤插入head中
// 多個loader是有順序要求的,從右往左寫,因為轉換的時候是從右往左轉換的
module: {
rules: {
test: /\.css$/,
use: ['style-laoder', 'css-loader'],
include: path.join(__dirname, 'src'), //限制範圍,提高打包速度
exclude: /node_modules/
}
}
複製程式碼
- 支援es6,react.js等
yarn add babel-loader babel-core babel-preset-env babel-preset-stage-0 babel-preset -react -D
{
test: /\.js$/,
use: {
loader: 'babel-loader',
query: {
presets: ['env', 'stage-0', 'react'] // env轉換es6 stage-0轉es7 react轉react
}
}
}
同時可以把babel配置寫到.babelrc中
複製程式碼
- 從js中分離css
yarn add extract-text-webpack-plugin -D
{
test: /\.css$/, // 轉換檔案的匹配正則
use: ExtractTextWebpackPlugin.extract({
fallback: 'style-loader',
//如果需要,可以在 sass-loader 之前將 resolve-url-loader 連結進來
use: ['css-loader']
})
},
//加上plugin
plugins: [
new ExtractTextWebpackPlugin({
filename: 'css/[name].[hash].css' //放到dist/css/下
})
]
複製程式碼
- 支援圖片
yarn add file-loader url-loader -D
file-loader 解決css等檔案中引入圖片路徑的問題
url-loader 當圖片較小的時候會把圖片BASE64編碼,大於limit引數的時候還是使用file-loader 進行拷貝
{
// file-loader是解析圖片地址,把圖片從原始檔拷貝到目標檔案並且修改原始檔名字
// 可以處理任意二進位制,bootstrap裡的字型
// url-loader可以在檔案比較小的時候,直接變成base64字串內嵌到頁面中
{
test: /\.(png|jpg|jpeg|gif|svg)/,
use: {
loader: 'url-loader',
options: {
outputPath: 'images/', // 圖片輸出的路徑
limit: 5 * 1024
}
}
},
// 同時要處理打包圖片路徑問題,
output: {
publicPath: '/'
}
複製程式碼
- 處理css3屬性字首
yarn add postcss-loader -D
{
test: /\.css$/, // 轉換檔案的匹配正則
// css-loader用來處理css中url的路徑
// style-loader可以把css檔案變成style標籤插入head中
// 多個loader是有順序要求的,從右往左寫,因為轉換的時候是從右往左轉換的
// 此外掛先用css-loader處理一下css檔案
use: ExtractTextWebpackPlugin.extract({
fallback: 'style-loader',
//如果需要,可以在 sass-loader 之前將 resolve-url-loader 連結進來
use: ['css-loader', 'postcss-loader']
})
},
建立.postcssrc.js檔案
module.exports = {
"plugins": {
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {
"browsers": [
"ie >= 9",
"ff >= 30",
"chrome >= 34",
"safari >= 7",
"opera >= 23"
]
}
}
}
複製程式碼
- 除錯打包的程式碼 webapck通過配置可以自動給我們source maps檔案,map檔案是一種對應編譯檔案和原始檔的方法
devtool: 'eval-source-map'
1. source-map 把對映檔案生成到單獨的檔案,最完整最慢
2. cheap-module-source-map 在一個單獨的檔案中產生一個不帶列對映的Map
3. eval-source-map 使用eval打包原始檔模組,在同一個檔案中生成完整sourcemap
4. cheap-module-eval-source-map sourcemap和打包後的JS同行顯示,沒有對映列
複製程式碼
- 壓縮js
webpack --mode production 會壓縮,可以忽略下面
yarn add uglifyjs-webpack-plugin -D
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
new UglifyjsWebpackPlugin(),
複製程式碼
- 壓縮css
webpack --mode production 會壓縮,可以忽略下面
{
test: /\.css$/, // 轉換檔案的匹配正則
use: ExtractTextWebpackPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-laoder',
options: {minimize: true}
},
'postcss-loader'
]
})
},
複製程式碼
- 清空打包輸出目錄
yarn add clean-webpack-plugin -D
const CleanWebpackPlugin = require('clean-webpack-plugin')
new CleanWebpackPlugin([path.join(__dirname, 'dist')]),
複製程式碼
- 區分環境變數 許多 library 將通過與 process.env.NODE_ENV 環境變數關聯,以決定 library 中應該引用哪些內容。我們可以使用 webpack 內建的 DefinePlugin 為所有的依賴定義這個變數:
"scripts": {
"build": "cross-env NODE_ENV=production webpack --mode development", // 設定NODE_ENV為production
"dev": "webpack-dev-server --open --mode development "
},
new webpack.DefinePlugin({
NODE_ENV:JSON.stringify(process.env.NODE_ENV)
})
在全域性都有NODE_ENV這個變數,當yarn run build,時,NODE_ENV = 'production'
複製程式碼
- 暴露全域性變數
new Webpack.ProvidePlugin({
'$': 'jquery'
}),
複製程式碼
- resolve解析
xtension: 指定extension之後可以不用在require或是import的時候加副檔名,會依次嘗試新增副檔名進行匹配
resolve: {
//自動補全字尾,注意第一個必須是空字串,字尾一定以點開頭
extension: ['', '.js', '.json', '.css']
}
alias: 配置別名可以加快webpack查詢模組的速度
resolve: {
alias: {
'bootstrap': 'bootstrap/dist/css/bootstrap.css'
}
}
複製程式碼
- 複製靜態資源
yarn add copy-webpack-plugin
const CopyWebpackPlugin = require('copy-webpack-plugin')
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, 'static'),
to: path.resolve(__dirname, 'pages/static'),
ignore: ['.*']
}
])
複製程式碼
基礎就是這些吧,程式碼優化,提高打包速度,多頁配置,我們們下回分解,詳見webpack高階配置