上一小節我簡單介紹了 webpack 的一些用法,它的核心用法我還沒有介紹,webpack 默認只會對 js 的一些代碼進行打包,不可以對 css 樣式進行打包,或把二進制圖片打包成 data URL,熱更新
Loader
介紹
loader 用於對模塊的源代碼進行轉換。例如:typescript 轉換成 js,less 轉換爲 css 等。
使用
webpack 4.x 有三種使用 loader 的方式:
- 配置(推薦) :在 webpack.config.js 文件中指定 loader。
- 內聯 :在每個 import 語句中顯式指定 loader。
- CLI :在 shell 命令中指定它們。
注:下面我會以配置的方式爲例子,如果想了解其他兩種方式的用法可以看一下官方的文檔:https://www.webpackjs.com/concepts/loaders/
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
module: {
rules: [{
test: /\.jpg$/,
use: {
loader: 'file-loader'
}
}]
},
output: {
filename: 'main.js',
path: path.join(__dirname, 'dist'),
}
}
和上一章的代碼相比,我只添加了 module
這一項,那這個 module
是什麼意思呢?
module
中可以配置一些 loader 和 plugins 中,可以理解成 當 webpack 4.x 不知道如何打包文件時,它會在 module 配置的 規則 和 插件中尋找解決方法
loader
寫在 rules 中,rules 是一個數組,其中的每一個對象基本是需要一個 test 和 use , test 是一個正則表達式,用來匹配文件後綴名。 use 中就填寫你要使用到的 loader 名稱。
file-loader
是一個處理二進制文件,默認情況下,生成的文件的文件名就是文件內容的 MD5 哈希值並會保留所引用資源的原始擴展名。如果你不滿足於默認的文件名,你可以通過 options 中的 name 進行佔位符配置文件名,這是鏈接:https://www.webpackjs.com/loaders/file-loader/。如果你對打包生成的文件路徑不滿,可以通過 outputpath 進行配置。
和 file-loader 類似的 loader 是 url-loader ,它可以將 二進制圖片 直接轉換爲
base64
, 這個雖然可以帶來請求的減少,但同時也會增加打包文件的體積。尤其是一個很大很大的圖片的時候,這個問題尤其突出。所以最好是對文件的大小進行限制,通過 option 中的 limit (單位:byte) ,例如limit: 2048
表示 小於 2kb 則按照 url-loader 打包,超出了就會按照 file-loader 來打包。可以參見:https://www.webpackjs.com/loaders/url-loader/
打包CSS樣式表
打包 CSS 樣式表需要安裝
style-loader
、css-loader
npm i style-loader css-loader -D
webpack.config.js 文件的代碼如下:
.
.
.
module: {
rules: [
.
.
.
{
test: /\.css$/,
use: ['style-loader','css-loader'],
}
.
.
.
]
}
.
.
.
}
注意:這兩個的順序必須是
style-loader
在前,css-loader
在後,不可顛倒
- css-loader :用來解析樣式表中用到的外部引用,例如:
@import
和url()
, - style-loader : 就是將
css-loader
分享出的樣式掛載到頭部(header區域)
css-loader
有很多其他的特性,例如二次加載,模塊化css
.
.
.
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
importLoaders: 2,
modules: true,
}
],
}
.
.
.
其中 modules
表示啓動 css 模塊化,importLoaders
表示二次加載,那這個二次加載什麼意思呢?可以理解成當確保無論這麼加載都會將按照配置的loader順序加載一遍,不會缺省loader,
less、scss 的使用
使用 less 和 sass 很簡單,這裏我以 less-loader
爲例:
先安裝:
npm i less-loader less -D
webpack.config.js
.
.
.
{
test: /\.css$/,
use: ['style-loader','css-loader','less-loader'],
}
.
.
.
less-loader 的作用就是幫助我們把它翻譯成我們看得懂的 css 樣式表
學習 less-loader
配置,參見:https://www.webpackjs.com/loaders/less-loader/
學習 sass-loader
配置,參見:https://www.webpackjs.com/loaders/sass-loader/
給樣式加上廠商前綴
給樣式加上廠商前綴需要使用 postcss-loader
安裝:
npm i -D postcss-loader
使用它需要創建一個 postcss.config.js 的配置文件,配置參見:https://www.webpackjs.com/loaders/postcss-loader/
我先安裝一個 autoprefixer
的插件
npm i -D autoprefixer
postcss.config.js:
module.exports = {
plugins: [
require('autoprefixer')
]
}
webpack.config.js:
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader',
'postcss-loader'
],
},
打包字體圖片
使用字體圖片只需使用 file-loader
就行了
{
test: /\.(eot|ttf|svg)$/,
use: ['file-loader'],
},
插件
介紹
它很像 vue,react 的生命週期函數,可以在 webpack 運行到某個時刻的時候,幫你做一些事情
使用
下面我以 htmlWebapckPlugin 作爲例子:
安裝:
npm i html-webpack-plugin -D
使用:
module.exports = {
mode: 'development',
entry: './src/index.js',
//
plugins: [new HtmlWebpackPlugin({
template: 'src/template.html',
})],
// 可以使用模板進行打包
output: {
filename: 'main.js',
path: path.join(__dirname, 'dist'),
}
}
htmlWebpackPlugin 會在打包結束後,自動生成一個html文件,並把打包生成的js自動引入到這個html文件中,使用模板可以安裝你的方式進行打包
devtool
介紹
主要是當我們源代碼錯誤時,可以根據控制檯輸出的錯誤信息來定位我們到底是哪裏出錯了。這個功能很有用
可以參考:https://www.webpackjs.com/configuration/devtool/ 的表格,哪裏有很多配置項。
默認是
devtool: 'none'
,當我們在生產時一般我們使用cheap-module-eval-source-map
,線上的時候一般使用cheap-module-source-map
雖然有很多配置項,但我們還是可以總結出一些規律:
- souce-map :生成一個
.map.js
的映射文件 - inline :把
.map.js
的內容打包合併到我們輸出文件中 - cheap : 表示只提示哪一行出錯,不精確到哪一個字符,只提示業務中出現錯誤的代碼,不提示用到的第三方的錯誤的代碼
- module :會提示第三方的錯誤代碼
- eval :會用到
eval()
這種方式打包
自動監聽並保存代碼
兩種方式都要使用 package.js 文件的 script:
第一種(webpack)
"scripts": {
"build": "webpack --watch"
},
不能使用ajax
第二種(使用 webpack-dev-server 推薦)
不僅可以自動打包,還可以自動刷新瀏覽器
webpack.config.js :
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js',
},
devServer: {
contentBase: './dist',
open: true,
proxy: {
'api' : 'http://localhost:3000'
}
},
.
.
.
}
其中:
- contentBase :表示開啓服務器的路徑,默認自動打開
index.html
- open :開啓服務器時,自動打開瀏覽器
- proxy :跨域代理
配置了這些還需要在 package.json
中使用 script
添加一項:
"scripts": {
"start": "webpack-dev-server"
},
其實我們可以不配置上面的東西,僅僅借用 script
就可以實現,這種方式更簡單:
"scripts": {
"dev": "webpack-dev-server --open --port 3000 --contentBase dist"
},
爲什麼我們一定要使用服務器的方式打開文件呢?現在的項目中都會跨域使用ajax發起跨域請求。如果以 file:
的方式打開的文件是不可以發出ajax請求的,會報錯。
開啓熱更新
webpack.config.js :
module.exports = {
.
.
.
devServer: {
contentBase: './dist',
open: true,
hot: true,
hotOnly: true,
},
.
.
.
}
使用 BABLE 寫 ES6
介紹
babel 可以將 ES6 的語法轉換成 ES5 的語法
安裝
第一種:polyfill 打包業務中使用
會污染全局作用域
npm install --save-dev babel-loader @babel/core
npm install @babel/preset-env --save-dev
npm install --save @babel/polyfill
@babel/core 是一個 babel 的核心庫,就是用於語法轉換的
第二種:transform-runtime 打包庫文件中使用
以閉包的形式保護了作用域
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
npm install --save @babel/runtime-corejs2
使用
webpack.config.js:
第一種:polyfill 打包業務中使用
const path = require('path');
module.exports = {
//...
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" ,
options: {
"presets": [["@babel/preset-env",{
useBuiltIns: 'usage'
}]]
},
},
]
},
//...
}
配置完後,還要在輸入的主文件中的第一行導入 import "@babel/polyfill"
,如果配置了 useBuiltIns: 'usage'
,@babel/polyfill
會自動導入,所以可以不用導入
第二種:transform-runtime 打包庫文件中使用
const path = require('path');
module.exports = {
//...
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" ,
options: {
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false,
}
]
]
},
},
]
},
//...
}
如果你感覺 option 中的代碼比較長,可以創建一個 .babelrc
的文件,將 option 中的代碼複製到 .babelrc
中就行了,不能有註釋