此專案主要來學習配置各種前端使用到的各種檔案格式,順便記錄起來,方便之後查閱。
我們使用babel來編譯一些高版本的JS,例如:ES6,ES7等...
先讓我們安裝babel套件
npm i @babel/core @babel/preset-env babel-loader -D
接著在js module部分新增babel-loader
{
test: /\.js$/,
use:['babel-loader'],
},
在babel編譯讀取時,會依照設定檔.babelrc裡面的設定進行編譯,下面的presets設定是指要使用哪種語言特性,我這邊是選擇目前所有ES標準裡的最新特性。
{
"presets": ["@babel/preset-env"]
}
可以至babel官網查看presets的各種設定。
我們需要安裝在node環境下能夠編譯scss的套件以及將scss轉成css的套件
npm i -D node-sass sass-loader
轉成css後我們還需要安裝css-loader來將css程式中的@import和url()的匯入敘述,告訴webpack依賴這些資源。
接著再使用style-loader將css程式轉換成字串,植入JS程式中,透過JS在DOM增加樣式。
當然我們也可以使用ExtractTextPlugin將css檔案獨立出來,這個我們稍後再來說明。
npm i -D css-loader style-loader
{
test: /\.(scss|sass)$/,
use:[
'style-loader',
'css-loader',
'sass-loader'
]
}
在webpack loaders中的use執行順序是由最後面執行到最前面,也就是sass-loader最先開始執行。
有一些css在某些瀏覽器可能沒有支援,那我們要怎麼讓瀏覽器保持相容性呢?
我們需要添加字首-webkit -ms..等等, 但添加這些字首是非常費時的。
所幸有一個工具能夠幫我們解決這問題,甚至可以用css最新的語法,那就是PostCSS !
使用PostCSS時,我們必須先建立一個設定檔postcss.config.js
//postcss.config.js
module.exports = {
plugins:[
require('autoprefixer')
]
}
// package.json 物件添加,代表所要兼容的瀏覽器資訊
"browserslist": [
"last 5 version",
"> 1%",
"ie >= 10",
"ios >= 8"
]
上面我使用了自動添加瀏覽器兼容的字首之後,我們需要在上面的loader新增postcss-loader
{
test: /\.(scss|sass)$/,
use:[
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader'
]
}
postcss-loader必須在css-loader解析之前執行,否則會無效。
在網站中我們總是無法避免會使用圖檔的部分。
那在css或js中引入圖檔時,我們要怎麼去讓webpack載入資源呢?
使用file-loader就能夠解決這個問題
npm i -D file-loader
{
test: /\.(png|svg|jpg)$/,
use:[
{
loader:'file-loader',
options:{
name: '[path][name].[ext]?[hash:8]'
}
}
]
}
載入圖片我們也可以使用url-loader去進行加載,若圖片體積不大則我們可以進行base64編碼來載入圖片。
優點是可以減少請求但若圖片體積過大使得編碼過大的話,則在打包時會使js檔變得太大,可能會導致加載時間更長。
所以通常我們會設置limit來判斷是否要進行base64編碼轉換,若沒有進行base64的圖片則是經過file-loader去載入資源。
npm i -D url-loader
{
test:/\.(png|svg|jpg)$/,
use:[
{
loader:'url-loader',
options:{
limit:50000,
name:'[path][name].[ext]?[hash:8]'
}
},
]
}
那怎麼進行圖片壓縮呢?
我們使用image-webpack-loader這個來進行壓縮
npm i -D image-webpack-loader
一樣在剛剛的use中使用,我們會先對圖片進行壓縮,才會去判斷是否要將圖片轉成base64
{
test:/\.(png|svg|jpg)$/,
use:[
{
loader:'url-loader',
options:{
limit:50000,
name:'[path][name].[ext]?[hash:8]'
}
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: '65-90',
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
}
]
}
上面所設定的壓縮部分可以參考image-webpack-loader的npm,在這就不進行詳細說明。
我們在開發時有時會有一些檔案是不需要經過loader就能夠使用的,我們所需要做的就是將該檔案移至打包後的檔案就可,那我們需要怎麼做呢?
CopyWebpackPlugin可以解決我們這個需求
npm i -D copy-webpack-plugin
安裝後我們來看要怎麼使用
var CopyWebpackPlugin = require('copy-webpack-plugin')
plugins:[
new CopyWebpackPlugin([
{from : 'assets', to: 'assets' }
])
]
首先我們必須先載入額外的CopyWebpackPlugin模組,接著在webpack.config.js中的plugins添加該模組。
在CopyWebpackPlugin中我們定義了 {from : 'assets', to: 'assets' } 這個物件,該物件的意思是我們從開發中的assets資料夾移至打包後的assets資料夾,這樣就完成了我們複製資料的功能了。
雖然現代開發網頁已經很少使用jQuery了,我們在這邊使用jQuery只是做為一個範例,你可以透過該種方式去引入你想要的套件。
但不太推薦將套件引入至全域,因為可能會有不避要的衝突,除非真的有需要。
我們透過webpack原本就提供的ProvidePlugin來實現全域引入的方式。
首先先下載jQeury
npm i --save jquery
接著引入ProvidePlugin模組
var webpack = require('webpack')
plugins:[
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'Window.jQuery': 'jquery'
})
]
// index.js
$('#test').text('hello')
我們在ProvidePlugin中定義了$,jQuery,Window.jQuery,這三個名稱,指的是我們可以在全域中使用這三個名稱來呼叫jquery。
此時你可以在自己的js檔中使用jQuery而不用再使用import方式去載入。
假如你的專案是使用多頁面的方式來進行開發,這樣可能有遇過一個問題就是有共用的JS檔時或者meta,title之類的名稱時,你都要手動去添加在各個html上,但webpack有提供一個套件能夠讓我們解決這個問題並且將打包後的JS可以自動注入JS當中。
npm i -D webpack-html-plugin
var HtmlWebpackPlugin = require('html-webpack-plugin');
plugins:[
new HtmlWebpackPlugin({
title: 'webpack練習',
filename: 'index.html',
template:'html/index.html',
chunks:['index']
}),
]
首先必須先引用html-webpack-plugin這個套件並在plugins中使用。
我們添加了幾個參數:
- title : 提供html使用的動態變數
- filename: 我們輸出後的檔案名稱
- template: 我們要套用的html
- chunks: 動態添加的JS檔
接著來看我們要套用的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><%=htmlWebpackPlugin.options.title%></title>
</head>
<body>
<div id="app"></div>
</body>
</html>
<%=htmlWebpackPlugin.options.title%>就是對應到我們在plugins有使用到的title參數,另一個要注意的點就是我們在這邊並未手動輸入打包後的JS檔。
至於要多頁面設定的話可以複製多個HtmlWebpackPlugin設定。
當webpack在處理loader時會在全部的資料夾進行搜索要編譯的相關檔名。
但我要編譯scss時�,並不需要再跑到其他資料夾進行搜索,因為我已經將所有scss放到scss這個資料夾了,這時再跑去其他資料夾進行搜索會耗很多打包時間。
有兩個參數可以使用:
include: 只有在包含該路徑中的檔案才會進行搜索。
exclude: 搜索時排除該路徑的所有檔案。
{
test: /\.(scss|sass)$/,
use: extractCSS.extract(['css-loader','postcss-loader']),
include: path.resolve('src/scss'),
exclude: path.resolve('node_modules')
},
註: 官方建議避免使用exclude,傾向只使用include。
我們在開發模式時修改JS完畢後儲存,webpack會偵測是否有改變然後再進行編譯。
但有時我們只是小小的改動JS而已但編譯時間還是很長,這是因為我們在打包時連同node_modules裝的那些套件一起打包了。但重點是這些套件我們不需要每次都進行打包呀,除非它有變動。
為了加快我們每次編譯的速度,我們必須將node_modules套件抽出來打包至名為vendor.js的檔案中。
optimization:{
splitChunks:{
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendeor',
chunks:'initial',
enforce:true
}
}
}
},
官方有提供我們這個方法來對node_modules的套件進行打包。這樣我們就解決的開發時編譯很慢的問題,要記得在我們先前提到的HtmlWebpackPlugin的chunks添加vendor路徑。
我在使用vue時通常會使用CDN或者是vue cli 來建構vue的專案,但突然有一天很好奇vue是怎麼用webpack建構出開發環境的,所以就有了這個主題,接下來來介紹如何使用webpack建構出vue環境。
先載入vue所需要的loader以及解析template。
npm i -D vue-loader vue-template-compiler vue-html-loader vue-style-loader
接著在載入vue:
npm i -S vue
接著在src資料夾中新增App.vue與index.js
// index.js
import Vue from 'vue'
import App from 'App.vue'
new Vue({
'el':'#app',
render:(h)=> h(App)
})
// App.vue
<template>
<div id="test">{{data}}</div>
</template>
<script>
export default{
data(){
return{
data: 'hello'
}
}
}
</script>
<style lang="scss" scoped>
#test{
color:red;
}
</style>
記得在輸出的html新增id = app的DOM。
接著我們需要設定webpack,我們僅需要讓webpack認識.vue檔案以及新增一個plugins即可完成vue環境。
//webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module:{
rules:[
{
test: /\.vue$/,
loader: 'vue-loader'
},
]
},
plugins:[
new VueLoaderPlugin()
]
其實這樣我們的vue就已經建構好了,是不是比想像中簡單呢?