webpack配置專案
一、專案初始化
npm init -y
npm install --save-dev webpack
npm install webpack-cli -D
建立 webpack.config.js檔案 在檔案中輸入程式碼:
let path=require("path") //引用node核心模組 => 路徑
module.exports={
mode:"production", //打包後文件模式 兩種 => development production
entry:'./src/index.js', //入口檔案位置
output: {
filename:'bundle.[hash:8].js', //檔名稱
path:path.resolve(__dirname,"dist"), //打包後的檔案地址為絕對路徑 名稱為’dist'
publicPath:'' //給所有打包檔案引入時加字首,包括css、js、img,如果只想處理圖片可以單獨在url-loader配置中加publicPath
}
}
執行:
npx webpack
【可選】在package.json檔案中 ,新增指令碼程式碼如下:
"scripts":{
"build" :"webpack --config webpack.config.my.js" //可以操作重新命名後的webpack.config.js檔案
}
執行:
npm run build
二、本地服務
使用簡單的服務外掛 webpack-dev-server, 在記憶體中啟動
npm install webpack-dev-server -D
執行:
npx webpack-dev-server
[可選] 在webpack.config.js檔案中新增服務程式碼:
devServer:{ //開發伺服器配置
port:3000, //埠號
progress:true , //是否顯示進度條
contentBase:'./dist', //伺服器啟動的位置
open:true, //自動開啟瀏覽器
compress:true //gzip壓縮
hot:true //啟動熱更新
}
【可選】在package.json檔案中加入程式碼:
"scripts":{
"dev":"webpack-dev-server --open" //新增 --open 自動開啟瀏覽器
}
執行:
npm run dev
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-9tnQ7kg3-1616136915365)(C:\Users\jfq\AppData\Roaming\Typora\typora-user-images\1614309130932.png)]
此報錯解決方案:
npm uninstall -D webpack-cli
npm install -D [email protected]
三、loader
- loader 讓 webpack 能夠去處理那些非 JavaScript 檔案(webpack 自身只理解 JavaScript);
- loader 可以將所有型別的檔案轉換為 webpack 能夠處理的有效模組
在webpack.config.js檔案中配置程式碼:
module.exports = {
module: { //模組
rules: [ //規則
{ test: /\.css$/, use: 'css-loader' }
]
}
};
推薦使用yarn 進行安裝
3.1 處理CSS
包括css less sass 必須在js檔案中匯入 import ‘.css’
3.1.1 處理css檔案
1、安裝 style-loader css-loader 模組
npm install style-loader css-loader -D
2、在webpack.config.js檔案中配置程式碼:
//css-loader 用來解析@import這種語法
//style-loader 用來把css插入 header 標籤中
//loader的執行順序:預設是從右向左,從下向上
module.exports={
module:{
rules:[
//{test:/\.css$/,use:['style-loader','css-loader']} //use可以寫成string array object
{
test:/\.css$/,
use:[{
loader:"style-loader",
options:{
insertAt:"top" //將css放到body上面;1.0版本已經放棄;現在不使用
}
},
"css-loader"
]
}
]
}
}
3.1.2 處理less檔案
1、安裝 style-loader css-loader less-loader 模組 和 less 模組
npm install style-loader css-loader less-loader -D
2、在webpack.config.js檔案中配置程式碼:
module.exports={
module:{
rules:[
{
test:/\.less$/,
use:[
{
loader:"style-loader",
},
"css-loader",
"less-loader"
]
}
]
}
}
3.1.3 處理sass檔案
- 安裝style-loader css-loader sass-loader 模組 和 sass 模組
- 用法跟less一樣;
3.1.4 css相容處理
1、安裝 “postcss-loader autoprefixer” 模組
yarn add postcss-loader autoprefixer -D
2、postcss 需要配置文件 postcss.config.js
module.exports = {
plugins: {
// 相容瀏覽器,新增字首
'autoprefixer':{
overrideBrowserslist: [
"Android 4.1",
"iOS 7.1",
"Chrome > 31",
"ff > 31",
"ie >= 8"
//'last 10 versions', // 所有主流瀏覽器最近10版本用
],
grid: true
}
}
}
3、在 “webpack.config.js”檔案中新增配置:
// css
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
}
// less
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'less-loader'
]
},
3.2 處理JS
3.2.1 ESLint語法檢測
npm install eslint-config-airbnb-base eslint-plugin-import eslint eslint-loader -D
webpack.config.js中配置
/*
eslint語法檢查:eslint-loader eslint
注意:只檢查自己的js程式碼,第三方的庫是不用檢查的
設定檢查規則:
packag.json中eslintConfig中設定~
"eslintConfig":{
"extends":"airbnb-base"
}
aribnb --> eslint-config-airbnb-base eslint-plugin-import eslint
*/
{
test:/\.js$/,
exclude:/node_modules/,
loader: 'eslint-loader',
options:{
fix:true//eslint自動修復格式錯誤
}
}
3.在package.json中配置eslintConfig
"eslintConfig": {
"extends": "airbnb-base"
}
4.如果配置完成後,打包時出現Resolve error: unable to load resolver “node” src\main.js:1:1 錯誤,請安裝下面的依賴後再打包
npm install eslint-import-resolver-node -D
3.2.2 JS相容處理
因為es6語法不相容部分瀏覽器,所以要對專案進行配置
1.安裝依賴
npm install babel-loader @babel/preset-env @babel/core core-js -D //第一三方法安裝這個
npm install @babel/polyfill -D //第二個方法安裝這個
2.三種方法相容
(1)babel-loader @babel/preset-env @babel/core 相容
只能相容基本的語法,但是像是promise語法,無法進行相容
(2)相容全部js語法 @babel/polyfill
在index.js中引入依賴即可
import ‘@babel/polyfill’
缺點:全部相容造成打包檔案太大
(3)core-js 配合第一種進行按需相容
3.配置詳情(下面是將eslint檢查與js相容配置放在了一起,module中不可以對.js檔案(同一種檔案)進行多次匹配,多次匹配只會匹配第一個,所以要結合在一起)
{
test:/\.js$/,
exclude:/node_modules/,
use:[
//要優先執行eslint-loader,可使用配置enforce:'pre'
{
loader: 'eslint-loader',
options:{
fix:true //eslint自動修復格式錯誤
}
},
//js相容性處理:babel-loader @babel/preset-env @babel/core
{
loader: 'babel-loader',
options:{
//預設:指示babel做怎麼樣的相容性處理
presets:[
[
'@babel/preset-env',
{
// 按需載入
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定相容瀏覽器版本範圍
targets: {
chrome: '70', // 谷歌版本70及以上
firefox: '62',
ie: '9',
safari: '10',
edge: '17',
}
}
]
]
}
}
]
},
所以一般採用第一種加第三種組合進行.js檔案相容,也就是上面貼的程式碼。
第二種具體引入方式如下,不建議使用
{
test:/\.js$/,
exclude:/node_modules/,
loader:'babel-loader',
options:{
presets:['@babel/preset-env']
}
}
3.3 處理其他檔案
3.2.1 處理路徑
- 安裝 file-loader 外掛 可以處理 圖片、字型等
npm install --save-dev file-loader
- 在webpack.config.js檔案中新增程式碼配置:
module.exports = {
module: {
rules: [
{
test: /\.(png|svg|jpg|gif)$/, //影象的格式,也可以判斷字型檔案/\.(woff|woff2|eot|ttf|otf)$/
use: [
'file-loader'
]
}
]
}
};
*解析html
中的img
如
yarn add html-loader -D
{
test: /\.html$/,
use: 'html-loader'
}
3.2.2 當圖片小於多少,用base64編碼
yarn add url-loader -D
//如果過大,才用file-loader
{
test: /\.(png|jpg|gif)$/,
// 當圖片小於多少,用base64,否則用file-loader產生真實的圖片
use: {
loader: 'url-loader',
options: {
limit: 200 * 1024, // 小於200k變成base64
}
}
}
3.2.3 打包分類
1.圖片分類
{
test: /\.(png|jpg|gif)$/,
// 當圖片小於多少,用base64,否則用file-loader產生真實的圖片
use: {
loader: 'url-loader',
options: {
limit: 1, // 200k 200 * 1024
outputPath: 'img/' // 打包後輸出地址 在dist/img
}
}
},
2.css分類
plugins: [
new MiniCssExtractPlugin({
filename: 'css/main.css'
}),
]
3.希望輸出的時候,給這些css、img
加上字首,傳到伺服器也能訪問:
output: {
filename: 'bundle.[hash:8].js', // [hash:8] 只顯示8位hash
path: path.resolve(__dirname, 'dist'),
publicPath: 'http://www.mayufo.cn' // 給靜態資源統一加
},
如果只處理圖片路徑:
{
test: /\.(png|jpg|gif)$/,
// 當圖片小於多少,用base64,否則用file-loader產生真實的圖片
use: {
loader: 'url-loader',
options: {
limit: 1, // 200k 200 * 1024
outputPath: '/img/', // 打包後輸出地址
publicPath: 'http://www.mayufo.cn'
}
}
}
四、外掛[plugins]
4.1html-webpack-plugin
使用‘html-webpack-plugin’外掛自定義打包html檔案
npm install html-webpack-plugin -D
在webpack.config.js檔案中,新增配置程式碼:
const htmlWebpackPlugin = require('html-webpack-plugin') //引入外掛
plugins:[ //放置所有的webpack外掛
new htmlWebpackPlugin({ //用於使用模板打包時生成檔案
template:'', //模板檔案
filename:'', //打包後生成的檔案
hash:true, //新增hash值解決快取問題
minify:{
removeAttributeQuotes:true, //刪除屬性雙引號
collapseWhitespace:true //摺疊空行變為一行
}
})
]
4.2 mini-css-extract-plugin
抽離css樣式,成單獨檔案
npm install mini-css-extract-plugin -D
在webpack.config.js中配置:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// 壓縮css
module.exports={
plugins: [
new MiniCssExtractPlugin({
filename: 'css/main.css' //輸出檔名
})
],
module:{
rules:[
{
test: /\.css$/, // css 處理
use: [
// {
// loader: 'style-loader',
// },
// 此時不需要style-loader
MiniCssExtractPlugin.loader, // 抽離
'css-loader', // css-loader 用來解析@import這種語法,
'postcss-loader'
]
}
]
}
}
4.3 壓縮css,js程式碼
yarn add optimize-css-assets-webpack-plugin -D
yarn add uglifyjs-webpack-plugin -D
2、在webpack.config.js檔案中配置程式碼:
// 用了`mini-css-extract-plugin`抽離css為link需使用`optimize-css-assets-webpack-plugin`進行壓縮css,使用此方法壓縮了css需要`uglifyjs-webpack-plugin`壓縮js
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin") //壓縮css
const UglifyJsPlugin = require("uglifyjs-webpack-plugin") //壓縮js
module.exports = {
optimization: { // 優化項
minimizer: [
new UglifyJsPlugin({ // 優化js
cache: true, // 是否快取
parallel: true, // 是否併發打包
// sourceMap: true // 原始碼對映 set to true if you want JS source maps
}),
new OptimizeCSSAssetsPlugin({}) // css 的優化
]
},
mode: 'production',
entry: '',
output: {},
}
五、配置優化項
5.1 模組熱更新(HMR)
只存在於開發環境,哪塊更新只更新那塊
- 配置熱更新,在devServer中配置hot,開啟HMR功能
devServer:{
contentBase: resolve(__dirname,'build'),//自動構建目錄,打包後的資料夾
compress:true,
port:3000,
open:true,
hot:true //開啟熱更新
}
此時樣式檔案已經可以實現熱更新,因為style-loader內部實現了,但是js和html檔案會出現問題。
(1)解決html檔案問題,將entry改為陣列,引入index.html檔案,
html檔案:預設不能使用HMR功能,同時會導致問題:html檔案不能熱更新(不用做HMR功能)
entry:['./src/index.js','./src/index.html'],
(2)解決js檔案問題,配置js檔案
js檔案:預設不能使用HMR功能 --需要修改js程式碼,新增支援,入口js檔案是沒法處理的,這裡處理非入口的print.js檔案
import print from './print'
print();
if(module.hot){
//一旦 module.hot 為true,說明開啟了HMR功能。 -->讓HMR功能程式碼失效
module.hot.accept('./print.js',function(){
//方法會監聽 print.js檔案變化,一旦發生變化,其他模組不會重新打包構建。
//會執行後面的回撥函式
print();
})
}
5.2除錯工具(devtool)
利於程式碼除錯,顯示報錯準確行數;
devtool: 'source-map' //cheap-module-souce-map
引數介紹
/**
* source-map :一種提供原始碼到構建後代碼的對映技術(如果構建後代碼出錯,可以通過對映追蹤原始碼錯誤)
* [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
*
* source-map:外部
* 錯誤程式碼準確資訊 和 原始碼的錯誤位置
* inline-source-map:內聯
* 錯誤程式碼準確資訊 和 原始碼的錯誤位置
* 只生成一個內聯source-map
* hidden-source-map:外部
* 錯誤程式碼的錯誤原因,但是沒有錯誤位置
* 不能追蹤原始碼錯誤,只能提示到構建後代碼的錯誤位置
* eval-source-map:內聯
* 每個檔案都生成對應的source-map,都在eval
* 錯誤程式碼準確資訊 和 原始碼的錯誤位置
* nosources-source-map:外部
* 能找到錯誤程式碼的準確資訊,但是沒有任何原始碼資訊
* cheap-source-map:外部
* 提示錯誤資訊,和原始碼的錯誤位置,但是隻能精確到某一行
* cheap-module-source-map
* 錯誤程式碼準確資訊 和 原始碼的錯誤位置
* module會將loader的source map加入
*
* 內聯 和 外部的區別:1.外部生成了檔案,內聯沒有 2.內聯構建速度更快
*
* 開發環境:速度快,除錯更友好
* 速度快(eval>inline>cheap>...)
* eval-cheap-source-map
* eval-source-map
* 除錯更友好
* souce-map
* cheap-module-source-map
* cheap-source-map
*
* --> eval-source-map 除錯更友好/ eval-cheap-module-source-map 效能更好
*
* 生產環境:原始碼要不要隱藏?除錯要不要更友好
* 內聯會讓程式碼體積變的非常大,所以在生產環境中不使用內聯
* nosources-source-map 程式碼全部隱藏
* hidden-source-map 只隱藏原始碼,會提示構建後代碼錯誤資訊
*
* -->source-map / cheap-module-souce-map
*/
react專案中devtool配置如下
devtool: isEnvProduction
? shouldUseSourceMap
? 'source-map'
: false
: isEnvDevelopment && 'cheap-module-source-map',
5.3 提高匹配效率 oneOf
提高loader匹配效率,使用方法如下,匹配到一個loader後,後面的就不會再繼續匹配了。
注意:不能有兩個配置處理同一種類型檔案
module:{
rules:[
{
test:/\.js$/,
exclude:/node_modules/,
// //優先執行
enforce:'pre',
loader:'eslint-loader',
options:{
fix:true
}
},
{
//下面的loader只會匹配一個,處理效能更好
//注意:不能有兩個配置處理同一種類型檔案
oneOf:[
{
test:/\.css$/,
use:[...commenCssLoader]
},
{
test:/\.less$/,
use:[...commenCssLoader,'less-loader']
},
]
}
]
},
5.4 babel快取
不用重新載入所有的檔案,使用者第二次進入頁面的時候直接讀取快取
- 在匹配.js檔案的loader中寫入配置cacheDirectory
{
test:/\.js$/,
exclude:/node_modules/,
loader:'babel-loader',
options:{
presets:[
[
'@babel/preset-env',
{
useBuiltIns:'usage',
corejs:{version:3},
targets:{
chrome:'70',
firefox:'62',
ie:'9',
safari:'10',
edge:'17',
}
}
]
],
//開啟babel快取
//第二次構建時,會讀取之前的快取
cacheDirectory:true
}
},
- 給輸出的js檔案還有css檔案設定打包輸出名稱
output:{
filename:'js/build.[contenthash:10].js',
path:resolve(__dirname,'build')
},
new MiniCssExtractPlugin({
filename:'css/build.[contenthash:10].css'
}),
配置詳情
/**
* babel快取
* cacheDirectory:true
* 檔案資源快取
* hash:每次webpack構建時會生成一個唯一的hash值。
* 問題:因為js和css同時使用一個hash值。
* 如果重新打包,會導致所有快取失效。(可能只改變了一個檔案)
* chunkhash:根據chunk生成的hash值。如果打包來源於同一個chunk,那麼hash值就一樣
* 問題:js和css的hash值還是一樣的。因為css是在js中被引用的,兩個同屬一個chunk
* contenthash: 根據檔案的內容生成hash值。不同檔案hash值一定不一樣
*/
5.5 tree shaking(樹搖)
去除無用程式碼(未使用的程式碼)
自動開啟條件:
- 必須使用es6模組化。
- 開啟mode:production環境。
- 在package.json中配置sideEffects
/**
* tree shaking(樹搖):
* 去除無用程式碼(未使用的程式碼)
* 自動開啟條件:1.必須使用es6模組化。2.開啟mode:production環境。
* 作用:減少程式碼體積
*
* 在package.json中配置
* "sideEffects":false 所有程式碼都沒有副作用 (都可以進行tree shaking)
* 問題:可能會把css/ @babel/polyfill (副作用)檔案幹掉
* 解決:
* "sideEffects":["*.css"]
*/
六、打包多頁應用
// 多入口
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
home: './src/index.js',
other: './src/other.js'
},
output: {
filename: "[name].js",
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'home.html',
chunks: ['home']
}),
new HtmlWebpackPlugin({
template: './index.html',
filename: 'other.html',
chunks: ['other', 'home'] // other.html 裡面有 other.js & home.js
}),
]
}