因專案需要,用webpack搭建一個常用功能的環境。
初步功能羅列如下:
自動配置多入口出口
less轉css
css字首自動補齊
css提取成單獨檔案
css壓縮
圖片壓縮
引入字型和svg
js Babel 壓縮
css和js的分離/合併和過濾
1.建立並且進入資料夾
mkdir webpack4.29.6 && cd webpack4.29.6
複製程式碼
2.如下圖建立各個demo檔案和圖片
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test</title>
</head>
<body>
隨便寫一些index2333
</body>
</html>
複製程式碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test</title>
</head>
<body>
隨便寫一些about2333
</body>
</html>
複製程式碼
其他的檔案可以先空著,圖片先不匯入也沒關係。
3建立package.json(以下所有命令都是在webpack4.29.6資料夾下執行)
npm init -y
複製程式碼
4.安裝以下幾個依賴
(
webpack/webpack-cli這兩個需要注意,3.x以前版本是合併在一起的,4.x後拆分了
webpack-dev-server:起服務
html-webpack-plugin:動態生成html
webpack-merge:合併webpack配置檔案
)
npm install -D webpack webpack-cli webpack-dev-server html-webpack-plugin webpack-merge
複製程式碼
確保區域性依賴和全域性依賴版本都如下圖是最新的(看清楚了,webpack是4.29.6的,如果你因為網路問題裝成3.幾的,後面將全部報錯。這步很關鍵,不然你會有無窮盡的麻煩,如果實在不成功可以先把全域性node下的webpack相關檔案刪除,window在c盤/Program Files/nodejs/下)。
5.建立三個webpack配置文字(1.common2.dev3.prod)並且分別寫入
touch webpack.common.js webpack.dev.js webpack.prod.js
複製程式碼
webpack.common.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
index: "./src/js/index.js"
},
output: {
//[name] 輸出名稱等於輸入名稱 [contenthash:8] 八位hash
filename: "[name].[contenthash:8].js",
//你應該知道的node path 知識: http://nodejs.cn/api/path.html
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
]
},
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: "./src/index.html"
})
]
};
複製程式碼
webpack.dev.js:
const merge = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "development",
//開啟除錯
devtool: "source-map",
devServer: {
//設定基本目錄結構
contentBase: "./dist",
//伺服器的IP地址,可以使用IP也可以使用localhost
host: "localhost",
//服務端壓縮是否開啟
compress: true,
//配置服務埠號
port: 8090
}
});
複製程式碼
webpack.prod.js:
const merge = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "production",
});
複製程式碼
6.修改下package.json中的script物件
"scripts": {
"dev": "webpack-dev-server --config webpack.dev.js",
"build": "rimraf dist && webpack --config webpack.prod.js"
},
複製程式碼
7.嘗試啟動服務或者打包
啟動服務:
npm run dev
複製程式碼
打包: (rimraf dist: 打包前刪除了rimraf資料夾再重新生成)
npm run build
複製程式碼
dist:
這樣便成功了第一步。因為修改了配置檔案每步都要重啟服務比較麻煩,我們這裡引入nodemon。並且新增一條命令
npm install -D nodemon
複製程式碼
// 監聽webpack.common.js檔案,有變動的話就重新啟動 npm run dev
"startdev": "nodemon --watch webpack.common.js --exec npm run dev "
複製程式碼
package.json:
開始正式配置專案常見的功能
前面打包的檔案圖片可以看到只打出了index.html,這裡看看怎麼引入多個html
webpack.common.js: 在入口增加多一個about.js和外掛多生產一個例項即可:
但是手動新增有點搓,嘗試用node遍歷自動匯入:在根目錄新建一個multi.page.js檔案:
multi.page.js:
// 多入口出口處理
const path = require("path");
const fs = require("fs");
const htmlWebpackPlugin = require("html-webpack-plugin");
const pagesPath = path.resolve("./src");
var pageList = [];
function readPages() {
fs.readdirSync(pagesPath).forEach(e => {
var fullPath = pagesPath + "/" + e;
if (e.includes("html")) {
var baseName = e.slice(0, e.indexOf("."));
pageList.push({
entry: pagesPath + "\\js\\" + baseName + ".js",
chunkName: baseName,
template: pagesPath +'\\'+ e
});
}
});
return pageList;
}
// 入口
exports.getEntryPages = function() {
return readPages().reduce((r, page) => {
r[page.chunkName] = page.entry;
return r;
}, {});
};
//出口
exports.htmlPlugins = function() {
var list = readPages().map(page => {
var options = {
filename: page.chunkName + ".html",
template: page.template,
chunks: [page.chunkName]
};
return new htmlWebpackPlugin(options);
});
return list;
};
複製程式碼
webpack.common.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const multiPage = require("./multi.page");
module.exports = {
// entry: {
// index: "./src/js/index.js",
// about: "./src/js/about.js"
// },
entry: multiPage.getEntryPages(),
output: {
//[name] 輸出名稱等於輸入名稱 [contenthash:8] 八位hash
filename: "[name].[contenthash:8].js",
//你應該知道的node path 知識: http://nodejs.cn/api/path.html
path: path.resolve(__dirname, "dist")
},
module: {
rules: []
},
plugins: [
// new HtmlWebpackPlugin({
// filename: "index.html",
// template: "./src/index.html"
// }),
// new HtmlWebpackPlugin({
// filename: "about.html",
// template: "./src/about.html"
// })
...multiPage.htmlPlugins()
]
};
複製程式碼
就是將手動引入匯出改善成nodejs自動遍歷
後面就是常見功能了,先暫時寫到webpack.common.js裡面方便除錯,最後按需切到webpack.dev.js或者webpack.prod.js
處理css(這裡我以less為例)安裝以下依賴
npm install -D css-loader style-loader less less-loader
複製程式碼
修改webpack.common.js:
module: {
rules: [
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
include: path.resolve(__dirname, "./src") // 制定路徑提升效能
}
]
},
複製程式碼
修改index.js引入index.less,並且隨意寫點樣式
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test</title>
</head>
<body>
<div class="test">
隨便寫點什麼 這裡不要自己引入css和js 全部交給webpack來處理
</div>
</body>
</html>
複製程式碼
index.js:
import index from "../css/index.less";
複製程式碼
index.less
body {
display: flex;
background: #666;
.test {
color: #ff0;
}
}
複製程式碼
就會發現相關樣式在head style 裡了
再優化一步,將style提出來
安裝依賴mini-css-extract-plugin
npm install -D mini-css-extract-plugin
複製程式碼
webpack.common.js 引進依賴、修改規則和產出,檔案總體如下
webpack.common.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const multiPage = require("./multi.page");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //提取css檔案
module.exports = {
// entry: {
// index: "./src/js/index.js",
// about: "./src/js/about.js"
// },
entry: multiPage.getEntryPages(),
output: {
//[name] 輸出名稱等於輸入名稱 [contenthash:8] 八位hash
filename: "[name].[contenthash:8].js",
//你應該知道的node path 知識: http://nodejs.cn/api/path.html
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.less$/,
// use: ["style-loader", "css-loader", "less-loader"],
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
include: path.resolve(__dirname, "./src") // 制定路徑提升效能
}
]
},
plugins: [
// new HtmlWebpackPlugin({
// filename: "index.html",
// template: "./src/index.html"
// }),
// new HtmlWebpackPlugin({
// filename: "about.html",
// template: "./src/about.html"
// })
...multiPage.htmlPlugins(),
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash:8].css"
})
]
};
複製程式碼
繼續優化將css字首自動補齊
安裝依賴:
npm install -D postcss-loader autoprefixer
複製程式碼
修改package.json:
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
複製程式碼
修改webpack.common.js:
--- use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
+++ use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
plugins: () => [require("autoprefixer")()]
}
},
"less-loader"
],
複製程式碼
最後壓縮css檔案
安裝依賴:
npm install -D optimize-css-assets-webpack-plugin
複製程式碼
修改webpack.common.js:
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano'), //用於優化\最小化CSS的CSS處理器,預設為cssnano
cssProcessorOptions: { safe: true, discardComments: { removeAll: true } }, //傳遞給cssProcessor的選項,預設為{}
canPrint: true //一個布林值,指示外掛是否可以將訊息列印到控制檯,預設為true
}),
複製程式碼
檢視一下結果 原始檔:
打包後的: 另外補充一句,看到頭部這裡莫名其妙引入了一個這個style和相關樣式,一臉懵逼還未找到問題所在。引入圖片以及對圖片進行壓縮
npm install -D css-loader file-loader html-withimg-loader image-webpack-loader
複製程式碼
webpack.common.js:
{
test: /\.(svg|png|jpe?g|gif)$/i,
use: [
{
loader: "url-loader",
options: {
limit: 1,
name: "images/[name].[contenthash:8].[ext]",
publicPath: "../"
}
},
{
loader: "image-webpack-loader",
options: {
pngquant: {
quality: "70-80",
speed: 1
}
}
}
]
},
{
test: /\.html$/,
use:[
'html-withimg-loader'
]
}
複製程式碼
引入字型
修改webpack.common.js:
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: "file-loader",
options: {
name: "assets/[name].[contenthash:8].[ext]",
publicPath: "../"
}
}
]
}
複製程式碼
babel 升級後有點小噁心..不想說了 後面再根據專案豐富css和js的提取和合並過濾